diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-10 10:04:06 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-10 10:04:06 -0400 |
| commit | 1378fffd9da094beb41b2db89b96f556c23ab6cb (patch) | |
| tree | e0558c031bd4b1a013dc56b75c4caa3ff5442021 /source/compiler-core/slang-artifact-impl.cpp | |
| parent | 89083c4b50af8e48e70b25b63cc62aca21ab706c (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.cpp | 515 |
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 |
