summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-08-10 11:37:26 -0400
committerGitHub <noreply@github.com>2022-08-10 11:37:26 -0400
commitfcdb4629c4c3dd2931eaa88b96b668d914c4519c (patch)
treec54c0b9c6411f9be55b9a2816e528b91d6032703
parent1378fffd9da094beb41b2db89b96f556c23ab6cb (diff)
Yet more refactoring around Artifact (#2352)
* #include an absolute path didn't work - because paths were taken to always be relative. * WIP with hierarchical enums. * Some small fixes and improvements around artifact desc related types. * Improvements around hierarchical enum. * Fixes to get Artifact types refactor to be able to execute tests. * Attempt to better categorize PTX. * Work around for potentially unused function warning. * Typo fix. * Simplify Artifact header. * Small improvements around Artifact kind/payload/style. * Added IDestroyable/ICastable * Add IArtifactList. * First impl of IArtifactUtil. * Use the ICastable interface for IArtifactRepresentation. * Added IArtifactRepresentation & IArtifactAssociated. * Add SLANG_OVERRIDE to avoid gcc/clang warning. * Fix calling convention issue on win32. * Fix missing SLANG_OVERRIDE. * First attempt at file abstraction around Artifact. * Added creation of lock file. * Move functionality for determining file paths to the IArtifactUtil. Add casting to ICastable. * Added some casting/finding mechanisms. * Simplify IArtifact interface, and use Items for file reps. * Fix problem with libraries on DXIL. * Split out ArtifactRepresentation. * Move ArtifactDesc functionality to ArtifactDescUtil. ArtifactInfoUtil becomes ArtifactDescUtil. * Split implementations from the interfaces for Artifact. * Use TypeTextUtil for target name outputting. * Add artifact impls. * Add ICastableList * Added UnknownCastableAdapter * Make ISlangSharedLibrary derive from ICastable, and remain backwards compatible with slang-llvm. * Refactor Representation on Artifact. * Make our ISlangBlobs also derive from ICastable. Make ISlangBlob atomic ref counted. * Split out CastableList and related types, and placed in core. * Small fixes around IArtifact. Improve IArtifact docs. First impl of getChildren for IArtifact. * Documentation improvements for Artifact related types. * Fix typo. * Special case adding a ICastableList to a LazyCastableList. * Small simplification of LazyCastableList, by adding State member. * Removed the ILockFile interface because IFileArtifactRepresentation can be used.
-rw-r--r--build/visual-studio/core/core.vcxproj5
-rw-r--r--build/visual-studio/core/core.vcxproj.filters15
-rw-r--r--build/visual-studio/slang-rt/slang-rt.vcxproj5
-rw-r--r--build/visual-studio/slang-rt/slang-rt.vcxproj.filters15
-rw-r--r--source/compiler-core/slang-artifact-desc-util.cpp6
-rw-r--r--source/compiler-core/slang-artifact-impl.cpp386
-rw-r--r--source/compiler-core/slang-artifact-impl.h98
-rw-r--r--source/compiler-core/slang-artifact-representation-impl.cpp60
-rw-r--r--source/compiler-core/slang-artifact-representation-impl.h46
-rw-r--r--source/compiler-core/slang-artifact-representation.h27
-rw-r--r--source/compiler-core/slang-artifact-util.cpp48
-rw-r--r--source/compiler-core/slang-artifact-util.h8
-rw-r--r--source/compiler-core/slang-artifact.h81
-rw-r--r--source/core/slang-castable-list-impl.cpp178
-rw-r--r--source/core/slang-castable-list-impl.h83
-rw-r--r--source/core/slang-castable-list.h57
-rw-r--r--source/core/slang-destroyable.h9
-rw-r--r--source/core/slang-lazy-castable-list.cpp163
-rw-r--r--source/core/slang-lazy-castable-list.h66
19 files changed, 712 insertions, 644 deletions
diff --git a/build/visual-studio/core/core.vcxproj b/build/visual-studio/core/core.vcxproj
index c4a28f94b..13e933326 100644
--- a/build/visual-studio/core/core.vcxproj
+++ b/build/visual-studio/core/core.vcxproj
@@ -281,6 +281,8 @@
<ClInclude Include="..\..\..\source\core\slang-basic.h" />
<ClInclude Include="..\..\..\source\core\slang-blob.h" />
<ClInclude Include="..\..\..\source\core\slang-byte-encode-util.h" />
+ <ClInclude Include="..\..\..\source\core\slang-castable-list-impl.h" />
+ <ClInclude Include="..\..\..\source\core\slang-castable-list.h" />
<ClInclude Include="..\..\..\source\core\slang-char-encode.h" />
<ClInclude Include="..\..\..\source\core\slang-char-util.h" />
<ClInclude Include="..\..\..\source\core\slang-chunked-list.h" />
@@ -299,6 +301,7 @@
<ClInclude Include="..\..\..\source\core\slang-hex-dump-util.h" />
<ClInclude Include="..\..\..\source\core\slang-http.h" />
<ClInclude Include="..\..\..\source\core\slang-io.h" />
+ <ClInclude Include="..\..\..\source\core\slang-lazy-castable-list.h" />
<ClInclude Include="..\..\..\source\core\slang-linked-list.h" />
<ClInclude Include="..\..\..\source\core\slang-list.h" />
<ClInclude Include="..\..\..\source\core\slang-lz4-compression-system.h" />
@@ -342,6 +345,7 @@
<ClCompile Include="..\..\..\source\core\slang-archive-file-system.cpp" />
<ClCompile Include="..\..\..\source\core\slang-blob.cpp" />
<ClCompile Include="..\..\..\source\core\slang-byte-encode-util.cpp" />
+ <ClCompile Include="..\..\..\source\core\slang-castable-list-impl.cpp" />
<ClCompile Include="..\..\..\source\core\slang-char-encode.cpp" />
<ClCompile Include="..\..\..\source\core\slang-char-util.cpp" />
<ClCompile Include="..\..\..\source\core\slang-command-line.cpp" />
@@ -351,6 +355,7 @@
<ClCompile Include="..\..\..\source\core\slang-hex-dump-util.cpp" />
<ClCompile Include="..\..\..\source\core\slang-http.cpp" />
<ClCompile Include="..\..\..\source\core\slang-io.cpp" />
+ <ClCompile Include="..\..\..\source\core\slang-lazy-castable-list.cpp" />
<ClCompile Include="..\..\..\source\core\slang-lz4-compression-system.cpp" />
<ClCompile Include="..\..\..\source\core\slang-memory-arena.cpp" />
<ClCompile Include="..\..\..\source\core\slang-offset-container.cpp" />
diff --git a/build/visual-studio/core/core.vcxproj.filters b/build/visual-studio/core/core.vcxproj.filters
index 91a852b8e..3d394caa8 100644
--- a/build/visual-studio/core/core.vcxproj.filters
+++ b/build/visual-studio/core/core.vcxproj.filters
@@ -30,6 +30,12 @@
<ClInclude Include="..\..\..\source\core\slang-byte-encode-util.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-castable-list-impl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-castable-list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-char-encode.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -84,6 +90,9 @@
<ClInclude Include="..\..\..\source\core\slang-io.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-lazy-castable-list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-linked-list.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -209,6 +218,9 @@
<ClCompile Include="..\..\..\source\core\slang-byte-encode-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\core\slang-castable-list-impl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\core\slang-char-encode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -236,6 +248,9 @@
<ClCompile Include="..\..\..\source\core\slang-io.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\core\slang-lazy-castable-list.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\core\slang-lz4-compression-system.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/build/visual-studio/slang-rt/slang-rt.vcxproj b/build/visual-studio/slang-rt/slang-rt.vcxproj
index 723f5360e..1c1190be2 100644
--- a/build/visual-studio/slang-rt/slang-rt.vcxproj
+++ b/build/visual-studio/slang-rt/slang-rt.vcxproj
@@ -281,6 +281,8 @@
<ClInclude Include="..\..\..\source\core\slang-basic.h" />
<ClInclude Include="..\..\..\source\core\slang-blob.h" />
<ClInclude Include="..\..\..\source\core\slang-byte-encode-util.h" />
+ <ClInclude Include="..\..\..\source\core\slang-castable-list-impl.h" />
+ <ClInclude Include="..\..\..\source\core\slang-castable-list.h" />
<ClInclude Include="..\..\..\source\core\slang-char-encode.h" />
<ClInclude Include="..\..\..\source\core\slang-char-util.h" />
<ClInclude Include="..\..\..\source\core\slang-chunked-list.h" />
@@ -299,6 +301,7 @@
<ClInclude Include="..\..\..\source\core\slang-hex-dump-util.h" />
<ClInclude Include="..\..\..\source\core\slang-http.h" />
<ClInclude Include="..\..\..\source\core\slang-io.h" />
+ <ClInclude Include="..\..\..\source\core\slang-lazy-castable-list.h" />
<ClInclude Include="..\..\..\source\core\slang-linked-list.h" />
<ClInclude Include="..\..\..\source\core\slang-list.h" />
<ClInclude Include="..\..\..\source\core\slang-lz4-compression-system.h" />
@@ -343,6 +346,7 @@
<ClCompile Include="..\..\..\source\core\slang-archive-file-system.cpp" />
<ClCompile Include="..\..\..\source\core\slang-blob.cpp" />
<ClCompile Include="..\..\..\source\core\slang-byte-encode-util.cpp" />
+ <ClCompile Include="..\..\..\source\core\slang-castable-list-impl.cpp" />
<ClCompile Include="..\..\..\source\core\slang-char-encode.cpp" />
<ClCompile Include="..\..\..\source\core\slang-char-util.cpp" />
<ClCompile Include="..\..\..\source\core\slang-command-line.cpp" />
@@ -352,6 +356,7 @@
<ClCompile Include="..\..\..\source\core\slang-hex-dump-util.cpp" />
<ClCompile Include="..\..\..\source\core\slang-http.cpp" />
<ClCompile Include="..\..\..\source\core\slang-io.cpp" />
+ <ClCompile Include="..\..\..\source\core\slang-lazy-castable-list.cpp" />
<ClCompile Include="..\..\..\source\core\slang-lz4-compression-system.cpp" />
<ClCompile Include="..\..\..\source\core\slang-memory-arena.cpp" />
<ClCompile Include="..\..\..\source\core\slang-offset-container.cpp" />
diff --git a/build/visual-studio/slang-rt/slang-rt.vcxproj.filters b/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
index 68fc24316..65952c3e7 100644
--- a/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
+++ b/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
@@ -30,6 +30,12 @@
<ClInclude Include="..\..\..\source\core\slang-byte-encode-util.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-castable-list-impl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-castable-list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-char-encode.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -84,6 +90,9 @@
<ClInclude Include="..\..\..\source\core\slang-io.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-lazy-castable-list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-linked-list.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -212,6 +221,9 @@
<ClCompile Include="..\..\..\source\core\slang-byte-encode-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\core\slang-castable-list-impl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\core\slang-char-encode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -239,6 +251,9 @@
<ClCompile Include="..\..\..\source\core\slang-io.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\core\slang-lazy-castable-list.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\core\slang-lz4-compression-system.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp
index 413858c32..69a9b66f1 100644
--- a/source/compiler-core/slang-artifact-desc-util.cpp
+++ b/source/compiler-core/slang-artifact-desc-util.cpp
@@ -651,9 +651,9 @@ UnownedStringSlice ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& des
Index pos = Path::findLastSeparatorIndex(basePath);
if (pos >= 0)
{
- outPath.append(basePath.head(pos));
- outPath.append(Path::kPathDelimiter);
-
+ // Keep the stem including the delimiter
+ outPath.append(basePath.head(pos + 1));
+ // Get the baseName
baseName = basePath.tail(pos + 1);
}
diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp
index d57edd2c8..73927db96 100644
--- a/source/compiler-core/slang-artifact-impl.cpp
+++ b/source/compiler-core/slang-artifact-impl.cpp
@@ -5,368 +5,9 @@
#include "slang-artifact-util.h"
-namespace Slang {
-
-/*
-If we use LazyCastableList for Items, it means we'll have to use the
-UnknownCastableAdapter for ISharedLibrary, IBlob etc.
-
-That means when we look for an item in the list, we will always do a query interface on those types,
-although it will always fail (so no atomic ref count).
-
-That doesn't seem wholey unreasonable.
-
-Note that we *can* derive from ICastable for *our* implementations of ISlangBlob, ISharedLibrary. So the
-kludge is only needed for types that really do require adaption. For Blob we'll require multiple interface inheritance.
-*/
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LazyCastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void LazyCastableList::removeAt(Index index)
-{
- SLANG_ASSERT(index >= 0 && index < getCount());
-
- if (auto list = as<ICastableList>(m_castable))
- {
- list->removeAt(index);
- }
- else
- {
- SLANG_ASSERT(index == 0);
- m_castable.setNull();
- }
-}
-
-void LazyCastableList::clear()
-{
- if (m_castable)
- {
- if (auto list = as<ICastableList>(m_castable))
- {
- list->clear();
- }
- else
- {
- m_castable.setNull();
- }
- }
-}
-
-void LazyCastableList::clearAndDeallocate()
-{
- m_castable.setNull();
-}
+#include "../core/slang-castable-list-impl.h"
-Count LazyCastableList::getCount() const
-{
- if (m_castable)
- {
- if (auto list = as<ICastableList>(m_castable))
- {
- return list->getCount();
- }
- return 1;
- }
- return 0;
-}
-
-void LazyCastableList::add(ICastable* castable)
-{
- SLANG_ASSERT(castable);
- SLANG_ASSERT(castable != m_castable);
-
- if (m_castable)
- {
- if (auto list = as<ICastableList>(m_castable))
- {
- // Shouldn't be in the list
- SLANG_ASSERT(list->indexOf(castable) < 0);
- list->add(castable);
- }
- else
- {
- list = new CastableList;
- list->add(m_castable);
- m_castable = list;
- list->add(castable);
- }
- }
- else
- {
- m_castable = castable;
- }
-}
-
-ICastableList* LazyCastableList::requireList()
-{
- if (m_castable)
- {
- if (auto list = as<ICastableList>(m_castable))
- {
- return list;
- }
- else
- {
- // Promote to a list with the element in it
- list = new CastableList;
- list->add(m_castable);
- m_castable = list;
- return list;
- }
- }
- else
- {
- // Create an empty list
- ICastableList* list = new CastableList;
- m_castable = list;
- return list;
- }
-}
-
-ICastableList* LazyCastableList::getList()
-{
- return (m_castable == nullptr) ? nullptr : requireList();
-}
-
-void* LazyCastableList::find(const Guid& guid)
-{
- if (!m_castable)
- {
- return nullptr;
- }
- if (auto list = as<ICastableList>(m_castable))
- {
- return list->find(guid);
- }
- else
- {
- return m_castable->castAs(guid);
- }
-}
-
-ConstArrayView<ICastable*> LazyCastableList::getView() const
-{
- if (!m_castable)
- {
- // Empty
- return ConstArrayView<ICastable*>();
- }
-
- if (auto list = as<ICastableList>(m_castable))
- {
- const auto count = list->getCount();
- const auto buffer = list->getBuffer();
-
- return ConstArrayView<ICastable*>(buffer, count);
- }
- else
- {
- return ConstArrayView<ICastable*>((ICastable*const*)&m_castable, 1);
- }
-}
-
-Index LazyCastableList::indexOf(ICastable* castable) const
-{
- return getView().indexOf(castable);
-}
-
-Index LazyCastableList::indexOfUnknown(ISlangUnknown* unk) const
-{
- {
- ComPtr<ICastable> castable;
- if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- return indexOf(castable);
- }
- }
-
- // It's not derived from ICastable, so can only be in list via an adapter
- const auto view = getView();
-
- const Count count = view.getCount();
- for (Index i = 0; i < count; ++i)
- {
- auto adapter = as<IUnknownCastableAdapter>(view[i]);
- if (adapter && adapter->getContained() == unk)
- {
- return i;
- }
- }
-
- return -1;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* UnknownCastableAdapter::castAs(const Guid& guid)
-{
- if (auto intf = getInterface(guid))
- {
- return intf;
- }
- if (auto obj = getObject(guid))
- {
- return obj;
- }
-
- if (m_found && guid == m_foundGuid)
- {
- return m_found;
- }
-
- ComPtr<ISlangUnknown> cast;
- if (SLANG_SUCCEEDED(m_contained->queryInterface(guid, (void**)cast.writeRef())) && cast)
- {
- // Save the interface in the cache
- m_found = cast;
- m_foundGuid = guid;
-
- return cast;
- }
- return nullptr;
-}
-
-void* UnknownCastableAdapter::getInterface(const Guid& guid)
-{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid())
- {
- return static_cast<ICastable*>(this);
- }
- return nullptr;
-}
-
-void* UnknownCastableAdapter::getObject(const Guid& guid)
-{
- SLANG_UNUSED(guid);
- return nullptr;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-CastableList::~CastableList()
-{
- for (auto castable : m_list)
- {
- castable->release();
- }
-}
-
-void* CastableList::castAs(const Guid& guid)
-{
- if (auto intf = getInterface(guid))
- {
- return intf;
- }
- return getObject(guid);
-}
-
-void* CastableList::getInterface(const Guid& guid)
-{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid() ||
- guid == ICastableList::getTypeGuid())
- {
- return static_cast<ICastableList*>(this);
- }
- return nullptr;
-}
-
-void* CastableList::getObject(const Guid& guid)
-{
- SLANG_UNUSED(guid);
- return nullptr;
-}
-
-void* CastableList::find(const Guid& guid)
-{
- for (ICastable* castable : m_list)
- {
- if (auto ptr = castable->castAs(guid))
- {
- return ptr;
- }
- }
- return nullptr;
-}
-
-Index CastableList::indexOf(ICastable* castable)
-{
- const Count count = m_list.getCount();
- for (Index i = 0; i < count; ++i)
- {
- ICastable* cur = m_list[i];
- if (cur == castable)
- {
- return i;
- }
- }
- return -1;
-}
-
-void CastableList::add(ICastable* castable)
-{
- SLANG_ASSERT(castable);
- castable->addRef();
- m_list.add(castable);
-}
-
-void CastableList::removeAt(Index i)
-{
- auto castable = m_list[i];
- m_list.removeAt(i);
- castable->release();
-}
-
-void CastableList::clear()
-{
- for (auto castable : m_list)
- {
- castable->release();
- }
- m_list.clear();
-}
-
-void CastableList::addUnknown(ISlangUnknown* unk)
-{
- // If it has ICastable interface we can just add as that
- {
- ComPtr<ICastable> castable;
- if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- return add(castable);
- }
- }
-
- // Wrap it in an adapter
- IUnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk);
- add(adapter);
-}
-
-Index CastableList::indexOfUnknown(ISlangUnknown* unk)
-{
- SLANG_ASSERT(unk);
- // If it has a castable interface we can just look for that
- {
- ComPtr<ICastable> castable;
- if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- return indexOf(castable);
- }
- }
-
- // It's not derived from ICastable, so can only be in list via an adapter
- const Count count = m_list.getCount();
- for (Index i = 0; i < count; ++i)
- {
- auto adapter = as<IUnknownCastableAdapter>(m_list[i]);
- if (adapter && adapter->getContained() == unk)
- {
- return i;
- }
- }
- return -1;
-}
+namespace Slang {
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -535,15 +176,15 @@ ICastableList* Artifact::getAssociated()
return m_associated.requireList();
}
-void Artifact::addRepresentation(IArtifactRepresentation* rep)
+void Artifact::addRepresentation(ICastable* castable)
{
- SLANG_ASSERT(rep);
- if (m_representations.indexOf(rep) >= 0)
+ SLANG_ASSERT(castable);
+ if (m_representations.indexOf(castable) >= 0)
{
SLANG_ASSERT_FAILURE("Already have this representation");
return;
}
- m_representations.add(rep);
+ m_representations.add(castable);
}
void Artifact::addRepresentationUnknown(ISlangUnknown* unk)
@@ -582,4 +223,19 @@ ICastableList* Artifact::getRepresentations()
return m_representations.requireList();
}
+IArtifactList* Artifact::getChildren()
+{
+ // If it has already evaluated, return it.
+ if (m_children)
+ {
+ return m_children;
+ }
+
+ auto util = ArtifactUtilImpl::getSingleton();
+ util->getChildrenDefaultImpl(this, m_children.writeRef());
+
+ return m_children;
+}
+
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h
index 79aad3b64..e4db46222 100644
--- a/source/compiler-core/slang-artifact-impl.h
+++ b/source/compiler-core/slang-artifact-impl.h
@@ -4,6 +4,8 @@
#include "slang-artifact.h"
+#include "../core/slang-lazy-castable-list.h"
+
#include "../../slang-com-helper.h"
#include "../../slang-com-ptr.h"
@@ -12,89 +14,6 @@
namespace Slang
{
-/* An adapter such that types which aren't derived from ICastable, can be used as such.
-
-With the following caveats.
-* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter
-* assumes when doing a queryInterface on the contained item
-*/
-class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter
-{
-public:
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- // ICastable
- SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
-
- // IUnknownCastableAdapter
- virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; }
-
- UnknownCastableAdapter(ISlangUnknown* unk):
- m_contained(unk)
- {
- SLANG_ASSERT(unk);
- }
-
-protected:
- void* getInterface(const Guid& guid);
- void* getObject(const Guid& guid);
-
- ComPtr<ISlangUnknown> m_contained;
-
- // We hold a cache for a single lookup to make things a little faster
- void* m_found = nullptr;
- Guid m_foundGuid;
-};
-
-class CastableList : public ComBaseObject, public ICastableList
-{
-public:
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- // ICastable
- SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
-
- // ICastableList
- virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_list.getCount(); }
- virtual ICastable* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return m_list[i]; }
- virtual void SLANG_MCALL add(ICastable* castable) SLANG_OVERRIDE;
- virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) SLANG_OVERRIDE;
- virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE;
- virtual void SLANG_MCALL clear() SLANG_OVERRIDE;
- virtual Index SLANG_MCALL indexOf(ICastable* castable) SLANG_OVERRIDE;
- virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) SLANG_OVERRIDE;
- virtual void* SLANG_MCALL find(const Guid& guid) SLANG_OVERRIDE;
- virtual ICastable* const* SLANG_MCALL getBuffer() SLANG_OVERRIDE { return m_list.getBuffer(); }
-
- virtual ~CastableList();
-
-protected:
- void* getInterface(const Guid& guid);
- void* getObject(const Guid& guid);
-
- List<ICastable*> m_list;
-};
-
-class LazyCastableList
-{
-public:
- void add(ICastable* castable);
- Count getCount() const;
- void removeAt(Index index);
- void clear();
- void clearAndDeallocate();
- void* find(const Guid& guid);
- ConstArrayView<ICastable*> getView() const;
- Index indexOf(ICastable* castable) const;
- Index indexOfUnknown(ISlangUnknown* unk) const;
-
- ICastableList* requireList();
- ICastableList* getList();
-
-protected:
- ComPtr<ICastable> m_castable;
-};
-
class ArtifactList : public ComBaseObject, public IArtifactList
{
public:
@@ -134,15 +53,6 @@ protected:
/*
Discussion:
-It could make sense to remove the explicit variables of a ISlangBlob, and the file backing from this interface, as they could
-all be implemented as element types presumably deriving from IArtifactInstance. Doing so would mean how a 'file' is turned into
-a blob is abstracted.
-
-It may be helpful to be able to add temporary files to the artifact (such that they will be deleted when the artifact goes out of
-scope). Using an implementation of the File backed IArtifactInstance, with a suitable desc would sort of work, but it breaks the idea
-that any IArtifactInstance *represents* the contents of Artifact that contains it. Of course there could be types *not* deriving
-from IArtifactInstance that handle temporary file existance. This is probably the simplest answer to the problem.
-
Another issue occurs around wanting to hold multiple kernels within a container. The problem here is that although through the desc
we can identify what target a kernel is for, there is no way of telling what stage it is for.
@@ -174,11 +84,13 @@ public:
virtual void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) SLANG_OVERRIDE;
virtual ICastableList* SLANG_MCALL getAssociated() SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(IArtifactRepresentation* rep) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) SLANG_OVERRIDE;
virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) SLANG_OVERRIDE;
virtual ICastableList* SLANG_MCALL getRepresentations() SLANG_OVERRIDE;
+ virtual IArtifactList* SLANG_MCALL getChildren() SLANG_OVERRIDE;
+
/// Ctor
Artifact(const Desc& desc, const String& name) :
m_desc(desc),
diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp
index 20480ae07..d1de75c79 100644
--- a/source/compiler-core/slang-artifact-representation-impl.cpp
+++ b/source/compiler-core/slang-artifact-representation-impl.cpp
@@ -77,71 +77,21 @@ bool FileArtifactRepresentation::exists()
return SLANG_SUCCEEDED(res) && pathType == SLANG_PATH_TYPE_FILE;
}
-FileArtifactRepresentation::~FileArtifactRepresentation()
-{
- if (m_kind == Kind::Owned)
- {
- auto fileSystem = _getFileSystem();
- fileSystem->remove(m_path.getBuffer());
- }
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LockFile !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* LockFile::getInterface(const Guid& guid)
+void FileArtifactRepresentation::disown()
{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid() ||
- guid == ILockFile::getTypeGuid())
+ if (_isOwned())
{
- return static_cast<ILockFile*>(this);
+ m_kind = Kind::Reference;
}
- return nullptr;
-}
-
-void* LockFile::getObject(const Guid& guid)
-{
- SLANG_UNUSED(guid);
- return nullptr;
}
-ISlangMutableFileSystem* LockFile::_getFileSystem()
-{
- return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton();
-}
-
-void* LockFile::castAs(const Guid& guid)
-{
- if (auto intf = getInterface(guid))
- {
- return intf;
- }
- return getObject(guid);
-}
-
-const char* LockFile::getPath()
-{
- return (m_path.getLength() > 0) ? m_path.getBuffer() : nullptr;
-}
-
-ISlangMutableFileSystem* LockFile::getFileSystem()
-{
- return m_fileSystem;
-}
-
-LockFile::~LockFile()
+FileArtifactRepresentation::~FileArtifactRepresentation()
{
- if (m_path.getLength() > 0)
+ if (_isOwned())
{
auto fileSystem = _getFileSystem();
fileSystem->remove(m_path.getBuffer());
}
}
-void LockFile::disown()
-{
- m_path = String();
- m_fileSystem.setNull();
-}
-
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h
index 9c2066e55..a40adf0e9 100644
--- a/source/compiler-core/slang-artifact-representation-impl.h
+++ b/source/compiler-core/slang-artifact-representation-impl.h
@@ -12,41 +12,7 @@
namespace Slang
{
-/* An implementation of ILockFile */
-class LockFile : public ComBaseObject, public ILockFile
-{
-public:
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- // ICastable
- SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
-
- // ILockFile
- SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE;
- SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE;
- SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE;
-
- /// Ctor
- LockFile(String path, ISlangMutableFileSystem* fileSystem) :
- m_path(path),
- m_fileSystem(fileSystem)
- {
- }
-
- ~LockFile();
-
-protected:
- void* getInterface(const Guid& uuid);
- void* getObject(const Guid& uuid);
-
- ISlangMutableFileSystem* _getFileSystem();
-
- String m_path;
- ComPtr<ISlangMutableFileSystem> m_fileSystem;
-};
-
-/*
-A representation of an artifact that is held in a file */
+/* A representation of an artifact that is held in a file */
class FileArtifactRepresentation : public ComBaseObject, public IFileArtifactRepresentation
{
public:
@@ -64,10 +30,11 @@ public:
// IFileArtifactRepresentation
virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; }
virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); }
- virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; }
virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; }
+ virtual SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW IFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; }
- FileArtifactRepresentation(Kind kind, String path, ILockFile* lockFile, ISlangMutableFileSystem* fileSystem):
+ FileArtifactRepresentation(Kind kind, String path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem):
m_kind(kind),
m_path(path),
m_lockFile(lockFile),
@@ -81,11 +48,14 @@ protected:
void* getInterface(const Guid& uuid);
void* getObject(const Guid& uuid);
+ /// True if the file is owned
+ bool _isOwned() const { return Index(m_kind) >= Index(Kind::Owned); }
+
ISlangMutableFileSystem* _getFileSystem();
Kind m_kind;
String m_path;
- ComPtr<ILockFile> m_lockFile;
+ ComPtr<IFileArtifactRepresentation> m_lockFile;
ComPtr<ISlangMutableFileSystem> m_fileSystem;
};
diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h
index 00a5c9e5b..230283ce4 100644
--- a/source/compiler-core/slang-artifact-representation.h
+++ b/source/compiler-core/slang-artifact-representation.h
@@ -7,20 +7,6 @@
namespace Slang
{
-/* A lock file */
-class ILockFile : public ICastable
-{
- SLANG_COM_INTERFACE(0x9177ea36, 0xa608, 0x4490, { 0x87, 0xf0, 0xf3, 0x93, 0x9, 0x7d, 0x36, 0xce })
-
- /// The path to a lock file.
- virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
- /// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
- virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0;
-
- /// Makes the lock file no longer owned. Doing so will make the path nullptr, and getFileSystem nullptr.
- virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0;
-};
-
/*
A representation as a file. If it is a temporary file, it will likely disappear.
A file representation does not have to be a representation of a file on the file system.
@@ -30,21 +16,26 @@ to be usable. */
class IFileArtifactRepresentation : public IArtifactRepresentation
{
public:
+ // NOTE!
enum class Kind
{
Reference, ///< References a file on the file system
- Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope
NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob.
+ Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope
+ Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for a temporary file
+ CountOf,
};
-
+
/// The the kind of file.
virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0;
/// The path (on the file system)
virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
- /// Get the lock file. Return nullptr if there is no lock file.
- virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() = 0;
/// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0;
+ /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become 'Reference'
+ virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0;
+ /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one.
+ virtual SLANG_NO_THROW IFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0;
};
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp
index 7f69a0464..909c9b3d2 100644
--- a/source/compiler-core/slang-artifact-util.cpp
+++ b/source/compiler-core/slang-artifact-util.cpp
@@ -67,7 +67,7 @@ ArtifactStyle ArtifactUtilImpl::getStyleParent(ArtifactStyle style) { return get
UnownedStringSlice ArtifactUtilImpl::getStyleName(ArtifactStyle style) { return getName(style); }
bool ArtifactUtilImpl::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); }
-SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutableFileSystem* fileSystem, ILockFile** outLockFile)
+SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile)
{
if (fileSystem)
{
@@ -84,7 +84,7 @@ SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutab
String lockPath;
SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath));
- ComPtr<ILockFile> lockFile(new LockFile(lockPath, fileSystem));
+ ComPtr<IFileArtifactRepresentation> lockFile(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Lock, lockPath, nullptr, fileSystem));
*outLockFile = lockFile.detach();
return SLANG_OK;
@@ -114,7 +114,7 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa
SLANG_RETURN_ON_FAIL(artifact->loadBlob(keep, blob.writeRef()));
// Okay we need to store as a temporary. Get a lock file.
- ComPtr<ILockFile> lockFile;
+ ComPtr<IFileArtifactRepresentation> lockFile;
SLANG_RETURN_ON_FAIL(createLockFile(artifact->getName(), nullptr, lockFile.writeRef()));
// Now we need the appropriate name for this item
@@ -126,25 +126,32 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa
// Write the contents
SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize()));
- // If the paths are identical we don't need a lock file
+ ComPtr<IFileArtifactRepresentation> fileRep;
+
+ // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed
+ // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path
+ // might mean the lock file and the rep have the same path.
+ // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile
+
+ // If the paths are identical, we can just use the lock file for the rep
if (UnownedStringSlice(lockFile->getPath()) == path.getUnownedSlice())
{
- // Make the lockFile no longer own the file
- lockFile->disown();
- // We no longer need the lock file
- lockFile.setNull();
+ fileRep.swap(lockFile);
+ }
+ else
+ {
+ // Create a new rep that references the lock file
+ fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, nullptr);
}
-
+
// Create the rep
- IFileArtifactRepresentation* fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, nullptr);
if (canKeep(keep))
{
artifact->addRepresentation(fileRep);
}
- // Return it
- fileRep->addRef();
- *outFile = fileRep;
+ // Return the file
+ *outFile = fileRep.detach();
return SLANG_OK;
}
@@ -153,4 +160,19 @@ ArtifactDesc ArtifactUtilImpl::makeDescFromCompileTarget(SlangCompileTarget targ
return ArtifactDescUtil::makeDescFromCompileTarget(target);
}
+SlangResult ArtifactUtilImpl::getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList)
+{
+ auto desc = artifact->getDesc();
+
+ // If it's a container type for now, just create empty list of children
+ if (isDerivedFrom(desc.kind, ArtifactKind::Container))
+ {
+ *outList = ComPtr<IArtifactList>(new ArtifactList(artifact)).detach();
+ return SLANG_OK;
+ }
+
+ return SLANG_E_NOT_AVAILABLE;
+}
+
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h
index f9070a76e..c391a5056 100644
--- a/source/compiler-core/slang-artifact-util.h
+++ b/source/compiler-core/slang-artifact-util.h
@@ -28,7 +28,7 @@ class IArtifactUtil : public ISlangUnknown
virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0;
virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, ILockFile** outLockFile) = 0;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) = 0;
/// Given a desc and a basePath returns a suitable name
virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0;
@@ -37,6 +37,8 @@ class IArtifactUtil : public ISlangUnknown
virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFileRep) = 0;
virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) = 0;
+
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList) = 0;
};
class ArtifactUtilImpl : public IArtifactUtil
@@ -64,7 +66,7 @@ public:
virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE;
virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, ILockFile** outLockFile) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE;
@@ -72,6 +74,8 @@ public:
virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList) SLANG_OVERRIDE;
+
static IArtifactUtil* getSingleton() { return &g_singleton; }
protected:
diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h
index 3c991b7b6..55b3ff89f 100644
--- a/source/compiler-core/slang-artifact.h
+++ b/source/compiler-core/slang-artifact.h
@@ -4,9 +4,10 @@
#include "../core/slang-basic.h"
-#include "../../slang-com-helper.h"
+//#include "../../slang-com-helper.h"
+//#include "../core/slang-destroyable.h"
-#include "../core/slang-destroyable.h"
+#include "../core/slang-castable-list.h"
namespace Slang
{
@@ -202,6 +203,7 @@ inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked)
// Forward declare
class IFileArtifactRepresentation;
class IArtifactRepresentation;
+class IArtifactList;
// Controls what items can be kept.
enum class ArtifactKeep
@@ -218,40 +220,6 @@ SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(Artif
/// Returns the keep type for an intermediate
SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; }
-/* A useful interface for handling lists of castable interfaces. Cannot hold nullptr */
-class ICastableList : public ICastable
-{
- SLANG_COM_INTERFACE(0x335f3d40, 0x934c, 0x40dc, { 0xb5, 0xe1, 0xf7, 0x6e, 0x40, 0x3, 0x62, 0x5 })
-
- /// Get the count of all interfaces held in the list
- virtual Count SLANG_MCALL getCount() = 0;
- /// Get the interface at the specified index
- virtual ICastable* SLANG_MCALL getAt(Index i) = 0;
- /// Add an item to the list
- virtual void SLANG_MCALL add(ICastable* unk) = 0;
- /// Add IUnknown, will cast to ICastable and if that's not possible will wrap
- virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) = 0;
- /// Remove item at index, remaining items stay in the same order
- virtual void SLANG_MCALL removeAt(Index i) = 0;
- /// Clear the list
- virtual void SLANG_MCALL clear() = 0;
- /// Find the first index of castable, or -1 if not found
- virtual Index SLANG_MCALL indexOf(ICastable* castable) = 0;
- /// Find the index interface (handling wrapping if necessary)
- virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) = 0;
- /// Find the first item that casts to non null
- virtual void* SLANG_MCALL find(const Guid& guid) = 0;
- /// Access the internal buffer (any mutation can invalidate this value)
- virtual ICastable*const* SLANG_MCALL getBuffer() = 0;
-};
-
-// Simply finding things in a ICastableList
-template <typename T>
-SLANG_FORCE_INLINE T* find(ICastableList* list)
-{
- return reinterpret_cast<T*>(list->find(T::getTypeGuid()));
-}
-
/* The IArtifact interface is designed to represent some Artifact of compilation. It could be input to or output from a compilation.
An abstraction is desirable here, because depending on the compiler the artifact/s could be
@@ -277,12 +245,23 @@ files could be a Container containing artifacts for
* Files that contain known types
* Callable interface (an ISlangSharedLibrary)
-Each one of these additions is an 'Element'. An Element is an interface pointer and a Desc that describes what the
-inteface represents. Having the associated desc provides more detail about what the interface pointer actually is
-without having to make the interface know what it is being used for. This allows an interface to be used in multiple
-ways - for example the ISlangBlob interface could be used to represent some text, or a compiled kernel.
+There are several types of ways to associate data with an artifact:
+
+* A representation
+* Associated data
+* A child artifact
+
+A `representation` has to wholly represent the artifact. That representation could be a blob, a file on the file system,
+an in memory representation. There are two classes of `Representation` - ones that can be turned into blobs (and therefore
+derive from IArtifactRepresentation) and ones that are in of themselves a representation (such as a blob or or ISlangSharedLibrary).
+
+`Associated data` is information that is associated with the artifact, but isn't a (whole) representation. It could be part
+of the representation, or useful for the implementation of a representation. Could also be considered as a kind of side channel
+to associate arbitrary temporary data with an artifact.
+
+A `child artifact` belongs to the artifact, within the hierarchy of artifacts. Child artifacts are held in an IArtifactList.
-A more long term goals would be to
+More long term goals would be to
* Make Diagnostics into an interface (such it can be added to a Artifact result)
* Use Artifact and related types for downstream compiler
@@ -329,16 +308,27 @@ public:
/// Get the list of associated items
virtual ICastableList* SLANG_MCALL getAssociated() = 0;
- /// Add a representation that derives from IArtifactRepresentation
- virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(IArtifactRepresentation* rep) = 0;
+ /// Add a representation
+ virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) = 0;
/// Add a representation that doesn't derive from IArtifactRepresentation
virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) = 0;
/// Find representation
virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) = 0;
/// Get the list of all representations
virtual ICastableList* SLANG_MCALL getRepresentations() = 0;
+
+ /// Get the children. This may be evaluated lazily.
+ /// Only artifacts with a ArtifactKind that derives from Container generally produce childen.
+ /// If an artifact doesn't support children, it can return nullptr.
+ virtual IArtifactList* SLANG_MCALL getChildren() = 0;
};
+template <typename T>
+SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact)
+{
+ return reinterpret_cast<T*>(artifact->findRepresentation(T::getTypeGuid()));
+}
+
/* A list of artifacts. */
class IArtifactList : public ICastable
{
@@ -380,11 +370,6 @@ class IArtifactRepresentation : public ICastable
virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0;
};
-template <typename T>
-SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact)
-{
- return reinterpret_cast<T*>(artifact->findRepresentation(T::getTypeGuid()));
-}
} // namespace Slang
diff --git a/source/core/slang-castable-list-impl.cpp b/source/core/slang-castable-list-impl.cpp
new file mode 100644
index 000000000..ee10ea995
--- /dev/null
+++ b/source/core/slang-castable-list-impl.cpp
@@ -0,0 +1,178 @@
+// slang-castable-list-impl.cpp
+#include "slang-castable-list-impl.h"
+
+namespace Slang {
+
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void* UnknownCastableAdapter::castAs(const Guid& guid)
+{
+ if (auto intf = getInterface(guid))
+ {
+ return intf;
+ }
+ if (auto obj = getObject(guid))
+ {
+ return obj;
+ }
+
+ if (m_found && guid == m_foundGuid)
+ {
+ return m_found;
+ }
+
+ ComPtr<ISlangUnknown> cast;
+ if (SLANG_SUCCEEDED(m_contained->queryInterface(guid, (void**)cast.writeRef())) && cast)
+ {
+ // Save the interface in the cache
+ m_found = cast;
+ m_foundGuid = guid;
+
+ return cast;
+ }
+ return nullptr;
+}
+
+void* UnknownCastableAdapter::getInterface(const Guid& guid)
+{
+ if (guid == ISlangUnknown::getTypeGuid() ||
+ guid == ICastable::getTypeGuid())
+ {
+ return static_cast<ICastable*>(this);
+ }
+ return nullptr;
+}
+
+void* UnknownCastableAdapter::getObject(const Guid& guid)
+{
+ SLANG_UNUSED(guid);
+ return nullptr;
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+CastableList::~CastableList()
+{
+ for (auto castable : m_list)
+ {
+ castable->release();
+ }
+}
+
+void* CastableList::castAs(const Guid& guid)
+{
+ if (auto intf = getInterface(guid))
+ {
+ return intf;
+ }
+ return getObject(guid);
+}
+
+void* CastableList::getInterface(const Guid& guid)
+{
+ if (guid == ISlangUnknown::getTypeGuid() ||
+ guid == ICastable::getTypeGuid() ||
+ guid == ICastableList::getTypeGuid())
+ {
+ return static_cast<ICastableList*>(this);
+ }
+ return nullptr;
+}
+
+void* CastableList::getObject(const Guid& guid)
+{
+ SLANG_UNUSED(guid);
+ return nullptr;
+}
+
+void* CastableList::find(const Guid& guid)
+{
+ for (ICastable* castable : m_list)
+ {
+ if (auto ptr = castable->castAs(guid))
+ {
+ return ptr;
+ }
+ }
+ return nullptr;
+}
+
+Index CastableList::indexOf(ICastable* castable)
+{
+ const Count count = m_list.getCount();
+ for (Index i = 0; i < count; ++i)
+ {
+ ICastable* cur = m_list[i];
+ if (cur == castable)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void CastableList::add(ICastable* castable)
+{
+ SLANG_ASSERT(castable);
+ castable->addRef();
+ m_list.add(castable);
+}
+
+void CastableList::removeAt(Index i)
+{
+ auto castable = m_list[i];
+ m_list.removeAt(i);
+ castable->release();
+}
+
+void CastableList::clear()
+{
+ for (auto castable : m_list)
+ {
+ castable->release();
+ }
+ m_list.clear();
+}
+
+void CastableList::addUnknown(ISlangUnknown* unk)
+{
+ // If it has ICastable interface we can just add as that
+ {
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ return add(castable);
+ }
+ }
+
+ // Wrap it in an adapter
+ IUnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk);
+ add(adapter);
+}
+
+Index CastableList::indexOfUnknown(ISlangUnknown* unk)
+{
+ SLANG_ASSERT(unk);
+ // If it has a castable interface we can just look for that
+ {
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ return indexOf(castable);
+ }
+ }
+
+ // It's not derived from ICastable, so can only be in list via an adapter
+ const Count count = m_list.getCount();
+ for (Index i = 0; i < count; ++i)
+ {
+ auto adapter = as<IUnknownCastableAdapter>(m_list[i]);
+ if (adapter && adapter->getContained() == unk)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+} // namespace Slang
diff --git a/source/core/slang-castable-list-impl.h b/source/core/slang-castable-list-impl.h
new file mode 100644
index 000000000..6c03855f2
--- /dev/null
+++ b/source/core/slang-castable-list-impl.h
@@ -0,0 +1,83 @@
+// slang-castable-list.h
+#ifndef SLANG_CASTABLE_LIST_IMPL_H
+#define SLANG_CASTABLE_LIST_IMPL_H
+
+#include "slang-castable-list.h"
+
+#include "../../slang-com-helper.h"
+#include "../../slang-com-ptr.h"
+
+#include "../core/slang-com-object.h"
+
+namespace Slang
+{
+
+/* An adapter such that types which aren't derived from ICastable, can be used as such.
+
+With the following caveats.
+* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter
+* assumes when doing a queryInterface on the contained item, it will remain in scope when released (this is *not* strict COM)
+*/
+class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter
+{
+public:
+ SLANG_COM_BASE_IUNKNOWN_ALL
+
+ // ICastable
+ SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
+
+ // IUnknownCastableAdapter
+ virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; }
+
+ UnknownCastableAdapter(ISlangUnknown* unk):
+ m_contained(unk)
+ {
+ SLANG_ASSERT(unk);
+ }
+
+protected:
+ void* getInterface(const Guid& guid);
+ void* getObject(const Guid& guid);
+
+ ComPtr<ISlangUnknown> m_contained;
+
+ // We hold a cache for a single lookup to make things a little faster
+ void* m_found = nullptr;
+ Guid m_foundGuid;
+};
+
+/* Implementation of the ICastableList interface.
+Is atomic reference counted*/
+class CastableList : public ComBaseObject, public ICastableList
+{
+public:
+ SLANG_COM_BASE_IUNKNOWN_ALL
+
+ // ICastable
+ SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
+
+ // ICastableList
+ virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_list.getCount(); }
+ virtual ICastable* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return m_list[i]; }
+ virtual void SLANG_MCALL add(ICastable* castable) SLANG_OVERRIDE;
+ virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) SLANG_OVERRIDE;
+ virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE;
+ virtual void SLANG_MCALL clear() SLANG_OVERRIDE;
+ virtual Index SLANG_MCALL indexOf(ICastable* castable) SLANG_OVERRIDE;
+ virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) SLANG_OVERRIDE;
+ virtual void* SLANG_MCALL find(const Guid& guid) SLANG_OVERRIDE;
+ virtual ICastable*const* SLANG_MCALL getBuffer() SLANG_OVERRIDE { return m_list.getBuffer(); }
+
+ /// Dtor
+ virtual ~CastableList();
+
+protected:
+ void* getInterface(const Guid& guid);
+ void* getObject(const Guid& guid);
+
+ List<ICastable*> m_list;
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/core/slang-castable-list.h b/source/core/slang-castable-list.h
new file mode 100644
index 000000000..942f53376
--- /dev/null
+++ b/source/core/slang-castable-list.h
@@ -0,0 +1,57 @@
+// slang-castable-list.h
+#ifndef SLANG_CASTABLE_LIST_H
+#define SLANG_CASTABLE_LIST_H
+
+#include "../core/slang-basic.h"
+
+#include "../core/slang-destroyable.h"
+
+namespace Slang
+{
+
+/* A useful interface for handling lists of castable interfaces. Cannot hold nullptr */
+class ICastableList : public ICastable
+{
+ SLANG_COM_INTERFACE(0x335f3d40, 0x934c, 0x40dc, { 0xb5, 0xe1, 0xf7, 0x6e, 0x40, 0x3, 0x62, 0x5 })
+
+ /// Get the count of all interfaces held in the list
+ virtual Count SLANG_MCALL getCount() = 0;
+ /// Get the interface at the specified index
+ virtual ICastable* SLANG_MCALL getAt(Index i) = 0;
+ /// Add an item to the list
+ virtual void SLANG_MCALL add(ICastable* unk) = 0;
+ /// Add IUnknown, will cast to ICastable and if that's not possible will wrap
+ virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) = 0;
+ /// Remove item at index, remaining items stay in the same order
+ virtual void SLANG_MCALL removeAt(Index i) = 0;
+ /// Clear the list
+ virtual void SLANG_MCALL clear() = 0;
+ /// Find the first index of castable, or -1 if not found
+ virtual Index SLANG_MCALL indexOf(ICastable* castable) = 0;
+ /// Find the index interface (handling wrapping if necessary)
+ virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) = 0;
+ /// Find the first item that casts to non null
+ virtual void* SLANG_MCALL find(const Guid& guid) = 0;
+ /// Access the internal buffer (any mutation can invalidate this value)
+ virtual ICastable*const* SLANG_MCALL getBuffer() = 0;
+};
+
+// Simply finding things in a ICastableList
+template <typename T>
+SLANG_FORCE_INLINE T* find(ICastableList* list)
+{
+ return reinterpret_cast<T*>(list->find(T::getTypeGuid()));
+}
+
+/* Adapter interface to make a non castable types work as ICastable */
+class IUnknownCastableAdapter : public ICastable
+{
+ SLANG_COM_INTERFACE(0x8b4aad81, 0x4934, 0x4a67, { 0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54 });
+
+ /// When using the adapter, this provides a way to directly get the internal no ICastable type
+ virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() = 0;
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/core/slang-destroyable.h b/source/core/slang-destroyable.h
index bf373ba33..390b16e7c 100644
--- a/source/core/slang-destroyable.h
+++ b/source/core/slang-destroyable.h
@@ -9,15 +9,6 @@
namespace Slang
{
-/* Adapter interface to make a non castable type work as ICastable */
-class IUnknownCastableAdapter : public ICastable
-{
- SLANG_COM_INTERFACE(0x8b4aad81, 0x4934, 0x4a67, { 0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54 } );
-
- /// When using the adapter, this provides a way to directly get the internal no ICastable type
- virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() = 0;
-};
-
/* An interface that allows for an object to implement 'destruction'. A destroyed
interface/object should release any other contained references.
Behavior of an interface that is IDestroyed should be defined on the interface. Typically
diff --git a/source/core/slang-lazy-castable-list.cpp b/source/core/slang-lazy-castable-list.cpp
new file mode 100644
index 000000000..d9f0090d5
--- /dev/null
+++ b/source/core/slang-lazy-castable-list.cpp
@@ -0,0 +1,163 @@
+// slang-lazy-castable-list.cpp
+#include "slang-lazy-castable-list.h"
+
+#include "slang-castable-list-impl.h"
+
+namespace Slang {
+
+void LazyCastableList::removeAt(Index index)
+{
+ SLANG_ASSERT(index >= 0 && index < getCount());
+
+ switch (m_state)
+ {
+ case State::None: break;
+ case State::One:
+ {
+ m_state = State::None;
+ m_castable.setNull();
+ break;
+ }
+ case State::List:
+ {
+ static_cast<ICastableList*>(m_castable.get())->removeAt(index);
+ break;
+ }
+ }
+}
+
+void LazyCastableList::clear()
+{
+ if (m_state == State::List)
+ {
+ auto list = static_cast<ICastableList*>(m_castable.get());
+ list->clear();
+ }
+ else
+ {
+ m_state = State::None;
+ m_castable.setNull();
+ }
+}
+
+void LazyCastableList::clearAndDeallocate()
+{
+ m_state = State::None;
+ m_castable.setNull();
+}
+
+Count LazyCastableList::getCount() const
+{
+ switch (m_state)
+ {
+ case State::None: return 0;
+ case State::One: return 1;
+ default:
+ case State::List: return static_cast<ICastableList*>(m_castable.get())->getCount();
+ }
+}
+
+void LazyCastableList::add(ICastable* castable)
+{
+ SLANG_ASSERT(castable);
+ if (m_state == State::None)
+ {
+ m_castable = castable;
+ m_state = State::One;
+ }
+ else
+ {
+ requireList()->add(castable);
+ }
+}
+
+ICastableList* LazyCastableList::requireList()
+{
+ switch (m_state)
+ {
+ case State::None:
+ {
+ m_castable = new CastableList;
+ m_state = State::List;
+ break;
+ }
+ case State::One:
+ {
+ // Turn into a list
+ auto list = new CastableList;
+ list->add(m_castable);
+ m_castable = list;
+ m_state = State::List;
+ break;
+ }
+ default: break;
+ }
+ SLANG_ASSERT(m_state == State::List);
+ return static_cast<ICastableList*>(m_castable.get());
+}
+
+ICastableList* LazyCastableList::getList()
+{
+ return (m_state == State::None) ? nullptr : requireList();
+}
+
+void* LazyCastableList::find(const Guid& guid)
+{
+ for (auto castable : getView())
+ {
+ if (auto ptr = castable->castAs(guid))
+ {
+ return ptr;
+ }
+ }
+ return nullptr;
+}
+
+ConstArrayView<ICastable*> LazyCastableList::getView() const
+{
+ switch (m_state)
+ {
+ case State::None: return ConstArrayView<ICastable*>();
+ case State::One: return ConstArrayView<ICastable*>((ICastable*const*)&m_castable, 1);
+ default:
+ case State::List:
+ {
+ auto list = static_cast<ICastableList*>(m_castable.get());
+ return ConstArrayView<ICastable*>(list->getBuffer(), list->getCount());
+ }
+ }
+}
+
+Index LazyCastableList::indexOf(ICastable* castable) const
+{
+ return getView().indexOf(castable);
+}
+
+Index LazyCastableList::indexOfUnknown(ISlangUnknown* unk) const
+{
+ // Try as a ICastable first
+ {
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ return indexOf(castable);
+ }
+ }
+
+ // It's not derived from ICastable, so can only be in list via an adapter
+ const auto view = getView();
+
+ const Count count = view.getCount();
+ for (Index i = 0; i < count; ++i)
+ {
+ auto adapter = as<IUnknownCastableAdapter>(view[i]);
+ if (adapter && adapter->getContained() == unk)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+} // namespace Slang
diff --git a/source/core/slang-lazy-castable-list.h b/source/core/slang-lazy-castable-list.h
new file mode 100644
index 000000000..4f73ce9ca
--- /dev/null
+++ b/source/core/slang-lazy-castable-list.h
@@ -0,0 +1,66 @@
+// slang-lazy-castable-list.h
+#ifndef SLANG_LAZY_CASTABLE_LIST_H
+#define SLANG_LAZY_CASTABLE_LIST_H
+
+#include "slang-castable-list.h"
+
+#include "../../slang-com-ptr.h"
+
+namespace Slang
+{
+
+/* Sometimes the overhead around having a potential list of items that might often be
+empty or only contain a single element is considerable.
+
+The `LazyCastableList` provides functionality around ICastableList to minimize allocation, or the
+need to allocate an ICastableList. It does this by tracking state in m_state, and varying the
+meaning of m_castable.
+
+* State::None - there is no list
+* State::One - there is a single entry, that is held in m_castable
+* State::List - m_castable is actually ICastableList, and holds the contents
+*/
+class LazyCastableList
+{
+public:
+ /// Add a castable to the lsit
+ void add(ICastable* castable);
+ /// Return the amount of items in the list
+ Count getCount() const;
+ /// Remove the item at the specified index
+ void removeAt(Index index);
+ /// Clear the list
+ void clear();
+ /// Clear and deallocate the list
+ void clearAndDeallocate();
+ /// Find the first item that castAs(guid) produces a result
+ void* find(const Guid& guid);
+ /// Get the contents of the list as a view
+ ConstArrayView<ICastable*> getView() const;
+ /// Get the index of castable in the list. Returns -1 if not found
+ Index indexOf(ICastable* castable) const;
+ /// Get the index of unk. Handles if the wrapping has been used.
+ Index indexOfUnknown(ISlangUnknown* unk) const;
+
+ /// Will always return a valid ICastableList
+ ICastableList* requireList();
+ /// Will return nullptr if the list is empty, else it returns a ICastableList holding the elements
+ ICastableList* getList();
+
+protected:
+ enum class State
+ {
+ None,
+ One,
+ List,
+ };
+ // A state is not *strictly* necessary, because we can always determine what m_castable is
+ // with a castAs. But doing so is not exactly fast, and using the state makes some code simpler
+ // additionally.
+ State m_state = State::None;
+ ComPtr<ICastable> m_castable;
+};
+
+} // namespace Slang
+
+#endif