summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-08-26 20:32:53 -0400
committerGitHub <noreply@github.com>2022-08-26 20:32:53 -0400
commit5c2c2cfc9918bb43225159e67a851e196e17759a (patch)
tree216009d02afe9dc17b074fdd394141ef71472268
parentef067bef2f2188a4b3c420cbcd8d223874888ed2 (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++.
-rw-r--r--build/visual-studio/compiler-core/compiler-core.vcxproj2
-rw-r--r--build/visual-studio/compiler-core/compiler-core.vcxproj.filters6
-rw-r--r--slang.h9
-rw-r--r--source/compiler-core/slang-artifact-associated-impl.cpp1
-rw-r--r--source/compiler-core/slang-artifact-associated-impl.h6
-rw-r--r--source/compiler-core/slang-artifact-diagnostic-util.cpp29
-rw-r--r--source/compiler-core/slang-artifact-diagnostic-util.h57
-rw-r--r--source/compiler-core/slang-artifact.h11
-rw-r--r--source/compiler-core/slang-downstream-compiler.cpp73
-rw-r--r--source/compiler-core/slang-downstream-compiler.h28
-rw-r--r--source/compiler-core/slang-downstream-dep1.cpp30
-rw-r--r--source/compiler-core/slang-dxc-compiler.cpp34
-rw-r--r--source/compiler-core/slang-fxc-compiler.cpp26
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp26
-rw-r--r--source/compiler-core/slang-glslang-compiler.cpp10
-rw-r--r--source/compiler-core/slang-nvrtc-compiler.cpp23
-rw-r--r--source/compiler-core/slang-slice-allocator.cpp94
-rw-r--r--source/compiler-core/slang-slice-allocator.h103
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp47
-rw-r--r--source/core/slang-blob.cpp98
-rw-r--r--source/core/slang-blob.h92
-rw-r--r--source/core/slang-io.cpp2
-rw-r--r--source/core/slang-riff-file-system.cpp2
-rw-r--r--source/core/slang-zip-file-system.cpp2
-rw-r--r--source/slang/slang-compiler.cpp59
-rw-r--r--tools/slang-test/parse-diagnostic-util.cpp6
-rw-r--r--tools/slang-test/parse-diagnostic-util.h6
-rw-r--r--tools/slang-test/slang-test-main.cpp14
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>
diff --git a/slang.h b/slang.h
index 53ab0c70a..a224bf6f6 100644
--- a/slang.h
+++ b/slang.h
@@ -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())))