From 5c2c2cfc9918bb43225159e67a851e196e17759a Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Fri, 26 Aug 2022 20:32:53 -0400 Subject: DownstreamCompileOptions using POD types (#2381) * #include an absolute path didn't work - because paths were taken to always be relative. * Make DownstreamCompileOptions use POD types. * CharSliceAllocator -> SliceAllocator Added SliceConverter CharSliceCaster -> SliceCaster * First attempt at zero terminating around blobs. * Fix clang warning. * Add SlangTerminatedChars Make Blob implementations support it. Make most blobs 'terminated'. * Fix bug setting up sourceFiles for CommandLineDownstreamCompiler. * Traffic in TerminatedCharSlice for sourceFiles. Use ArtifactDesc to generate temporary file names for source. * Fix typo in testing for shared library/C++. --- source/core/slang-blob.cpp | 98 ++++++++++++++++++++++++++++++++++ source/core/slang-blob.h | 92 +++++++++++++++++++++---------- source/core/slang-io.cpp | 2 +- source/core/slang-riff-file-system.cpp | 2 +- source/core/slang-zip-file-system.cpp | 2 +- 5 files changed, 165 insertions(+), 31 deletions(-) (limited to 'source/core') diff --git a/source/core/slang-blob.cpp b/source/core/slang-blob.cpp index 0da8f6292..6cf5214cc 100644 --- a/source/core/slang-blob.cpp +++ b/source/core/slang-blob.cpp @@ -33,6 +33,104 @@ void* BlobBase::castAs(const SlangUUID& guid) return getObject(guid); } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* StringBlob::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void* StringBlob::getObject(const Guid& guid) +{ + // Can allow accessing the contained String + if (guid == getTypeGuid()) + { + return this; + } + // Can always be accessed as terminated char* + if (guid == SlangTerminatedChars::getTypeGuid()) + { + return const_cast(m_string.getBuffer()); + } + return nullptr; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RawBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* RawBlob::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void* RawBlob::getObject(const Guid& guid) +{ + // If the data has 0 termination, we can return the pointer + if (guid == SlangTerminatedChars::getTypeGuid() && m_data.isTerminated()) + { + return (char*)m_data.getData(); + } + return nullptr; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ScopeBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ScopeBlob::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + if (auto obj = getObject(guid)) + { + return obj; + } + + // If the contained thing is castable, ask it + if (m_castable) + { + return m_castable->castAs(guid); + } + + return nullptr; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ListBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ListBlob::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void* ListBlob::getObject(const Guid& guid) +{ + // If the data is terminated return the pointer + if (guid == SlangTerminatedChars::getTypeGuid()) + { + const auto count = m_data.getCount(); + if (m_data.getCapacity() > count) + { + auto buf = m_data.getBuffer(); + if (buf[count] == 0) + { + return (char*)buf; + } + } + } + return nullptr; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StaticBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ SlangResult StaticBlob::queryInterface(SlangUUID const& guid, void** outObject) diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h index 49bfd4a17..1acf279ef 100644 --- a/source/core/slang-blob.h +++ b/source/core/slang-blob.h @@ -40,7 +40,12 @@ There is a reasonable argument that StringBlob should contain it's own copy of t class StringBlob : public BlobBase { public: - // ISlangBlob + SLANG_CLASS_GUID(0xf7e0e93c, 0xde70, 0x4531, { 0x9c, 0x9f, 0xdd, 0xa3, 0xf6, 0xc6, 0xc0, 0xdd }); + + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; + + // ISlangBlob SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_string.getBuffer(); } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_string.getLength(); } @@ -61,6 +66,8 @@ protected: /// Get the contained string SLANG_FORCE_INLINE const String& getString() const { return m_string; } + void* getObject(const Guid& guid); + String m_string; }; @@ -70,6 +77,8 @@ public: typedef BlobBase Super; typedef ListBlob ThisType; + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getBuffer(); } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getCount(); } @@ -83,6 +92,8 @@ protected: // Move ctor explicit ListBlob(List&& data) : m_data(data) {} + void* getObject(const Guid& guid); + void operator=(const ThisType& rhs) = delete; List m_data; @@ -96,9 +107,21 @@ public: void* allocate(size_t size) { deallocate(); - m_data = ::malloc(size); + if (size > 0) + { + m_data = ::malloc(size); + } m_sizeInBytes = size; + m_capacityInBytes = size; return m_data; + } + /// Allocate size including a 0 byte at `size`. + void* allocateTerminated(size_t size) + { + uint8_t* data = (uint8_t*)allocate(size + 1); + data[size] = 0; + m_sizeInBytes = size; + return data; } /// Deallocates if holds an allocation void deallocate() @@ -109,14 +132,16 @@ public: m_data = nullptr; } m_sizeInBytes = 0; + m_capacityInBytes = 0; } - // Reallocate so the buffer is the specified size. Contents of buffer up to size remain intact. - void reallocate(size_t size) + // Reallocate so the buffer is the specified capacity/size. Contents of buffer up to size remain intact. + void reallocate(size_t capacity) { - if (size != m_sizeInBytes) + if (capacity != m_capacityInBytes) { - m_data = ::realloc(m_data, size); - m_sizeInBytes = size; + m_data = ::realloc(m_data, capacity); + m_sizeInBytes = capacity; + m_capacityInBytes = capacity; } } /// Makes this no longer own the allocation. Returns the allocated data (or nullptr if no allocation) @@ -125,6 +150,7 @@ public: void* data = m_data; m_data = nullptr; m_sizeInBytes = 0; + m_capacityInBytes = 0; return data; } /// Attach some data. @@ -134,6 +160,7 @@ public: deallocate(); m_data = data; m_sizeInBytes = size; + m_capacityInBytes = size; } void* set(const void* data, size_t size) @@ -146,26 +173,33 @@ public: return dst; } - /// Get the allocated data. Returns nullptr if there is no allocated data + /// Get the allocated data. Returns nullptr if there is no allocated data void* getData() const { return m_data; } - /// Get the size of the allocated data. + /// Get the size of the allocated data. size_t getSizeInBytes() const { return m_sizeInBytes; } + /// Get the capacity in bytes + size_t getCapacityInBytes() const { return m_capacityInBytes; } - void swap(ThisType& rhs) + void setSizeInBytes(size_t size) { - void*const data = m_data; - const size_t sizeInBytes = m_sizeInBytes; - - m_data = rhs.m_data; - m_sizeInBytes = rhs.m_sizeInBytes; + SLANG_ASSERT(size <= m_capacityInBytes); + m_sizeInBytes = size; + } - rhs.m_data = data; - rhs.m_sizeInBytes = sizeInBytes; + void swap(ThisType& rhs) + { + Swap(m_data, rhs.m_data); + Swap(m_sizeInBytes, rhs.m_sizeInBytes); + Swap(m_capacityInBytes, rhs.m_capacityInBytes); } + /// True if has zero termination, at the byte at m_sizeInBytes + bool isTerminated() const { return m_capacityInBytes > m_sizeInBytes && ((const char*)m_data)[m_sizeInBytes] == 0; } + ScopedAllocation() : m_data(nullptr), - m_sizeInBytes(0) + m_sizeInBytes(0), + m_capacityInBytes(0) { } @@ -178,6 +212,7 @@ private: void* m_data; size_t m_sizeInBytes; + size_t m_capacityInBytes; }; /** A blob that manages some raw data that it owns. @@ -185,18 +220,12 @@ private: class RawBlob : public BlobBase { public: + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getData(); } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getSizeInBytes(); } - /// Moves ownership of data and dataCount to the blob - /// data must be a pointer returned by ::malloc. - static ComPtr moveCreate(uint8_t* data, size_t dataCount) - { - RawBlob* blob = new RawBlob; - blob->m_data.attach(data, dataCount); - return ComPtr(blob); - } static ComPtr moveCreate(ScopedAllocation& alloc) { RawBlob* blob = new RawBlob; @@ -215,9 +244,11 @@ protected: // NOTE! Takes a copy of the input data RawBlob(const void* data, size_t size) { - memcpy(m_data.allocate(size), data, size); + memcpy(m_data.allocateTerminated(size), data, size); } + void* getObject(const Guid& guid); + RawBlob() = default; ScopedAllocation m_data; @@ -287,6 +318,9 @@ protected: class ScopeBlob : public BlobBase { public: + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; + // ISlangBlob SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_blob->getBufferPointer(); } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_blob->getBufferSize(); } @@ -299,15 +333,17 @@ public: protected: // Ctor - ScopeBlob(ISlangBlob* blob, ISlangUnknown* scope) : m_blob(blob), m_scope(scope) { + // Cache the ICastable interface if there is one. + blob->queryInterface(ICastable::getTypeGuid(), (void**)m_castable.writeRef()); } ComPtr m_scope; ComPtr m_blob; + ComPtr m_castable; ///< Set if the blob has this interface. Set to nullptr if does not. }; } // namespace Slang diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index a6e97057b..ef260f088 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -894,7 +894,7 @@ namespace Slang const size_t sizeInBytes = size_t(positionSizeInBytes); - void* data = out.allocate(sizeInBytes); + void* data = out.allocateTerminated(sizeInBytes); if (!data) { return SLANG_E_OUT_OF_MEMORY; diff --git a/source/core/slang-riff-file-system.cpp b/source/core/slang-riff-file-system.cpp index 186650ed3..e916cf689 100644 --- a/source/core/slang-riff-file-system.cpp +++ b/source/core/slang-riff-file-system.cpp @@ -87,7 +87,7 @@ SlangResult RiffFileSystem::loadFile(char const* path, ISlangBlob** outBlob) { // Okay lets decompress into a blob ScopedAllocation alloc; - void* dst = alloc.allocate(entry->m_uncompressedSizeInBytes); + void* dst = alloc.allocateTerminated(entry->m_uncompressedSizeInBytes); ISlangBlob* compressedData = entry->m_contents; SLANG_RETURN_ON_FAIL(m_compressionSystem->decompress(compressedData->getBufferPointer(), compressedData->getBufferSize(), entry->m_uncompressedSizeInBytes, dst)); diff --git a/source/core/slang-zip-file-system.cpp b/source/core/slang-zip-file-system.cpp index ce25066df..64ed64e13 100644 --- a/source/core/slang-zip-file-system.cpp +++ b/source/core/slang-zip-file-system.cpp @@ -430,7 +430,7 @@ SlangResult ZipFileSystemImpl::loadFile(char const* path, ISlangBlob** outBlob) } ScopedAllocation alloc; - if (!alloc.allocate(size_t(fileStat.m_uncomp_size))) + if (!alloc.allocateTerminated(size_t(fileStat.m_uncomp_size))) { return SLANG_E_OUT_OF_MEMORY; } -- cgit v1.2.3