summaryrefslogtreecommitdiffstats
path: root/source/core
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 /source/core
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.
Diffstat (limited to 'source/core')
-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
6 files changed, 547 insertions, 9 deletions
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