diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-10 11:37:26 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-10 11:37:26 -0400 |
| commit | fcdb4629c4c3dd2931eaa88b96b668d914c4519c (patch) | |
| tree | c54c0b9c6411f9be55b9a2816e528b91d6032703 /source/compiler-core | |
| parent | 1378fffd9da094beb41b2db89b96f556c23ab6cb (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.
Diffstat (limited to 'source/compiler-core')
| -rw-r--r-- | source/compiler-core/slang-artifact-desc-util.cpp | 6 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-impl.cpp | 386 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-impl.h | 98 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-representation-impl.cpp | 60 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-representation-impl.h | 46 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-representation.h | 27 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-util.cpp | 48 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-util.h | 8 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact.h | 81 |
9 files changed, 125 insertions, 635 deletions
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 |
