summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-artifact-impl.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-08-10 10:04:06 -0400
committerGitHub <noreply@github.com>2022-08-10 10:04:06 -0400
commit1378fffd9da094beb41b2db89b96f556c23ab6cb (patch)
treee0558c031bd4b1a013dc56b75c4caa3ff5442021 /source/compiler-core/slang-artifact-impl.cpp
parent89083c4b50af8e48e70b25b63cc62aca21ab706c (diff)
Artifact and ICastable (#2351)
* #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. * Fix typo.
Diffstat (limited to 'source/compiler-core/slang-artifact-impl.cpp')
-rw-r--r--source/compiler-core/slang-artifact-impl.cpp515
1 files changed, 438 insertions, 77 deletions
diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp
index 8dbae063b..d57edd2c8 100644
--- a/source/compiler-core/slang-artifact-impl.cpp
+++ b/source/compiler-core/slang-artifact-impl.cpp
@@ -7,6 +7,367 @@
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();
+}
+
+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;
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
void* ArtifactList::getInterface(const Guid& guid)
@@ -91,86 +452,24 @@ void* Artifact::getInterface(const Guid& uuid)
bool Artifact::exists()
{
- for (ISlangUnknown* item : m_items)
+ for (auto rep : m_representations.getView())
{
- ComPtr<ICastable> castable;
-
- if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ if (auto artifactRep = as<IArtifactRepresentation>(rep))
{
- auto rep = as<IArtifactRepresentation>(castable);
- if (rep)
+ // It is an artifact rep and it exists, we are done
+ if (artifactRep->exists())
{
- // It is a rep and it exists
- if (rep->exists())
- {
- return true;
- }
- continue;
- }
- // Associated types don't encapsulate an artifact representation, so don't signal existance
- if (as<IArtifactAssociated>(castable))
- {
- continue;
+ return true;
}
}
-
- // It can't be IArtifactRepresentation or IArtifactAssociated, so we assume means it exists
- return true;
- }
-
- return false;
-}
-
-void Artifact::addItem(ISlangUnknown* intf)
-{
- SLANG_ASSERT(intf);
- // Can't already be in there
- SLANG_ASSERT(m_items.indexOf(intf) < 0);
- // Add it
- m_items.add(ComPtr<ISlangUnknown>(intf));
-}
-
-void Artifact::removeItemAt(Index i)
-{
- m_items.removeAt(i);
-}
-
-void* Artifact::findItemInterface(const Guid& guid)
-{
- for (ISlangUnknown* intf : m_items)
- {
- ISlangUnknown* cast = nullptr;
- if (SLANG_SUCCEEDED(intf->queryInterface(guid, (void**)&cast)) && cast)
+ else
{
- // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope
- // (as strict COM requires so as to allow on demand interfaces).
- cast->release();
- return cast;
+ // If it's *not* IArtifactRepresentation derived, it's existance *is* a representation
+ return true;
}
}
- return nullptr;
-}
-
-void* Artifact::findItemObject(const Guid& classGuid)
-{
- for (ISlangUnknown* intf : m_items)
- {
- ComPtr<ICastable> castable;
- if (SLANG_SUCCEEDED(intf->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- void* obj = castable->castAs(classGuid);
- // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope
- // (as strict COM requires so as to allow on demand interfaces).
-
- // If could cast return the result
- if (obj)
- {
- return obj;
- }
- }
- }
- return nullptr;
+ return false;
}
SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep)
@@ -182,7 +481,7 @@ SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFi
SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
{
// If we have a blob just return it
- if (auto blob = findItem<ISlangBlob>(this))
+ if (auto blob = (ISlangBlob*)findRepresentation(ISlangBlob::getTypeGuid()))
{
blob->addRef();
*outBlob = blob;
@@ -192,12 +491,11 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
ComPtr<ISlangBlob> blob;
// Look for a representation that we can serialize into a blob
- for (ISlangUnknown* intf : m_items)
+ for (auto rep : m_representations.getView())
{
- ComPtr<IArtifactRepresentation> rep;
- if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep)
+ if (auto artifactRep = as<IArtifactRepresentation>(rep))
{
- SlangResult res = rep->writeToBlob(blob.writeRef());
+ SlangResult res = artifactRep->writeToBlob(blob.writeRef());
if (SLANG_SUCCEEDED(res) && blob)
{
break;
@@ -214,11 +512,74 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
// Put in cache
if (canKeep(keep))
{
- addItem(blob);
+ addRepresentationUnknown(blob);
}
*outBlob = blob.detach();
return SLANG_OK;
}
+void Artifact::addAssociated(ICastable* castable)
+{
+ SLANG_ASSERT(castable);
+ m_associated.add(castable);
+}
+
+void* Artifact::findAssociated(const Guid& guid)
+{
+ return m_associated.find(guid);
+}
+
+ICastableList* Artifact::getAssociated()
+{
+ return m_associated.requireList();
+}
+
+void Artifact::addRepresentation(IArtifactRepresentation* rep)
+{
+ SLANG_ASSERT(rep);
+ if (m_representations.indexOf(rep) >= 0)
+ {
+ SLANG_ASSERT_FAILURE("Already have this representation");
+ return;
+ }
+ m_representations.add(rep);
+}
+
+void Artifact::addRepresentationUnknown(ISlangUnknown* unk)
+{
+ SLANG_ASSERT(unk);
+ if (m_representations.indexOfUnknown(unk) >= 0)
+ {
+ SLANG_ASSERT_FAILURE("Already have this representation");
+ return;
+ }
+
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ if (m_representations.indexOf(castable) >= 0)
+ {
+ SLANG_ASSERT_FAILURE("Already have this representation");
+ return;
+ }
+ m_representations.add(castable);
+ }
+ else
+ {
+ UnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk);
+ m_representations.add(adapter);
+ }
+}
+
+void* Artifact::findRepresentation(const Guid& guid)
+{
+ return m_representations.find(guid);
+}
+
+ICastableList* Artifact::getRepresentations()
+{
+ return m_representations.requireList();
+}
+
} // namespace Slang