diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-26 20:32:53 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-26 20:32:53 -0400 |
| commit | 5c2c2cfc9918bb43225159e67a851e196e17759a (patch) | |
| tree | 216009d02afe9dc17b074fdd394141ef71472268 | |
| parent | ef067bef2f2188a4b3c420cbcd8d223874888ed2 (diff) | |
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++.
28 files changed, 610 insertions, 286 deletions
diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj b/build/visual-studio/compiler-core/compiler-core.vcxproj index c721d9f81..8bddbaee3 100644 --- a/build/visual-studio/compiler-core/compiler-core.vcxproj +++ b/build/visual-studio/compiler-core/compiler-core.vcxproj @@ -290,6 +290,7 @@ <ClInclude Include="..\..\..\source\compiler-core\slang-name-convention-util.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-name.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-nvrtc-compiler.h" />
+ <ClInclude Include="..\..\..\source\compiler-core\slang-slice-allocator.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-source-loc.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-test-server-protocol.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-token-defs.h" />
@@ -332,6 +333,7 @@ <ClCompile Include="..\..\..\source\compiler-core\slang-name-convention-util.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-name.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-nvrtc-compiler.cpp" />
+ <ClCompile Include="..\..\..\source\compiler-core\slang-slice-allocator.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-source-loc.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-test-server-protocol.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-token.cpp" />
diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters index 70fd9ca5c..898f2d2ba 100644 --- a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters +++ b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters @@ -129,6 +129,9 @@ <ClInclude Include="..\..\..\source\compiler-core\slang-nvrtc-compiler.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\compiler-core\slang-slice-allocator.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\compiler-core\slang-source-loc.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -251,6 +254,9 @@ <ClCompile Include="..\..\..\source\compiler-core\slang-nvrtc-compiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\compiler-core\slang-slice-allocator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\compiler-core\slang-source-loc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -980,6 +980,15 @@ extern "C" }; #define SLANG_UUID_ISlangBlob ISlangBlob::getTypeGuid() + /* Can be requested from ISlangCastable cast to indicate the contained chars are null terminated. + */ + struct SlangTerminatedChars + { + SLANG_CLASS_GUID(0xbe0db1a8, 0x3594, 0x4603, { 0xa7, 0x8b, 0xc4, 0x86, 0x84, 0x30, 0xdf, 0xbb }); + operator const char*() const { return chars; } + char chars[1]; + }; + /** A (real or virtual) file system. Slang can make use of this interface whenever it would otherwise try to load files diff --git a/source/compiler-core/slang-artifact-associated-impl.cpp b/source/compiler-core/slang-artifact-associated-impl.cpp index 9b437b9c0..770c2601f 100644 --- a/source/compiler-core/slang-artifact-associated-impl.cpp +++ b/source/compiler-core/slang-artifact-associated-impl.cpp @@ -16,6 +16,7 @@ namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnostics !!!!!!!!!!!!!!!!!!!!!!!!!!! */ ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs): + ComBaseObject(), m_result(rhs.m_result), m_diagnostics(rhs.m_diagnostics), m_raw(rhs.m_raw.getLength() + 1) diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h index 415e01494..321717a48 100644 --- a/source/compiler-core/slang-artifact-associated-impl.h +++ b/source/compiler-core/slang-artifact-associated-impl.h @@ -37,7 +37,7 @@ public: SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE { m_result = res; } SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const CharSlice& slice) SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL appendRaw(const CharSlice& slice) SLANG_OVERRIDE; - SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return CharSliceCaster::asTerminatedCharSlice(m_raw); } + SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return SliceCaster::asTerminatedCharSlice(m_raw); } SLANG_NO_THROW virtual void SLANG_MCALL reset() SLANG_OVERRIDE; SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; @@ -50,7 +50,7 @@ public: SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; /// Default ctor - ArtifactDiagnostics() {} + ArtifactDiagnostics():ComBaseObject() {} /// Copy ctor ArtifactDiagnostics(const ThisType& rhs); @@ -61,7 +61,7 @@ protected: void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - CharSliceAllocator m_allocator; + SliceAllocator m_allocator; List<Diagnostic> m_diagnostics; SlangResult m_result = SLANG_OK; diff --git a/source/compiler-core/slang-artifact-diagnostic-util.cpp b/source/compiler-core/slang-artifact-diagnostic-util.cpp index 0f6b70ab4..3a2c64dce 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.cpp +++ b/source/compiler-core/slang-artifact-diagnostic-util.cpp @@ -6,29 +6,6 @@ namespace Slang { -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CharSliceAllocator !!!!!!!!!!!!!!!!!!!!!!!!!!! */ - -TerminatedCharSlice CharSliceAllocator::allocate(const char* in) -{ - const size_t length = ::strlen(in); - auto dst = m_arena.allocateString(in, length); - return TerminatedCharSlice(dst, length); -} - -TerminatedCharSlice CharSliceAllocator::allocate(const UnownedStringSlice& slice) -{ - const auto length = slice.getLength(); - auto dst = m_arena.allocateString(slice.begin(), length); - return TerminatedCharSlice(dst, length); -} - -TerminatedCharSlice CharSliceAllocator::allocate(const Slice<char>& slice) -{ - const auto count = slice.count; - auto dst = m_arena.allocateString(slice.begin(), count); - return TerminatedCharSlice(dst, count); -} - /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnosticsUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* static */UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity) @@ -42,7 +19,7 @@ TerminatedCharSlice CharSliceAllocator::allocate(const Slice<char>& slice) } } -/* static */SlangResult ArtifactDiagnosticUtil::splitPathLocation(CharSliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic) +/* static */SlangResult ArtifactDiagnosticUtil::splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic) { const Index lineStartIndex = pathLocation.lastIndexOf('('); if (lineStartIndex >= 0) @@ -100,7 +77,7 @@ TerminatedCharSlice CharSliceAllocator::allocate(const Slice<char>& slice) return SLANG_OK; } -/* static */SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(CharSliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics) +/* static */SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics) { List<UnownedStringSlice> splitLine; @@ -150,7 +127,7 @@ TerminatedCharSlice CharSliceAllocator::allocate(const Slice<char>& slice) String text(in); diagnostic.severity = ArtifactDiagnostic::Severity::Info; - diagnostic.text = CharSliceCaster::asTerminatedCharSlice(text); + diagnostic.text = SliceCaster::asTerminatedCharSlice(text); diagnostics->add(diagnostic); } diff --git a/source/compiler-core/slang-artifact-diagnostic-util.h b/source/compiler-core/slang-artifact-diagnostic-util.h index 5a98acd22..fe158ce38 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.h +++ b/source/compiler-core/slang-artifact-diagnostic-util.h @@ -6,59 +6,11 @@ #include "slang-artifact-associated.h" -#include "../core/slang-memory-arena.h" +#include "slang-slice-allocator.h" namespace Slang { -/* -The reason to wrap in a struct rathan than have as free functions is doing so will lead to compile time -errors with incorrect usage around temporarires. -*/ -struct CharSliceCaster -{ - /// The slice will only be in scope whilst the string is - static TerminatedCharSlice asTerminatedCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return TerminatedCharSlice(unowned.begin(), unowned.getLength()); } - - static CharSlice asCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return CharSlice(unowned.begin(), unowned.getLength()); } - -private: - // We don't want temporaries to be 'asSliced' so disable - static TerminatedCharSlice asTerminatedCharSlice(const String&& in) = delete; - static CharSlice asCharSlice(const String&& in) = delete; -}; - -SLANG_FORCE_INLINE UnownedStringSlice asStringSlice(const CharSlice& slice) -{ - return UnownedStringSlice(slice.begin(), slice.end()); -} - -SLANG_FORCE_INLINE CharSlice asCharSlice(const UnownedStringSlice& slice) -{ - return CharSlice(slice.begin(), slice.getLength()); -} - -struct CharSliceAllocator -{ - TerminatedCharSlice allocate(const Slice<char>& slice); - TerminatedCharSlice allocate(const UnownedStringSlice& slice); - TerminatedCharSlice allocate(const String& in) { return allocate(in.getUnownedSlice()); } - TerminatedCharSlice allocate(const char* in); - TerminatedCharSlice allocate(const char* start, const char* end) { return allocate(UnownedStringSlice(start, end)); } - - void deallocateAll() { m_arena.deallocateAll(); } - - CharSliceAllocator(): - m_arena(1024) - { - } -protected: - - MemoryArena m_arena; -}; - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnosticUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ - struct ArtifactDiagnosticUtil { typedef ArtifactDiagnostic::Severity Severity; @@ -67,21 +19,20 @@ struct ArtifactDiagnosticUtil static UnownedStringSlice getSeverityText(Severity severity); /// Given a path, that holds line number and potentially column number in () after path, writes result into outDiagnostic - static SlangResult splitPathLocation(CharSliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic); + static SlangResult splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic); /// Split the line (separated by :), where a path is at pathIndex static SlangResult splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List<UnownedStringSlice>& outSlices); - typedef SlangResult(*LineParser)(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic); + typedef SlangResult(*LineParser)(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic); /// Given diagnostics in inText that are colon delimited, use lineParser to do per line parsing. - static SlangResult parseColonDelimitedDiagnostics(CharSliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics); + static SlangResult parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics); /// Maybe add a note static void maybeAddNote(const UnownedStringSlice& in, IArtifactDiagnostics* diagnostics); }; - } // namespace Slang #endif diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index da9934388..672e8d8d4 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -19,7 +19,7 @@ struct Slice const T* begin() const { return data; } const T* end() const { return data + count; } - const T& operator[](Index index) { SLANG_ASSERT(index >= 0 && index < count); return data[index]; } + const T& operator[](Index index) const { SLANG_ASSERT(index >= 0 && index < count); return data[index]; } Slice() :count(0), data(nullptr) {} Slice(const T* inData, Count inCount) : @@ -31,6 +31,12 @@ struct Slice Count count; }; +template <typename T> +SLANG_FORCE_INLINE Slice<T> makeSlice(const T* inData, Count inCount) +{ + return Slice<T>(inData, inCount); +} + struct CharSlice : public Slice<char> { typedef CharSlice ThisType; @@ -52,6 +58,9 @@ struct TerminatedCharSlice : public CharSlice SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return Super::operator==(rhs); } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + /// Make convertable to char* + SLANG_FORCE_INLINE operator const char* () const { return data; } + explicit TerminatedCharSlice(const char* in) :Super(in) {} TerminatedCharSlice(const char* in, Count inCount) :Super(in, inCount) { SLANG_ASSERT(in[inCount] == 0); } TerminatedCharSlice() :Super("", 0) {} diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index aa3a44975..f134d77f5 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -68,13 +68,13 @@ void* DownstreamCompilerBase::getObject(const Guid& guid) static bool _isContentsInFile(const DownstreamCompileOptions& options) { - if (options.sourceContentsPath.getLength() <= 0) + if (options.sourceContentsPath.count <= 0) { return false; } // We can see if we can load it - if (File::exists(options.sourceContentsPath)) + if (File::exists(asStringSlice(options.sourceContentsPath))) { // Here we look for the file on the regular file system (as opposed to using the // ISlangFileSystem. This is unfortunate but necessary - because when we call out @@ -87,9 +87,9 @@ static bool _isContentsInFile(const DownstreamCompileOptions& options) // file system access. String readContents; - if (SLANG_SUCCEEDED(File::readAllText(options.sourceContentsPath, readContents))) + if (SLANG_SUCCEEDED(File::readAllText(asStringSlice(options.sourceContentsPath), readContents))) { - return options.sourceContents == readContents.getUnownedSlice(); + return asStringSlice(options.sourceContents) == readContents.getUnownedSlice(); } } return false; @@ -102,17 +102,30 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio CompileOptions options(inOptions); - auto helper = DefaultArtifactHelper::getSingleton(); + // Work out the ArtifactDesc + const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - // Find all the files that will be produced + auto helper = DefaultArtifactHelper::getSingleton(); + // Holds all of the artifacts that are relatated to the final artifact - such as debug files, ancillary file and lock files auto artifactList = CastableList::create(); + // It may be necessary to produce a temporary file 'lock file'. ComPtr<IFileArtifactRepresentation> lockFile; - if (options.modulePath.getLength() == 0 || options.sourceContents.getLength() != 0) + // The allocator can be used for items that are not kept in scope by the options + SliceAllocator allocator; + + // We may need to produce a new list of source files, use this list to hold them. + List<TerminatedCharSlice> sourceFiles; + + // Copy over all of the source files that are explicitly set, to sourceFiles which well use + // to hold the actual list of sourceFiles required. + sourceFiles.addRange(inOptions.sourceFiles.begin(), inOptions.sourceFiles.count); + + if (options.modulePath.count == 0 || options.sourceContents.count != 0) { - String modulePath = options.modulePath; + String modulePath = asString(options.modulePath); // If there is no module path, generate one. if (modulePath.getLength() == 0) @@ -125,31 +138,24 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio artifactList->add(lockArtifact); modulePath = lockFile->getPath(); - options.modulePath = modulePath; + options.modulePath = allocator.allocate(modulePath); } - + if (_isContentsInFile(options)) { - options.sourceFiles.add(options.sourceContentsPath); + sourceFiles.add(options.sourceContentsPath); } else { - String compileSourcePath = modulePath; - - compileSourcePath.append("-src"); + // Work out the ArtifactDesc for the source language + const auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage); - // Make the temporary filename have the appropriate extension. - if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_C) - { - compileSourcePath.append(".c"); - } - else - { - compileSourcePath.append(".cpp"); - } + // Work out the name for the source + StringBuilder compileSourcePath; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(sourceDesc, (modulePath + "-src").getUnownedSlice(), compileSourcePath)); // Write it out - SLANG_RETURN_ON_FAIL(File::writeAllText(compileSourcePath, options.sourceContents)); + SLANG_RETURN_ON_FAIL(File::writeAllText(compileSourcePath, asStringSlice(options.sourceContents))); // Create the reference to the file auto fileRep = FileArtifactRepresentation::create(IFileArtifactRepresentation::Kind::Owned, compileSourcePath.getUnownedSlice(), lockFile, nullptr); @@ -159,29 +165,29 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio artifactList->add(fileArtifact); // Add it as a source file - options.sourceFiles.add(compileSourcePath); + sourceFiles.add(allocator.allocate(compileSourcePath)); } // There is no source contents - options.sourceContents = String(); - options.sourceContentsPath = String(); + options.sourceContents = TerminatedCharSlice(); + options.sourceContentsPath = TerminatedCharSlice(); } + options.sourceFiles = SliceCaster::asSlice(sourceFiles); + // Append command line args to the end of cmdLine using the target specific function for the specified options SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); // The 'mainArtifact' is the main product produced from the compilation - the executable/sharedlibrary/object etc ComPtr<IArtifact> mainArtifact; { - const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - List<ComPtr<IArtifact>> artifacts; SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); for (IArtifact* artifact : artifacts) { // The main artifact must be in the list, so add it if we find it - if (artifact->getDesc() == desc) + if (artifact->getDesc() == targetDesc) { SLANG_ASSERT(mainArtifact == nullptr); mainArtifact = artifact; @@ -249,8 +255,10 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } } - auto artifact = ArtifactUtil::createArtifactForCompileTarget(options.targetType); + // Create the result artifact + auto artifact = ArtifactUtil::createArtifact(targetDesc); + // Createa the diagnostics auto diagnostics = ArtifactDiagnostics::create(); SLANG_RETURN_ON_FAIL(parseOutput(exeRes, diagnostics)); @@ -259,7 +267,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio artifact->addAssociated(diagnostics); // Find the rep from the 'main' artifact, we'll just use the same representation on the output - // artifact. Sharing is needed, because the rep owns the file. + // artifact. Sharing is desirable, because the rep owns the file. if (auto fileRep = mainArtifact ? findRepresentation<IFileArtifactRepresentation>(mainArtifact) : nullptr) { artifact->addRepresentation(fileRep); @@ -272,7 +280,6 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } *outArtifact = artifact.detach(); - return SLANG_OK; } diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 4fca3949a..9fea5cb05 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -90,8 +90,8 @@ struct DownstreamCompileOptions struct Define { - String nameWithSig; ///< If macro takes parameters include in brackets - String value; + TerminatedCharSlice nameWithSig; ///< If macro takes parameters include in brackets + TerminatedCharSlice value; }; struct CapabilityVersion @@ -119,38 +119,38 @@ struct DownstreamCompileOptions /// The path/name of the output module. Should not have the extension, as that will be added for each of the target types. /// If not set a module path will be internally generated internally on a command line based compiler - String modulePath; + TerminatedCharSlice modulePath; - List<Define> defines; + Slice<Define> defines; /// The contents of the source to compile. This can be empty is sourceFiles is set. /// If the compiler is a commandLine file this source will be written to a temporary file. - String sourceContents; + TerminatedCharSlice sourceContents; /// 'Path' that the contents originated from. NOTE! This is for reporting only and doesn't have to exist on file system - String sourceContentsPath; + TerminatedCharSlice sourceContentsPath; /// The names/paths of source to compile. This can be empty if sourceContents is set. - List<String> sourceFiles; + Slice<TerminatedCharSlice> sourceFiles; - List<String> includePaths; - List<String> libraryPaths; + Slice<TerminatedCharSlice> includePaths; + Slice<TerminatedCharSlice> libraryPaths; /// Libraries to link against. - List<ComPtr<IArtifact>> libraries; + Slice<IArtifact*> libraries; - List<CapabilityVersion> requiredCapabilityVersions; + Slice<CapabilityVersion> requiredCapabilityVersions; /// For compilers/compiles that require an entry point name, else can be empty - String entryPointName; + TerminatedCharSlice entryPointName; /// Profile name to use, only required for compiles that need to compile against a a specific profiles. /// Profile names are tied to compilers and targets. - String profileName; + TerminatedCharSlice profileName; /// The stage being compiled for SlangStage stage = SLANG_STAGE_NONE; /// Arguments that are specific to a particular compiler implementation. - List<String> compilerSpecificArguments; + Slice<TerminatedCharSlice> compilerSpecificArguments; /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. ISlangFileSystemExt* fileSystemExt = nullptr; diff --git a/source/compiler-core/slang-downstream-dep1.cpp b/source/compiler-core/slang-downstream-dep1.cpp index 0745fd9dc..ac66b4502 100644 --- a/source/compiler-core/slang-downstream-dep1.cpp +++ b/source/compiler-core/slang-downstream-dep1.cpp @@ -7,6 +7,8 @@ #include "../core/slang-castable-util.h" +#include "slang-slice-allocator.h" + namespace Slang { @@ -96,7 +98,7 @@ DownstreamCompilerAdapter_Dep1::DownstreamCompilerAdapter_Dep1(DownstreamCompile SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOptions, IArtifact** outArtifact) { typedef DownstreamCompileOptions_Dep1::SomeEnum SomeEnum; - + // Convert to the Deps1 compile options DownstreamCompileOptions_Dep1 options; @@ -112,27 +114,27 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti options.flags = inOptions.flags; options.platform = SomeEnum(inOptions.platform); - options.modulePath = inOptions.modulePath; + options.modulePath = asString(inOptions.modulePath); for (auto& src : inOptions.defines) { DownstreamCompileOptions_Dep1::Define dst; - dst.nameWithSig = src.nameWithSig; - dst.value = src.value; + dst.nameWithSig = asStringSlice(src.nameWithSig); + dst.value = asStringSlice(src.value); options.defines.add(dst); } - options.sourceContents = inOptions.sourceContents; - options.sourceContentsPath = inOptions.sourceContentsPath; + options.sourceContents = asStringSlice(inOptions.sourceContents); + options.sourceContentsPath = asStringSlice(inOptions.sourceContentsPath); - options.sourceFiles = inOptions.sourceFiles; + options.sourceFiles = SliceConverter::toList(inOptions.sourceFiles); - options.includePaths = inOptions.includePaths; - options.libraryPaths = inOptions.libraryPaths; + options.includePaths = SliceConverter::toList(inOptions.includePaths); + options.libraryPaths = SliceConverter::toList(inOptions.libraryPaths); - options.libraries = inOptions.libraries; + options.libraries = SliceConverter::toComPtrList(inOptions.libraries); for (auto& src : inOptions.requiredCapabilityVersions) { @@ -148,12 +150,12 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti options.requiredCapabilityVersions.add(capVer); } - options.entryPointName = inOptions.entryPointName; - options.profileName = inOptions.profileName; + options.entryPointName = asStringSlice(inOptions.entryPointName); + options.profileName = asStringSlice(inOptions.profileName); options.stage = inOptions.stage; - options.compilerSpecificArguments = inOptions.compilerSpecificArguments; + options.compilerSpecificArguments = SliceConverter::toList(inOptions.compilerSpecificArguments); options.fileSystemExt = inOptions.fileSystemExt; options.sourceManager = inOptions.sourceManager; @@ -161,7 +163,7 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti RefPtr<DownstreamCompileResult_Dep1> result; SLANG_RETURN_ON_FAIL(m_dep->compile(options, result)); - typedef CharSliceCaster Caster; + typedef SliceCaster Caster; ComPtr<IArtifact> artifact = ArtifactUtil::createArtifactForCompileTarget(options.targetType); diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 3fc7224f3..6aa065afd 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -196,7 +196,7 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, IArtifactDiagnostics::Diagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, IArtifactDiagnostics::Diagnostic& outDiagnostic) { /* tests/diagnostics/syntax-error-intrinsic.slang:14:2: error: expected expression */ if (lineSlices.getCount() < 5) @@ -251,7 +251,7 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif { diagnostics->appendRaw(asCharSlice(diagnosticsSlice)); - CharSliceAllocator allocator; + SliceAllocator allocator; List<IArtifactDiagnostics::Diagnostic> parsedDiagnostics; SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticsSlice, 0, _parseDiagnosticLine, diagnostics); @@ -279,7 +279,7 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath - if (options.sourceFiles.getCount() > 0) + if (options.sourceFiles.count > 0) { return SLANG_FAIL; } @@ -316,8 +316,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif // Create blob from the string ComPtr<IDxcBlobEncoding> dxcSourceBlob; SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned( - (LPBYTE)hlslSource.getBuffer(), - (UINT32)hlslSource.getLength(), + (LPBYTE)hlslSource.data, + (UINT32)hlslSource.count, 0, dxcSourceBlob.writeRef())); @@ -325,11 +325,11 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif // Add all compiler specific options List<OSString> compilerSpecific; - compilerSpecific.setCount(options.compilerSpecificArguments.getCount()); + compilerSpecific.setCount(options.compilerSpecificArguments.count); - for (Index i = 0; i < options.compilerSpecificArguments.getCount(); ++i) + for (Index i = 0; i < options.compilerSpecificArguments.count; ++i) { - compilerSpecific[i] = options.compilerSpecificArguments[i].toWString(); + compilerSpecific[i] = asString(options.compilerSpecificArguments[i]).toWString(); args.add(compilerSpecific[i]); } @@ -398,7 +398,7 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif // args.add(L"-no-warnings"); - String profileName = options.profileName; + String profileName = asString(options.profileName); // If we are going to link we have to compile in the lib profile style if (libraries.getCount()) { @@ -418,7 +418,7 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif } } - OSString wideEntryPointName = options.entryPointName.toWString(); + OSString wideEntryPointName = asString(options.entryPointName).toWString(); OSString wideProfileName = profileName.toWString(); if (options.flags & CompileOptions::Flag::EnableFloat16) @@ -429,10 +429,10 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif SearchDirectoryList searchDirectories; for (const auto& includePath : options.includePaths) { - searchDirectories.searchDirectories.add(includePath); + searchDirectories.searchDirectories.add(asString(includePath)); } - OSString sourcePath = options.sourceContentsPath.toWString(); + OSString sourcePath = asString(options.sourceContentsPath).toWString(); DxcIncludeHandler includeHandler(&searchDirectories, options.fileSystemExt, options.sourceManager); @@ -476,13 +476,13 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif // Add the compiled blob name String name; - if (options.modulePath.getLength()) + if (options.modulePath.count) { - name = Path::getFileNameWithoutExt(options.modulePath); + name = Path::getFileNameWithoutExt(asString(options.modulePath)); } - else if (options.sourceContentsPath.getLength()) + else if (options.sourceContentsPath.count) { - name = Path::getFileNameWithoutExt(options.sourceContentsPath); + name = Path::getFileNameWithoutExt(asString(options.sourceContentsPath)); } // Add the blob with name @@ -508,7 +508,7 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif } // Use the original profile name - wideProfileName = options.profileName.toWString(); + wideProfileName = asString(options.profileName).toWString(); ComPtr<IDxcOperationResult> linkDxcResult; SLANG_RETURN_ON_FAIL(linker->Link(wideEntryPointName.begin(), wideProfileName.begin(), linkLibraryNames.getBuffer(), UINT32(librariesCount), nullptr, 0, linkDxcResult.writeRef())); diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index c07952d2d..03eaa8e34 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -153,7 +153,7 @@ SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) { /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected token '@' */ if (lineSlices.getCount() < 3) @@ -183,7 +183,7 @@ static SlangResult _parseDiagnosticLine(CharSliceAllocator& allocator, const Uno SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath - if (options.sourceFiles.getCount() > 0) + if (options.sourceFiles.count > 0) { return SLANG_FAIL; } @@ -204,7 +204,7 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif SearchDirectoryList searchDirectories; for (const auto& includePath : options.includePaths) { - searchDirectories.searchDirectories.add(includePath); + searchDirectories.searchDirectories.add(asString(includePath)); } // Use the default fileSystemExt is not set @@ -213,9 +213,9 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif FxcIncludeHandler fxcIncludeHandlerStorage(&searchDirectories, options.fileSystemExt, options.sourceManager); if (options.fileSystemExt) { - if (options.sourceContentsPath.getLength() > 0) + if (options.sourceContentsPath.count > 0) { - fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(options.sourceContentsPath); + fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(asString(options.sourceContentsPath)); } includeHandler = &fxcIncludeHandlerStorage; } @@ -223,13 +223,13 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif List<D3D_SHADER_MACRO> dxMacrosStorage; D3D_SHADER_MACRO const* dxMacros = nullptr; - if (options.defines.getCount() > 0) + if (options.defines.count > 0) { for (const auto& define : options.defines) { D3D_SHADER_MACRO dxMacro; - dxMacro.Name = define.nameWithSig.getBuffer(); - dxMacro.Definition = define.value.getBuffer(); + dxMacro.Name = define.nameWithSig; + dxMacro.Definition = define.value; dxMacrosStorage.add(dxMacro); } D3D_SHADER_MACRO nullTerminator = { 0, 0 }; @@ -278,12 +278,12 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif ComPtr<ID3DBlob> diagnosticsBlob; HRESULT hr = m_compile( options.sourceContents.begin(), - options.sourceContents.getLength(), - options.sourceContentsPath.getBuffer(), + options.sourceContents.count, + options.sourceContentsPath, dxMacros, includeHandler, - options.entryPointName.getBuffer(), - options.profileName.getBuffer(), + options.entryPointName, + options.profileName, flags, 0, // unused: effect flags codeBlob.writeRef(), @@ -294,7 +294,7 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif // HRESULT is compatible with SlangResult diagnostics->setResult(hr); - CharSliceAllocator allocator; + SliceAllocator allocator; if (diagnosticsBlob) { diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 428da1632..7bbde64c4 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -166,7 +166,7 @@ enum class LineParseResult } // anonymous -static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, LineParseResult& outLineParseResult, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedStringSlice& line, LineParseResult& outLineParseResult, ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef Diagnostic::Severity Severity; @@ -353,10 +353,10 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow { LineParseResult prevLineResult = LineParseResult::Ignore; - CharSliceAllocator allocator; + SliceAllocator allocator; diagnostics->reset(); - diagnostics->setRaw(CharSliceCaster::asCharSlice(exeRes.standardError)); + diagnostics->setRaw(SliceCaster::asCharSlice(exeRes.standardError)); // We hold in workDiagnostics so as it is more convenient to append to the last with a continuation // also means we don't hold the allocations of building up continuations, just the results when finally allocated at the end @@ -434,7 +434,7 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow /* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) { - SLANG_ASSERT(options.modulePath.getLength()); + SLANG_ASSERT(options.modulePath.count); outArtifacts.clear(); @@ -442,7 +442,7 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, options.modulePath.getUnownedSlice(), builder)); + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); auto fileRep = FileArtifactRepresentation::create(IFileArtifactRepresentation::Kind::Owned, builder.getUnownedSlice(), lockFile, nullptr); auto artifact = ArtifactUtil::createArtifact(desc); @@ -456,8 +456,8 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow /* static */SlangResult GCCDownstreamCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { - SLANG_ASSERT(options.sourceContents.getLength() == 0); - SLANG_ASSERT(options.modulePath.getLength()); + SLANG_ASSERT(options.sourceContents.count == 0); + SLANG_ASSERT(options.modulePath.count); PlatformKind platformKind = (options.platform == PlatformKind::Unknown) ? PlatformUtil::getPlatformKind() : options.platform; @@ -539,7 +539,7 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow } StringBuilder moduleFilePath; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(targetDesc, options.modulePath.getUnownedSlice(), moduleFilePath)); + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(targetDesc, asStringSlice(options.modulePath), moduleFilePath)); cmdLine.addArg("-o"); cmdLine.addArg(moduleFilePath); @@ -579,9 +579,9 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow builder << "-D"; builder << define.nameWithSig; - if (define.value.getLength()) + if (define.value.count) { - builder << "=" << define.value; + builder << "=" << asStringSlice(define.value); } cmdLine.addArg(builder); @@ -591,7 +591,7 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow for (const auto& include : options.includePaths) { cmdLine.addArg("-I"); - cmdLine.addArg(include); + cmdLine.addArg(asString(include)); } // Link options @@ -616,12 +616,12 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow // Files to compile for (const auto& sourceFile : options.sourceFiles) { - cmdLine.addArg(sourceFile); + cmdLine.addArg(asString(sourceFile)); } // Add the library paths - if (options.libraryPaths.getCount() && options.targetType == SLANG_HOST_EXECUTABLE) + if (options.libraryPaths.count && options.targetType == SLANG_HOST_EXECUTABLE) { cmdLine.addArg("-Wl,-rpath,$ORIGIN"); } diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 3a96ed69d..a896e4278 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -98,7 +98,7 @@ SlangResult GlslangDownstreamCompiler::_invoke(glslang_CompileRequest_1_1& reque return err ? SLANG_FAIL : SLANG_OK; } -static SlangResult _parseDiagnosticLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) { /* ERROR: tests/diagnostics/syntax-error-intrinsic.slang:13: '@' : unexpected token */ @@ -128,7 +128,7 @@ static SlangResult _parseDiagnosticLine(CharSliceAllocator& allocator, const Uno SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath - if (options.sourceFiles.getCount() > 0) + if (options.sourceFiles.count > 0) { return SLANG_FAIL; } @@ -156,7 +156,7 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IA request.sizeInBytes = sizeof(request); request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; - request.sourcePath = options.sourceContentsPath.getBuffer(); + request.sourcePath = options.sourceContentsPath; request.slangStage = options.stage; @@ -201,9 +201,9 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IA if (SLANG_FAILED(invokeResult)) { - diagnostics->setRaw(CharSliceCaster::asCharSlice(diagnosticOutput)); + diagnostics->setRaw(SliceCaster::asCharSlice(diagnosticOutput)); - CharSliceAllocator allocator; + SliceAllocator allocator; SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticOutput.getUnownedSlice(), 1, _parseDiagnosticLine, diagnostics); SLANG_UNUSED(diagnosticParseRes); diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 99a5cc346..2c01dc633 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -171,7 +171,7 @@ SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseLocation(CharSliceAllocator& allocator, const UnownedStringSlice& in, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseLocation(SliceAllocator& allocator, const UnownedStringSlice& in, ArtifactDiagnostic& outDiagnostic) { const Index startIndex = in.indexOf('('); @@ -205,7 +205,7 @@ static bool _hasDriveLetter(const UnownedStringSlice& line) return line.getLength() > 2 && line[1] == ':' && _isDriveLetter(line[0]); } -static SlangResult _parseNVRTCLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef ArtifactDiagnostic::Severity Severity; @@ -618,8 +618,9 @@ SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompil } // Let's see if one of the paths finds cuda_fp16.h - for (const auto& includePath : options.includePaths) + for (const auto& curIncludePath : options.includePaths) { + const String includePath = asString(curIncludePath); const String checkPath = Path::combine(includePath, g_fp16HeaderName); if (File::exists(checkPath)) { @@ -645,7 +646,7 @@ SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompil SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& options, IArtifact** outArtifact) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath - if (options.sourceFiles.getCount() > 0) + if (options.sourceFiles.count > 0) { return SLANG_FAIL; } @@ -696,10 +697,10 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt { StringBuilder builder; builder << "-D"; - builder << define.nameWithSig; - if (define.value.getLength()) + builder << asStringSlice(define.nameWithSig); + if (define.value.count) { - builder << "=" << define.value; + builder << "=" << asStringSlice(define.value); } cmdLine.addArg(builder); @@ -709,7 +710,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt for (const auto& include : options.includePaths) { cmdLine.addArg("-I"); - cmdLine.addArg(include); + cmdLine.addArg(asString(include)); } SLANG_RETURN_ON_FAIL(_maybeAddHalfSupport(options, cmdLine)); @@ -819,7 +820,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt SLANG_ASSERT(headers.getCount() == headerIncludeNames.getCount()); nvrtcProgram program = nullptr; - nvrtcResult res = m_nvrtcCreateProgram(&program, options.sourceContents.getBuffer(), options.sourceContentsPath.getBuffer(), + nvrtcResult res = m_nvrtcCreateProgram(&program, options.sourceContents, options.sourceContentsPath, (int) headers.getCount(), headers.getBuffer(), headerIncludeNames.getBuffer()); @@ -859,10 +860,10 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt SLANG_NVRTC_RETURN_ON_FAIL(m_nvrtcGetProgramLog(program, dst)); rawDiagnostics.appendInPlace(dst, Index(logSize)); - diagnostics->setRaw(CharSliceCaster::asCharSlice(rawDiagnostics)); + diagnostics->setRaw(SliceCaster::asCharSlice(rawDiagnostics)); } - CharSliceAllocator allocator; + SliceAllocator allocator; // Parse the diagnostics here for (auto line : LineParser(rawDiagnostics.getUnownedSlice())) diff --git a/source/compiler-core/slang-slice-allocator.cpp b/source/compiler-core/slang-slice-allocator.cpp new file mode 100644 index 000000000..9985f6b19 --- /dev/null +++ b/source/compiler-core/slang-slice-allocator.cpp @@ -0,0 +1,94 @@ +// slang-slice-allocator.cpp +#include "slang-slice-allocator.h" + +#include "../core/slang-blob.h" + +namespace Slang { + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceConverter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */ List<String> SliceConverter::toList(const Slice<TerminatedCharSlice>& in) +{ + List<String> list; + const auto count = in.count; + + list.setCount(count); + for (Index i = 0; i < count; ++i) + { + list[i] = asStringSlice(in[i]); + } + return list; +} + +/* static */TerminatedCharSlice SliceConverter::toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob) +{ + const auto size = blob->getBufferSize(); + + if (size == 0) + { + return TerminatedCharSlice(); + } + + // If there is a 0 at the end byte, we are zero terminated + const char* chars = (const char*)blob->getBufferPointer(); + if (chars[size - 1] == 0) + { + return TerminatedCharSlice(chars, Count(size - 1)); + } + + // See if it has a castable interface + ComPtr<ICastable> castable; + if (SLANG_SUCCEEDED(blob->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef()))) + { + if (castable->castAs(SlangTerminatedChars::getTypeGuid())) + { + return TerminatedCharSlice(chars, Count(size)); + } + } + + // We are out of options, we just have to allocate with zero termination which allocateString does + auto dst = allocator.getArena().allocateString(chars, Count(size)); + return TerminatedCharSlice(dst, Count(size)); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceAllocator !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +TerminatedCharSlice SliceAllocator::allocate(const char* in) +{ + const size_t length = ::strlen(in); + auto dst = m_arena.allocateString(in, length); + return TerminatedCharSlice(dst, length); +} + +TerminatedCharSlice SliceAllocator::allocate(const UnownedStringSlice& slice) +{ + const auto length = slice.getLength(); + auto dst = m_arena.allocateString(slice.begin(), length); + return TerminatedCharSlice(dst, length); +} + +TerminatedCharSlice SliceAllocator::allocate(const Slice<char>& slice) +{ + const auto count = slice.count; + auto dst = m_arena.allocateString(slice.begin(), count); + return TerminatedCharSlice(dst, count); +} + +Slice<TerminatedCharSlice> SliceAllocator::allocate(const List<String>& in) +{ + const auto count = in.getCount(); + if (count == 0) + { + return Slice<TerminatedCharSlice>(nullptr, 0); + } + + auto dst = m_arena.allocateArray<TerminatedCharSlice>(count); + for (Index i = 0; i < count; ++i) + { + dst[i] = allocate(in[i]); + } + + return Slice<TerminatedCharSlice>(dst, count); +} + +} // namespace Slang diff --git a/source/compiler-core/slang-slice-allocator.h b/source/compiler-core/slang-slice-allocator.h new file mode 100644 index 000000000..41ed3943a --- /dev/null +++ b/source/compiler-core/slang-slice-allocator.h @@ -0,0 +1,103 @@ +// slang-slice-allocator.h +#ifndef SLANG_SLICE_ALLOCATOR_H +#define SLANG_SLICE_ALLOCATOR_H + +// Has definition of CharSlice +#include "slang-artifact.h" + +#include "../core/slang-memory-arena.h" + +namespace Slang +{ + +/* +The reason to wrap in a struct rather than have as free functions is doing so will lead to compile time +errors with incorrect usage around temporaries. +*/ +struct SliceCaster +{ + /// The slice will only be in scope whilst the string is + static TerminatedCharSlice asTerminatedCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return TerminatedCharSlice(unowned.begin(), unowned.getLength()); } + + static CharSlice asCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return CharSlice(unowned.begin(), unowned.getLength()); } + + template <typename T> + static Slice<T*> asSlice(const List<ComPtr<T>>& list) { return makeSlice((T*const*)list.getBuffer(), list.getCount()); } + + /// Get a list as a slice + template <typename T> + static Slice<T> asSlice(const List<T>& list) { return Slice<T>(list.getBuffer(), list.getCount()); } + +private: + /// We don't want to make a temporary list into a slice.. + template <typename T> + static Slice<T> asSlice(const List<T>&& list) = delete; + // We don't want temporaries to be 'asSliced' so disable + static TerminatedCharSlice asTerminatedCharSlice(const String&& in) = delete; + static CharSlice asCharSlice(const String&& in) = delete; +}; + +struct SliceAllocator; + +struct SliceConverter +{ + /// Convert into a list of strings + static List<String> toList(const Slice<TerminatedCharSlice>& in); + + /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does + static TerminatedCharSlice toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob); + + template <typename T> + static List<ComPtr<T>> toComPtrList(const Slice<T*>& in) + { + ISlangUnknown* check = (T*)nullptr; + SLANG_UNUSED(check); + List<ComPtr<T>> list; + list.setCount(in.count); + for (Index i = 0; i < in.count; ++i) list[i] = ComPtr<T>(in[i]); + return list; + } +}; + +SLANG_FORCE_INLINE UnownedStringSlice asStringSlice(const CharSlice& slice) +{ + return UnownedStringSlice(slice.begin(), slice.end()); +} + +SLANG_FORCE_INLINE CharSlice asCharSlice(const UnownedStringSlice& slice) +{ + return CharSlice(slice.begin(), slice.getLength()); +} + +SLANG_FORCE_INLINE String asString(const CharSlice& slice) +{ + return String(slice.begin(), slice.end()); +} + +struct SliceAllocator +{ + TerminatedCharSlice allocate(const Slice<char>& slice); + TerminatedCharSlice allocate(const UnownedStringSlice& slice); + TerminatedCharSlice allocate(const String& in) { return allocate(in.getUnownedSlice()); } + TerminatedCharSlice allocate(const char* in); + TerminatedCharSlice allocate(const char* start, const char* end) { return allocate(UnownedStringSlice(start, end)); } + + Slice<TerminatedCharSlice> allocate(const List<String>& in); + + /// Get the backing arena + MemoryArena& getArena() { return m_arena; } + + void deallocateAll() { m_arena.deallocateAll(); } + + SliceAllocator(): + m_arena(1024) + { + } +protected: + + MemoryArena m_arena; +}; + +} // namespace Slang + +#endif diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index ff3f378d6..c1fb89555 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -32,7 +32,9 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact /* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) { - SLANG_ASSERT(options.modulePath.getLength()); + SLANG_ASSERT(options.modulePath.count); + + const String modulePath = asString(options.modulePath); const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); @@ -42,28 +44,29 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, options.modulePath.getUnownedSlice(), builder)); + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, modulePath.getUnownedSlice(), builder)); _addFile(builder, desc, lockFile, outArtifacts); } if (flags & ProductFlag::Miscellaneous) { - _addFile(options.modulePath + ".ilk", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); + + _addFile(modulePath + ".ilk", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) { - _addFile(options.modulePath + ".exp", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); - _addFile(options.modulePath + ".lib", ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile(modulePath + ".exp", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); + _addFile(modulePath + ".lib", ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); } } if (flags & ProductFlag::Compile) { - _addFile(options.modulePath + ".obj", ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile(modulePath + ".obj", ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); } if (flags & ProductFlag::Debug) { // TODO(JS): Could try and determine based on debug information - _addFile(options.modulePath + ".pdb", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::DebugInfo, targetDesc), lockFile, outArtifacts); + _addFile(modulePath + ".pdb", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::DebugInfo, targetDesc), lockFile, outArtifacts); } return SLANG_OK; @@ -71,8 +74,8 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact /* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { - SLANG_ASSERT(options.sourceContents.getLength() == 0); - SLANG_ASSERT(options.modulePath.getLength()); + SLANG_ASSERT(options.sourceContents.count == 0); + SLANG_ASSERT(options.modulePath.count); // https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019 @@ -130,7 +133,7 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact { // Generate complete debugging information cmdLine.addArg("/Zi"); - cmdLine.addPrefixPathArg("/Fd", options.modulePath, ".pdb"); + cmdLine.addPrefixPathArg("/Fd", asString(options.modulePath), ".pdb"); } switch (options.optimizationLevel) @@ -179,6 +182,8 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact } } + const auto modulePath = asString(options.modulePath); + switch (options.targetType) { case SLANG_SHADER_SHARED_LIBRARY: @@ -193,29 +198,29 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact cmdLine.addArg("/LD"); } - cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".dll"); + cmdLine.addPrefixPathArg("/Fe", modulePath, ".dll"); break; } case SLANG_HOST_EXECUTABLE: { - cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".exe"); + cmdLine.addPrefixPathArg("/Fe", modulePath, ".exe"); break; } default: break; } // Object file specify it's location - needed if we are out - cmdLine.addPrefixPathArg("/Fo", options.modulePath, ".obj"); + cmdLine.addPrefixPathArg("/Fo", modulePath, ".obj"); // Add defines for (const auto& define : options.defines) { StringBuilder builder; builder << "/D"; - builder << define.nameWithSig; - if (define.value.getLength()) + builder << asStringSlice(define.nameWithSig); + if (define.value.count) { - builder << "=" << define.value; + builder << "=" << asStringSlice(define.value); } cmdLine.addArg(builder); @@ -225,7 +230,7 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact for (const auto& include : options.includePaths) { cmdLine.addArg("/I"); - cmdLine.addArg(include); + cmdLine.addArg(asString(include)); } // https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2019 @@ -234,7 +239,7 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact // Files to compile for (const auto& sourceFile : options.sourceFiles) { - cmdLine.addArg(sourceFile); + cmdLine.addArg(asString(sourceFile)); } // Link options (parameters past /link go to linker) @@ -297,7 +302,7 @@ static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnost return SLANG_OK; } -static SlangResult _parseVisualStudioLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) { typedef IArtifactDiagnostics::Diagnostic Diagnostic; @@ -425,9 +430,9 @@ static SlangResult _parseVisualStudioLine(CharSliceAllocator& allocator, const U { diagnostics->reset(); - diagnostics->setRaw(CharSliceCaster::asTerminatedCharSlice(exeRes.standardOutput)); + diagnostics->setRaw(SliceCaster::asTerminatedCharSlice(exeRes.standardOutput)); - CharSliceAllocator allocator; + SliceAllocator allocator; for (auto line : LineParser(exeRes.standardOutput.getUnownedSlice())) { 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<char*>(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<uint8_t>&& data) : m_data(data) {} + void* getObject(const Guid& guid); + void operator=(const ThisType& rhs) = delete; List<uint8_t> m_data; @@ -96,10 +107,22 @@ 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<ISlangBlob> moveCreate(uint8_t* data, size_t dataCount) - { - RawBlob* blob = new RawBlob; - blob->m_data.attach(data, dataCount); - return ComPtr<ISlangBlob>(blob); - } static ComPtr<ISlangBlob> 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<ISlangUnknown> m_scope; ComPtr<ISlangBlob> m_blob; + ComPtr<ICastable> 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; } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index c1f25a012..18c92ec1a 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -927,6 +927,8 @@ namespace Slang RefPtr<ExtensionTracker> extensionTracker = _newExtensionTracker(target); PassThroughMode compilerType; + SliceAllocator allocator; + if (auto endToEndReq = isPassThroughEnabled()) { compilerType = endToEndReq->m_passThrough; @@ -966,6 +968,11 @@ namespace Slang typedef DownstreamCompileOptions CompileOptions; CompileOptions options; + List<DownstreamCompileOptions::CapabilityVersion> requiredCapabilityVersions; + List<String> compilerSpecificArguments; + List<ComPtr<IArtifact>> libraries; + List<String> libraryPaths; + // Set compiler specific args { auto linkage = getLinkage(); @@ -977,7 +984,7 @@ namespace Slang auto& args = linkage->m_downstreamArgs.getArgsAt(nameIndex); for (const auto& arg : args.m_args) { - options.compilerSpecificArguments.add(arg.value); + compilerSpecificArguments.add(arg.value); } } } @@ -1041,13 +1048,12 @@ namespace Slang } } - // If emitted source is required, emit and set the path if (_useEmittedSource(compiler, translationUnit)) { // If it's not file based we can set an appropriate path name, and it doesn't matter if it doesn't // exist on the file system - options.sourceContentsPath = calcSourcePathForEntryPoints(); + options.sourceContentsPath = allocator.allocate(calcSourcePathForEntryPoints()); CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker); @@ -1063,8 +1069,8 @@ namespace Slang const SourceFile* sourceFile = sourceFiles[0]; - options.sourceContentsPath = sourceFile->getPathInfo().foundPath; - options.sourceContents = sourceFile->getContent(); + options.sourceContentsPath = SliceCaster::asTerminatedCharSlice(sourceFile->getPathInfo().foundPath); + options.sourceContents = SliceConverter::toTerminatedCharSlice(allocator, sourceFile->getContentBlob()); } } else @@ -1083,9 +1089,9 @@ namespace Slang metadata = findAssociated<IArtifactPostEmitMetadata>(sourceArtifact); ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::No, blob.writeRef())); + SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef())); - options.sourceContents = StringUtil::getString(blob); + options.sourceContents = SliceConverter::toTerminatedCharSlice(allocator, blob); } // Add any preprocessor definitions associated with the linkage @@ -1104,6 +1110,7 @@ namespace Slang } } + // If we have an extension tracker, we may need to set options such as SPIR-V version // and CUDA Shader Model. if (extensionTracker) @@ -1119,7 +1126,7 @@ namespace Slang version.kind = DownstreamCompileOptions::CapabilityVersion::Kind::CUDASM; version.version = cudaTracker->m_smVersion; - options.requiredCapabilityVersions.add(version); + requiredCapabilityVersions.add(version); } if (cudaTracker->isBaseTypeRequired(BaseType::Half)) @@ -1133,7 +1140,7 @@ namespace Slang version.kind = DownstreamCompileOptions::CapabilityVersion::Kind::SPIRV; version.version = glslTracker->getSPIRVVersion(); - options.requiredCapabilityVersions.add(version); + requiredCapabilityVersions.add(version); } } @@ -1186,11 +1193,11 @@ namespace Slang auto entryPoint = getEntryPoint(entryPointIndex); profile = getEffectiveProfile(entryPoint, targetReq); - options.entryPointName = getText(entryPoint->getName()); + options.entryPointName = allocator.allocate(getText(entryPoint->getName())); auto entryPointNameOverride = getProgram()->getEntryPointNameOverride(entryPointIndex); if (entryPointNameOverride.getLength() != 0) { - options.entryPointName = entryPointNameOverride; + options.entryPointName = allocator.allocate(entryPointNameOverride); } } else @@ -1225,7 +1232,7 @@ namespace Slang } // Set the profile - options.profileName = GetHLSLProfileName(profile); + options.profileName = allocator.allocate(GetHLSLProfileName(profile)); } // If we aren't using LLVM 'host callable', we want downstream compile to produce a shared library @@ -1239,7 +1246,7 @@ namespace Slang { if (_isCPUHostTarget(target)) { - options.libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath())); + libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath())); // Set up the library artifact auto artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU), toSlice("slang-rt")); @@ -1247,7 +1254,7 @@ namespace Slang ComPtr<IFileArtifactRepresentation> fileRep(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::NameOnly, toSlice("slang-rt"), nullptr, nullptr)); artifact->addRepresentation(fileRep); - options.libraries.add(artifact); + libraries.add(artifact); } } @@ -1335,23 +1342,35 @@ namespace Slang } // Add all the search paths (as calculated earlier - they will only be set if this is a pass through else will be empty) - options.includePaths = includePaths; + options.includePaths = allocator.allocate(includePaths); // Add the specified defines (as calculated earlier - they will only be set if this is a pass through else will be empty) { + const auto count = preprocessorDefinitions.Count(); + auto dst = allocator.getArena().allocateArray<DownstreamCompileOptions::Define>(count); + + Index i = 0; + for(auto& def : preprocessorDefinitions) { - DownstreamCompileOptions::Define define; - define.nameWithSig = def.Key; - define.value = def.Value; + auto& define = dst[i]; + + define.nameWithSig = allocator.allocate(def.Key); + define.value = allocator.allocate(def.Value); - options.defines.add(define); + ++i; } + options.defines = makeSlice(dst, count); } // Add all of the module libraries - options.libraries.addRange(linkage->m_libModules.getBuffer(), linkage->m_libModules.getCount()); + libraries.addRange(linkage->m_libModules.getBuffer(), linkage->m_libModules.getCount()); } + + options.compilerSpecificArguments = allocator.allocate(compilerSpecificArguments); + options.requiredCapabilityVersions = SliceCaster::asSlice(requiredCapabilityVersions); + options.libraries = SliceCaster::asSlice(libraries); + options.libraryPaths = allocator.allocate(libraryPaths); // Compile ComPtr<IArtifact> artifact; diff --git a/tools/slang-test/parse-diagnostic-util.cpp b/tools/slang-test/parse-diagnostic-util.cpp index c2cc1f010..49cc2555b 100644 --- a/tools/slang-test/parse-diagnostic-util.cpp +++ b/tools/slang-test/parse-diagnostic-util.cpp @@ -17,7 +17,7 @@ using namespace Slang; -/* static */SlangResult ParseDiagnosticUtil::parseGenericLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +/* static */SlangResult ParseDiagnosticUtil::parseGenericLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) { /* e:\git\somewhere\tests\diagnostics\syntax-error-intrinsic.slang(13): error C2018: unknown character '0x40' */ if (lineSlices.getCount() < 3) @@ -113,7 +113,7 @@ static bool _isSlangDiagnostic(const UnownedStringSlice& line) return SLANG_SUCCEEDED(_getSlangDiagnosticSeverity(typeSlice, type, code)); } -/* static */SlangResult ParseDiagnosticUtil::parseSlangLine(CharSliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +/* static */SlangResult ParseDiagnosticUtil::parseSlangLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) { /* tests/diagnostics/accessors.slang(11): error 31101: accessors other than 'set' must not have parameters @@ -286,7 +286,7 @@ static bool _isWhitespace(const UnownedStringSlice& slice) List<UnownedStringSlice> splitLine; - CharSliceAllocator allocator; + SliceAllocator allocator; UnownedStringSlice text(inText), line; while (StringUtil::extractLine(text, line)) diff --git a/tools/slang-test/parse-diagnostic-util.h b/tools/slang-test/parse-diagnostic-util.h index eb631f1fa..2ad7a7911 100644 --- a/tools/slang-test/parse-diagnostic-util.h +++ b/tools/slang-test/parse-diagnostic-util.h @@ -57,16 +57,16 @@ struct ParseDiagnosticUtil }; }; - typedef SlangResult (*LineParser)(Slang::CharSliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); + typedef SlangResult (*LineParser)(Slang::SliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); /// Given a compiler identity returns a line parsing function. static LineParser getLineParser(const CompilerIdentity& compilerIdentity); /// For a 'generic' (as in uses DownstreamCompiler mechanism) line parsing - static SlangResult parseGenericLine(Slang::CharSliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); + static SlangResult parseGenericLine(Slang::SliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); /// For parsing diagnostics from Slang - static SlangResult parseSlangLine(Slang::CharSliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); + static SlangResult parseSlangLine(Slang::SliceAllocator& allocator, const Slang::UnownedStringSlice& line, Slang::List<Slang::UnownedStringSlice>& lineSlices, Slang::ArtifactDiagnostic& outDiagnostic); /// Parse diagnostics into output text static SlangResult parseDiagnostics(const Slang::UnownedStringSlice& inText, Slang::IArtifactDiagnostics* diagnostics); diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index af7ca1f83..cd783bb05 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -2233,10 +2233,12 @@ static TestResult runCPPCompilerSharedLibrary(TestContext* context, TestInput& i options.targetType = SLANG_SHADER_SHARED_LIBRARY; // Compile this source - options.sourceFiles.add(filePath); - options.modulePath = modulePath; + TerminatedCharSlice sourceFiles[] = { SliceCaster::asTerminatedCharSlice(filePath) }; + TerminatedCharSlice includePaths[] = { TerminatedCharSlice(".") }; - options.includePaths.add("."); + options.sourceFiles = makeSlice(sourceFiles, 1); + options.includePaths = makeSlice(includePaths, 1); + options.modulePath = SliceCaster::asTerminatedCharSlice(modulePath); ComPtr<IArtifact> artifact; if (SLANG_FAILED(compiler->compile(options, artifact.writeRef()))) @@ -2351,9 +2353,11 @@ static TestResult runCPPCompilerExecute(TestContext* context, TestInput& input) options.sourceLanguage = (ext == "c") ? SLANG_SOURCE_LANGUAGE_C : SLANG_SOURCE_LANGUAGE_CPP; + TerminatedCharSlice filePaths[] = { SliceCaster::asTerminatedCharSlice(filePath) }; + // Compile this source - options.sourceFiles.add(filePath); - options.modulePath = modulePath; + options.sourceFiles = makeSlice(filePaths, 1); + options.modulePath = SliceCaster::asTerminatedCharSlice(modulePath); ComPtr<IArtifact> artifact; if (SLANG_FAILED(compiler->compile(options, artifact.writeRef()))) |
