summaryrefslogtreecommitdiffstats
path: root/source/compiler-core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-09-01 09:35:18 -0400
committerGitHub <noreply@github.com>2022-09-01 09:35:18 -0400
commitcd8715a7760189c54b36c0c250efbe1db5b8635c (patch)
treecd1b2e840e64cbdd9e9a383646f0e58a7f14ae97 /source/compiler-core
parent5c2c2cfc9918bb43225159e67a851e196e17759a (diff)
Passing source to Downstream compilation as artifacts (#2382)
* #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++. * Working with source being passed as artifacts to DownstreamCompiler. * Use artifacts in SourceManager/SourceFile. * Support infering extension from the original file extension.
Diffstat (limited to 'source/compiler-core')
-rw-r--r--source/compiler-core/slang-artifact-associated-impl.h2
-rw-r--r--source/compiler-core/slang-artifact-desc-util.cpp56
-rw-r--r--source/compiler-core/slang-artifact-desc-util.h3
-rw-r--r--source/compiler-core/slang-artifact-diagnostic-util.cpp2
-rw-r--r--source/compiler-core/slang-artifact-handler-impl.cpp2
-rw-r--r--source/compiler-core/slang-artifact-helper.cpp35
-rw-r--r--source/compiler-core/slang-artifact-helper.h21
-rw-r--r--source/compiler-core/slang-artifact-util.cpp139
-rw-r--r--source/compiler-core/slang-artifact-util.h25
-rw-r--r--source/compiler-core/slang-downstream-compiler.cpp103
-rw-r--r--source/compiler-core/slang-downstream-compiler.h10
-rw-r--r--source/compiler-core/slang-downstream-dep1.cpp39
-rw-r--r--source/compiler-core/slang-dxc-compiler.cpp22
-rw-r--r--source/compiler-core/slang-fxc-compiler.cpp22
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp14
-rw-r--r--source/compiler-core/slang-glslang-compiler.cpp21
-rw-r--r--source/compiler-core/slang-include-system.cpp17
-rw-r--r--source/compiler-core/slang-include-system.h10
-rw-r--r--source/compiler-core/slang-nvrtc-compiler.cpp20
-rw-r--r--source/compiler-core/slang-slice-allocator.cpp46
-rw-r--r--source/compiler-core/slang-slice-allocator.h56
-rw-r--r--source/compiler-core/slang-source-loc.cpp88
-rw-r--r--source/compiler-core/slang-source-loc.h24
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp16
24 files changed, 574 insertions, 219 deletions
diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h
index 321717a48..8506f1628 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 SliceCaster::asTerminatedCharSlice(m_raw); }
+ SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return SliceUtil::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;
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp
index cb5d401a9..7534e1265 100644
--- a/source/compiler-core/slang-artifact-desc-util.cpp
+++ b/source/compiler-core/slang-artifact-desc-util.cpp
@@ -443,12 +443,12 @@ static const KindExtension g_cpuKindExts[] =
{
switch (kind)
{
- case Kind::Library:
- case Kind::ObjectCode:
- {
- return true;
- }
- default: break;
+ case Kind::Library:
+ case Kind::ObjectCode:
+ {
+ return true;
+ }
+ default: break;
}
return false;
}
@@ -587,9 +587,6 @@ static UnownedStringSlice _getPayloadExtension(ArtifactPayload payload)
typedef ArtifactPayload Payload;
switch (payload)
{
- /* Misc */
- case Payload::Unknown: return toSlice("unknown");
-
/* Source types */
case Payload::HLSL: return toSlice("hlsl");
case Payload::GLSL: return toSlice("glsl");
@@ -685,8 +682,14 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S
}
case ArtifactKind::Source:
{
- out << _getPayloadExtension(desc.payload);
- return SLANG_OK;
+ auto ext = _getPayloadExtension(desc.payload);
+ if (ext.begin() != nullptr)
+ {
+ out << ext;
+ return SLANG_OK;
+ }
+ // Don't know the extension for that
+ return SLANG_E_NOT_FOUND;
}
default: break;
}
@@ -695,16 +698,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S
{
return appendCpuExtensionForKind(desc.kind, out);
}
- else
- {
- auto slice = _getPayloadExtension(desc.payload);
- if (slice.getLength())
- {
- out << slice;
- return SLANG_OK;
- }
- }
-
+
return SLANG_E_NOT_FOUND;
}
@@ -752,6 +746,12 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S
return getBaseNameFromPath(desc, path);
}
+/* static */SlangResult ArtifactDescUtil::hasDefinedNameForDesc(const ArtifactDesc& desc)
+{
+ StringBuilder buf;
+ return SLANG_SUCCEEDED(appendDefaultExtension(desc, buf));
+}
+
/* static */SlangResult ArtifactDescUtil::calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& inBaseName, StringBuilder& outName)
{
UnownedStringSlice baseName(inBaseName);
@@ -779,10 +779,18 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S
// If there is an extension append it
StringBuilder ext;
- if (SLANG_SUCCEEDED(appendDefaultExtension(desc, ext)) && ext.getLength() > 0)
+ if (SLANG_SUCCEEDED(appendDefaultExtension(desc, ext)))
+ {
+ if (ext.getLength())
+ {
+ outName.appendChar('.');
+ outName.append(ext);
+ }
+ }
+ else
{
- outName.appendChar('.');
- outName.append(ext);
+ // If we can't determine the type we can output with .unknown
+ outName.append(toSlice(".unknown"));
}
return SLANG_OK;
diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h
index 6c6c158f8..b700fa465 100644
--- a/source/compiler-core/slang-artifact-desc-util.h
+++ b/source/compiler-core/slang-artifact-desc-util.h
@@ -81,6 +81,9 @@ struct ArtifactDescUtil
/// Given a desc and a baseName works out the the output file name
static SlangResult calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& baseName, StringBuilder& outName);
+ /// Returns true if there is a defined name extension/type for this desc
+ static SlangResult hasDefinedNameForDesc(const ArtifactDesc& desc);
+
/// Given a target returns the ArtifactDesc
static ArtifactDesc makeDescForCompileTarget(SlangCompileTarget target);
diff --git a/source/compiler-core/slang-artifact-diagnostic-util.cpp b/source/compiler-core/slang-artifact-diagnostic-util.cpp
index 3a2c64dce..38e5c5fd8 100644
--- a/source/compiler-core/slang-artifact-diagnostic-util.cpp
+++ b/source/compiler-core/slang-artifact-diagnostic-util.cpp
@@ -127,7 +127,7 @@ namespace Slang {
String text(in);
diagnostic.severity = ArtifactDiagnostic::Severity::Info;
- diagnostic.text = SliceCaster::asTerminatedCharSlice(text);
+ diagnostic.text = SliceUtil::asTerminatedCharSlice(text);
diagnostics->add(diagnostic);
}
diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp
index c8e7bf247..94e6fb6f7 100644
--- a/source/compiler-core/slang-artifact-handler-impl.cpp
+++ b/source/compiler-core/slang-artifact-handler-impl.cpp
@@ -187,7 +187,7 @@ SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* art
// Now we need the appropriate name for this item
ComPtr<ISlangBlob> pathBlob;
- SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef()));
+ SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef()));
const auto path = StringUtil::getSlice(pathBlob);
diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp
index d24d08909..27965b0cc 100644
--- a/source/compiler-core/slang-artifact-helper.cpp
+++ b/source/compiler-core/slang-artifact-helper.cpp
@@ -7,6 +7,8 @@
#include "slang-artifact-desc-util.h"
#include "slang-artifact-util.h"
+#include "../compiler-core/slang-slice-allocator.h"
+
#include "../core/slang-castable-list-impl.h"
#include "../core/slang-castable-util.h"
@@ -108,12 +110,21 @@ SlangResult DefaultArtifactHelper::createLockFile(const char* inNameBase, ISlang
return SLANG_OK;
}
-SlangResult DefaultArtifactHelper::calcArtifactPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath)
+SlangResult DefaultArtifactHelper::calcArtifactDescPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath)
{
UnownedStringSlice basePath(inBasePath);
StringBuilder path;
SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path));
- *outPath = StringBlob::create(path).detach();
+ *outPath = StringBlob::moveCreate(path).detach();
+ return SLANG_OK;
+}
+
+SlangResult DefaultArtifactHelper::calcArtifactPath(IArtifact* artifact, const char* inBasePath, ISlangBlob** outPath)
+{
+ UnownedStringSlice basePath(inBasePath);
+ StringBuilder path;
+ SLANG_RETURN_ON_FAIL(ArtifactUtil::calcPath(artifact, basePath, path));
+ *outPath = StringBlob::moveCreate(path).detach();
return SLANG_OK;
}
@@ -140,4 +151,24 @@ SlangResult DefaultArtifactHelper::createCastableList(const Guid& guid, ICastabl
return SLANG_E_NO_INTERFACE;
}
+SlangResult DefaultArtifactHelper::createFileArtifactRepresentation(
+ IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep)
+{
+ *outRep = FileArtifactRepresentation::create(kind, asStringSlice(path), lockFile, fileSystem).detach();
+ return SLANG_OK;
+}
+
+
+SlangResult DefaultArtifactHelper::createFileArtifact(const ArtifactDesc& desc, const CharSlice& path, IArtifact** outArtifact)
+{
+ auto artifact = Artifact::create(desc);
+
+ auto fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Reference, asStringSlice(path), nullptr, nullptr);
+
+ artifact->addRepresentation(fileRep);
+
+ *outArtifact = artifact.detach();
+ return SLANG_OK;
+}
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h
index 22c1b5c99..208c80bd5 100644
--- a/source/compiler-core/slang-artifact-helper.h
+++ b/source/compiler-core/slang-artifact-helper.h
@@ -44,7 +44,10 @@ class IArtifactHelper : public ICastable
virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) = 0;
/// Given a desc and a basePath returns a suitable name
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0;
+
+ /// Given an artifact and a basePath returns a suitable name
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact* , const char* basePath, ISlangBlob** outPath) = 0;
/// Given a compile target return the equivalent desc
virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) = 0;
@@ -52,8 +55,15 @@ class IArtifactHelper : public ICastable
/// Given an interface returns as a castable interface. This might just cast unk into ICastable, or wrap it such that it uses the castable interface
virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0;
+ /// Create a file rep
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifactRepresentation(
+ IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep) = 0;
+
/// Create an empty ICastableList
virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) = 0;
+
+
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) = 0;
};
class DefaultArtifactHelper : public IArtifactHelper
@@ -85,7 +95,9 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE;
+
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE;
@@ -93,6 +105,11 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifactRepresentation(
+ IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep) SLANG_OVERRIDE;
+
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) SLANG_OVERRIDE;
+
static IArtifactHelper* getSingleton() { return &g_singleton; }
protected:
diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp
index 20a729cfa..047e87db0 100644
--- a/source/compiler-core/slang-artifact-util.cpp
+++ b/source/compiler-core/slang-artifact-util.cpp
@@ -120,4 +120,143 @@ namespace Slang {
return String();
}
+/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemTemporaryFile(IArtifact* artifact)
+{
+ if (auto fileRep = findFileSystemFile(artifact))
+ {
+ return fileRep->getLockFile() ? fileRep : nullptr;
+ }
+ return nullptr;
+}
+
+/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemFile(IArtifact* artifact)
+{
+ for (auto rep : artifact->getRepresentations())
+ {
+ if (auto fileSystemRep = as<IFileArtifactRepresentation>(rep))
+ {
+ if (fileSystemRep->getFileSystem() == nullptr)
+ {
+ return fileSystemRep;
+ }
+ }
+ }
+ return nullptr;
+}
+
+/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemPrimaryFile(IArtifact* artifact)
+{
+ for (auto rep : artifact->getRepresentations())
+ {
+ if (auto fileRep = as<IFileArtifactRepresentation>(rep))
+ {
+ // If it has a file system it's not on OS
+ // If it has a lock file it can be assumed to be temporary
+ if (fileRep->getFileSystem() != nullptr ||
+ fileRep->getLockFile())
+ {
+ continue;
+ }
+
+ // If it's a file that is persistant it will just be a reference to a pre-existing file
+ const auto kind = fileRep->getKind();
+ if (kind != IFileArtifactRepresentation::Kind::Reference)
+ {
+ continue;
+ }
+
+ return fileRep;
+ }
+ }
+ return nullptr;
+}
+
+UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact)
+{
+ // If a name is set we'll just use that
+ {
+ const char* name = artifact->getName();
+ if (name && name[0] != 0)
+ {
+ return UnownedStringSlice(name);
+ }
+ }
+
+ // Find the *first* file rep and use it's path.
+ // This may not be the file on the file system - but is probably the path/name the user most associated with the artifact
+ if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact))
+ {
+ // If there isn't a lock file it is
+ if (fileRep->getLockFile() == nullptr)
+ {
+ return UnownedStringSlice(fileRep->getPath());
+ }
+ }
+
+ return UnownedStringSlice();
+}
+
+/* static */UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact)
+{
+ for (auto rep :artifact->getRepresentations())
+ {
+ if (auto fileRep = as<IFileArtifactRepresentation>(rep))
+ {
+ const char* path = fileRep->getPath();
+ auto ext = Path::getPathExt(UnownedStringSlice(path));
+ if (ext.getLength())
+ {
+ return ext;
+ }
+ }
+ }
+
+ // Okay lets see if the name has an extension
+ return Path::getPathExt(UnownedStringSlice(artifact->getName()));
+}
+
+static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath)
+{
+ auto ext = ArtifactUtil::inferExtension(artifact);
+
+ // If no extension was determined by inferring, go with unknown
+ if (ext.begin() == nullptr)
+ {
+ ext = toSlice("unknown");
+ }
+
+ outPath.Clear();
+ outPath.append(basePath);
+ if (ext.getLength())
+ {
+ outPath.appendChar('.');
+ outPath.append(ext);
+ }
+ return SLANG_OK;
+}
+
+/* static */SlangResult ArtifactUtil::calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath)
+{
+ if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc()))
+ {
+ return ArtifactDescUtil::calcPathForDesc(artifact->getDesc(), basePath, outPath);
+ }
+ else
+ {
+ return _calcInferred(artifact, basePath, outPath);
+ }
+}
+
+/* static */SlangResult ArtifactUtil::calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName)
+{
+ if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc()))
+ {
+ return ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName, outName);
+ }
+ else
+ {
+ return _calcInferred(artifact, baseName, outName);
+ }
+}
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h
index dc370b557..16687d6a9 100644
--- a/source/compiler-core/slang-artifact-util.h
+++ b/source/compiler-core/slang-artifact-util.h
@@ -37,6 +37,31 @@ struct ArtifactUtil
static bool isSignificant(IArtifact* artifact, void* data = nullptr);
/// Find a significant artifact
static IArtifact* findSignificant(IArtifact* artifact);
+
+ /// Returns the rep of the artifact that contains a temporary (identified by having a lock) on
+ /// the OS file system
+ static IFileArtifactRepresentation* findFileSystemTemporaryFile(IArtifact* artifact);
+ /// Returns true if the artifact contains a file on the OS file system
+ static IFileArtifactRepresentation* findFileSystemFile(IArtifact* artifact);
+ /// Returns the rep of a file system file which *isn't* temporary
+ static IFileArtifactRepresentation* findFileSystemPrimaryFile(IArtifact* artifact);
+
+ /// Find the path/name associated with the artifact.
+ /// The path is *not* necessarily the path on the file system. The order of search is
+ /// * If the artifact has a name return that
+ /// * If the artifact has a IFileArtifactRepresentation (that isn't temporary) return it's path
+ /// * If not found return an empty slice
+ static UnownedStringSlice findPath(IArtifact* artifact);
+
+ /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be interpretted in different ways
+ /// This function uses the associated name and file representations to infer a extension. If none is found returns an empty slice.
+ static UnownedStringSlice inferExtension(IArtifact* artifact);
+
+ /// Given a desc and a basePath returns a suitable path for a entity of specified desc
+ static SlangResult calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath);
+
+ /// Given a desc and a baseName works out the the output file name
+ static SlangResult calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName);
};
} // namespace Slang
diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp
index f134d77f5..f665757bb 100644
--- a/source/compiler-core/slang-downstream-compiler.cpp
+++ b/source/compiler-core/slang-downstream-compiler.cpp
@@ -66,35 +66,6 @@ void* DownstreamCompilerBase::getObject(const Guid& guid)
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/
-static bool _isContentsInFile(const DownstreamCompileOptions& options)
-{
- if (options.sourceContentsPath.count <= 0)
- {
- return false;
- }
-
- // We can see if we can load it
- 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
- // to the compiler all it is able to (currently) see are files on the file system.
- //
- // Note that it could be coincidence that the filesystem has a file that's identical in
- // contents/name. That being the case though, any includes wouldn't work for a generated
- // file either from some specialized ISlangFileSystem, so this is probably as good as it gets
- // until we can integrate directly to a C/C++ compiler through say a shared library where we can control
- // file system access.
- String readContents;
-
- if (SLANG_SUCCEEDED(File::readAllText(asStringSlice(options.sourceContentsPath), readContents)))
- {
- return asStringSlice(options.sourceContents) == readContents.getUnownedSlice();
- }
- }
- return false;
-}
-
SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact)
{
// Copy the command line options
@@ -114,67 +85,26 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio
ComPtr<IFileArtifactRepresentation> lockFile;
// 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);
+ String modulePath;
- if (options.modulePath.count == 0 || options.sourceContents.count != 0)
+ // If no module path is set we will need to generate one
+ if (options.modulePath.count == 0)
{
- String modulePath = asString(options.modulePath);
+ // We could use the path to the source, or use the source name/paths as defined on the artifact
+ // For now we just go with a lock file based on "slang-generated".
+ SLANG_RETURN_ON_FAIL(helper->createLockFile("slang-generated", nullptr, lockFile.writeRef()));
- // If there is no module path, generate one.
- if (modulePath.getLength() == 0)
- {
- SLANG_RETURN_ON_FAIL(helper->createLockFile("slang-generated", nullptr, lockFile.writeRef()));
+ auto lockArtifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None));
+ lockArtifact->addRepresentation(lockFile);
- auto lockArtifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None));
- lockArtifact->addRepresentation(lockFile);
+ artifactList->add(lockArtifact);
- artifactList->add(lockArtifact);
+ // Add the source files such that they can exist
+ modulePath = lockFile->getPath();
- modulePath = lockFile->getPath();
- options.modulePath = allocator.allocate(modulePath);
- }
-
- if (_isContentsInFile(options))
- {
- sourceFiles.add(options.sourceContentsPath);
- }
- else
- {
- // Work out the ArtifactDesc for the source language
- const auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage);
-
- // 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, asStringSlice(options.sourceContents)));
-
- // Create the reference to the file
- auto fileRep = FileArtifactRepresentation::create(IFileArtifactRepresentation::Kind::Owned, compileSourcePath.getUnownedSlice(), lockFile, nullptr);
- auto fileArtifact = ArtifactUtil::createArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage));
- fileArtifact->addRepresentation(fileRep);
-
- artifactList->add(fileArtifact);
-
- // Add it as a source file
- sourceFiles.add(allocator.allocate(compileSourcePath));
- }
-
- // There is no source contents
- options.sourceContents = TerminatedCharSlice();
- options.sourceContentsPath = TerminatedCharSlice();
+ options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath);
}
- 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));
@@ -255,6 +185,15 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio
}
}
+ // Add all of the source artifacts, that are temporary on the file system, such that they can stay in scope for debugging
+ for (auto sourceArtifact : options.sourceArtifacts)
+ {
+ if (ArtifactUtil::findFileSystemTemporaryFile(sourceArtifact) && sourceArtifact->exists())
+ {
+ artifactList->add(sourceArtifact);
+ }
+ }
+
// Create the result artifact
auto artifact = ArtifactUtil::createArtifact(targetDesc);
diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h
index 9fea5cb05..a9ef56221 100644
--- a/source/compiler-core/slang-downstream-compiler.h
+++ b/source/compiler-core/slang-downstream-compiler.h
@@ -123,14 +123,8 @@ struct DownstreamCompileOptions
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.
- TerminatedCharSlice sourceContents;
- /// 'Path' that the contents originated from. NOTE! This is for reporting only and doesn't have to exist on file system
- TerminatedCharSlice sourceContentsPath;
-
- /// The names/paths of source to compile. This can be empty if sourceContents is set.
- Slice<TerminatedCharSlice> sourceFiles;
+ /// The source artifacts
+ Slice<IArtifact*> sourceArtifacts;
Slice<TerminatedCharSlice> includePaths;
Slice<TerminatedCharSlice> libraryPaths;
diff --git a/source/compiler-core/slang-downstream-dep1.cpp b/source/compiler-core/slang-downstream-dep1.cpp
index ac66b4502..c62fc77fc 100644
--- a/source/compiler-core/slang-downstream-dep1.cpp
+++ b/source/compiler-core/slang-downstream-dep1.cpp
@@ -6,6 +6,7 @@
#include "slang-artifact-desc-util.h"
#include "../core/slang-castable-util.h"
+#include "../core/slang-string-util.h"
#include "slang-slice-allocator.h"
@@ -97,6 +98,14 @@ DownstreamCompilerAdapter_Dep1::DownstreamCompilerAdapter_Dep1(DownstreamCompile
}
SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOptions, IArtifact** outArtifact)
{
+ // Currently this only for llvm, so we'll just ignore other scenarios
+ if (inOptions.sourceArtifacts.count != 1)
+ {
+ return SLANG_FAIL;
+ }
+
+ IArtifact* sourceArtifact = inOptions.sourceArtifacts[0];
+
typedef DownstreamCompileOptions_Dep1::SomeEnum SomeEnum;
// Convert to the Deps1 compile options
@@ -126,15 +135,16 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti
options.defines.add(dst);
}
- options.sourceContents = asStringSlice(inOptions.sourceContents);
- options.sourceContentsPath = asStringSlice(inOptions.sourceContentsPath);
-
- options.sourceFiles = SliceConverter::toList(inOptions.sourceFiles);
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()));
+
+ options.sourceContents = StringUtil::getString(blob);
+ options.sourceContentsPath = ArtifactUtil::findPath(sourceArtifact);
- options.includePaths = SliceConverter::toList(inOptions.includePaths);
- options.libraryPaths = SliceConverter::toList(inOptions.libraryPaths);
+ options.includePaths = SliceUtil::toList(inOptions.includePaths);
+ options.libraryPaths = SliceUtil::toList(inOptions.libraryPaths);
- options.libraries = SliceConverter::toComPtrList(inOptions.libraries);
+ options.libraries = SliceUtil::toComPtrList(inOptions.libraries);
for (auto& src : inOptions.requiredCapabilityVersions)
{
@@ -155,7 +165,7 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti
options.stage = inOptions.stage;
- options.compilerSpecificArguments = SliceConverter::toList(inOptions.compilerSpecificArguments);
+ options.compilerSpecificArguments = SliceUtil::toList(inOptions.compilerSpecificArguments);
options.fileSystemExt = inOptions.fileSystemExt;
options.sourceManager = inOptions.sourceManager;
@@ -163,8 +173,6 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti
RefPtr<DownstreamCompileResult_Dep1> result;
SLANG_RETURN_ON_FAIL(m_dep->compile(options, result));
- typedef SliceCaster Caster;
-
ComPtr<IArtifact> artifact = ArtifactUtil::createArtifactForCompileTarget(options.targetType);
// Convert the diagnostics
@@ -173,7 +181,7 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti
const DownstreamDiagnostics_Dep1* srcDiagnostics = &result->getDiagnostics();
dstDiagnostics->setResult(srcDiagnostics->result);
- dstDiagnostics->setRaw(Caster::asCharSlice(srcDiagnostics->rawDiagnostics));
+ dstDiagnostics->setRaw(SliceUtil::asCharSlice(srcDiagnostics->rawDiagnostics));
for (const auto& srcDiagnostic : srcDiagnostics->diagnostics)
{
@@ -182,11 +190,14 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOpti
dstDiagnostic.severity = ArtifactDiagnostic::Severity(srcDiagnostic.severity);
dstDiagnostic.stage = ArtifactDiagnostic::Stage(srcDiagnostic.stage);
- dstDiagnostic.code = Caster::asTerminatedCharSlice(srcDiagnostic.code);
- dstDiagnostic.text = Caster::asTerminatedCharSlice(srcDiagnostic.text);
- dstDiagnostic.filePath = Caster::asTerminatedCharSlice(srcDiagnostic.filePath);
+ dstDiagnostic.code = SliceUtil::asTerminatedCharSlice(srcDiagnostic.code);
+ dstDiagnostic.text = SliceUtil::asTerminatedCharSlice(srcDiagnostic.text);
+ dstDiagnostic.filePath = SliceUtil::asTerminatedCharSlice(srcDiagnostic.filePath);
dstDiagnostic.location.line = srcDiagnostic.fileLine;
+
+ // Add the diagnostic
+ dstDiagnostics->add(dstDiagnostic);
}
artifact->addAssociated(dstDiagnostics);
diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp
index 6aa065afd..03ad868a8 100644
--- a/source/compiler-core/slang-dxc-compiler.cpp
+++ b/source/compiler-core/slang-dxc-compiler.cpp
@@ -278,12 +278,14 @@ 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.count > 0)
+ // This compiler can only deal with a single artifact
+ if (options.sourceArtifacts.count != 1)
{
return SLANG_FAIL;
}
+ IArtifact* sourceArtifact = options.sourceArtifacts[0];
+
if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXIL)
{
SLANG_ASSERT(!"Can only compile HLSL to DXIL");
@@ -311,13 +313,14 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif
ComPtr<IDxcLibrary> dxcLibrary;
SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef()));
- const auto& hlslSource = options.sourceContents;
+ ComPtr<ISlangBlob> sourceBlob;
+ SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef()));
// Create blob from the string
ComPtr<IDxcBlobEncoding> dxcSourceBlob;
SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned(
- (LPBYTE)hlslSource.data,
- (UINT32)hlslSource.count,
+ (LPBYTE)sourceBlob->getBufferPointer(),
+ (UINT32)sourceBlob->getBufferSize(),
0,
dxcSourceBlob.writeRef()));
@@ -432,13 +435,14 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif
searchDirectories.searchDirectories.add(asString(includePath));
}
- OSString sourcePath = asString(options.sourceContentsPath).toWString();
+ String sourcePath = ArtifactUtil::findPath(sourceArtifact);
+ OSString wideSourcePath = sourcePath.toWString();
DxcIncludeHandler includeHandler(&searchDirectories, options.fileSystemExt, options.sourceManager);
ComPtr<IDxcOperationResult> dxcResult;
SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob,
- sourcePath.begin(),
+ wideSourcePath.begin(),
wideEntryPointName.begin(),
wideProfileName.begin(),
args.getBuffer(),
@@ -480,9 +484,9 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif
{
name = Path::getFileNameWithoutExt(asString(options.modulePath));
}
- else if (options.sourceContentsPath.count)
+ else if (sourcePath.getLength())
{
- name = Path::getFileNameWithoutExt(asString(options.sourceContentsPath));
+ name = Path::getFileNameWithoutExt(sourcePath);
}
// Add the blob with name
diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp
index 03eaa8e34..1706f0fb0 100644
--- a/source/compiler-core/slang-fxc-compiler.cpp
+++ b/source/compiler-core/slang-fxc-compiler.cpp
@@ -182,12 +182,14 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned
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.count > 0)
+ // This compiler can only deal with a single source artifact
+ if (options.sourceArtifacts.count != 1)
{
return SLANG_FAIL;
}
+ IArtifact* sourceArtifact = options.sourceArtifacts[0];
+
if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXBC)
{
SLANG_ASSERT(!"Can only compile HLSL to DXBC");
@@ -207,15 +209,18 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif
searchDirectories.searchDirectories.add(asString(includePath));
}
+ const auto sourcePath = ArtifactUtil::findPath(sourceArtifact);
+
// Use the default fileSystemExt is not set
ID3DInclude* includeHandler = nullptr;
FxcIncludeHandler fxcIncludeHandlerStorage(&searchDirectories, options.fileSystemExt, options.sourceManager);
if (options.fileSystemExt)
{
- if (options.sourceContentsPath.count > 0)
+
+ if (sourcePath.getLength() > 0)
{
- fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(asString(options.sourceContentsPath));
+ fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(sourcePath);
}
includeHandler = &fxcIncludeHandlerStorage;
}
@@ -274,12 +279,15 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif
break;
}
+ ComPtr<ISlangBlob> sourceBlob;
+ SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef()));
+
ComPtr<ID3DBlob> codeBlob;
ComPtr<ID3DBlob> diagnosticsBlob;
HRESULT hr = m_compile(
- options.sourceContents.begin(),
- options.sourceContents.count,
- options.sourceContentsPath,
+ sourceBlob->getBufferPointer(),
+ sourceBlob->getBufferSize(),
+ String(sourcePath).getBuffer(),
dxMacros,
includeHandler,
options.entryPointName,
diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp
index 7bbde64c4..8851477d7 100644
--- a/source/compiler-core/slang-gcc-compiler-util.cpp
+++ b/source/compiler-core/slang-gcc-compiler-util.cpp
@@ -356,7 +356,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS
SliceAllocator allocator;
diagnostics->reset();
- diagnostics->setRaw(SliceCaster::asCharSlice(exeRes.standardError));
+ diagnostics->setRaw(SliceUtil::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
@@ -456,7 +456,6 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS
/* static */SlangResult GCCDownstreamCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
{
- SLANG_ASSERT(options.sourceContents.count == 0);
SLANG_ASSERT(options.modulePath.count);
PlatformKind platformKind = (options.platform == PlatformKind::Unknown) ? PlatformUtil::getPlatformKind() : options.platform;
@@ -613,10 +612,15 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS
}
}
- // Files to compile
- for (const auto& sourceFile : options.sourceFiles)
+ // Files to compile, need to be on the file system.
+ for (IArtifact* sourceArtifact : options.sourceArtifacts)
{
- cmdLine.addArg(asString(sourceFile));
+ ComPtr<IFileArtifactRepresentation> fileRep;
+
+ // TODO(JS):
+ // Do we want to keep the file on the file system? It's probably reasonable to do so.
+ SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef()));
+ cmdLine.addArg(fileRep->getPath());
}
// Add the library paths
diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp
index a896e4278..d6ae59690 100644
--- a/source/compiler-core/slang-glslang-compiler.cpp
+++ b/source/compiler-core/slang-glslang-compiler.cpp
@@ -127,12 +127,14 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned
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.count > 0)
+ // This compiler can only handle a single artifact
+ if (options.sourceArtifacts.count != 1)
{
return SLANG_FAIL;
}
+ IArtifact* sourceArtifact = options.sourceArtifacts[0];
+
if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_GLSL || options.targetType != SLANG_SPIRV)
{
SLANG_ASSERT(!"Can only compile GLSL to SPIR-V");
@@ -150,18 +152,23 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IA
((List<uint8_t>*)userData)->addRange((uint8_t*)data, size);
};
-
+ ComPtr<ISlangBlob> sourceBlob;
+ SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef()));
+
+ String sourcePath = ArtifactUtil::findPath(sourceArtifact);
+
glslang_CompileRequest_1_1 request;
memset(&request, 0, sizeof(request));
request.sizeInBytes = sizeof(request);
request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV;
- request.sourcePath = options.sourceContentsPath;
+ request.sourcePath = sourcePath.getBuffer();
request.slangStage = options.stage;
- request.inputBegin = options.sourceContents.begin();
- request.inputEnd = options.sourceContents.end();
+ const char* inputBegin = (const char*)sourceBlob->getBufferPointer();
+ request.inputBegin = inputBegin;
+ request.inputEnd = inputBegin + sourceBlob->getBufferSize();
// Find the SPIR-V version if set
SemanticVersion spirvVersion;
@@ -201,7 +208,7 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IA
if (SLANG_FAILED(invokeResult))
{
- diagnostics->setRaw(SliceCaster::asCharSlice(diagnosticOutput));
+ diagnostics->setRaw(SliceUtil::asCharSlice(diagnosticOutput));
SliceAllocator allocator;
diff --git a/source/compiler-core/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp
index 891d376f6..455ecde2b 100644
--- a/source/compiler-core/slang-include-system.cpp
+++ b/source/compiler-core/slang-include-system.cpp
@@ -4,9 +4,22 @@
#include "../core/slang-io.h"
#include "../core/slang-string-util.h"
+#include "../core/slang-file-system.h"
+
+#include "slang-slice-allocator.h"
+#include "slang-artifact-impl.h"
+#include "slang-artifact-representation-impl.h"
+
namespace Slang
{
+IncludeSystem::IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) :
+ m_searchDirectories(searchDirectories),
+ m_fileSystemExt(fileSystemExt),
+ m_sourceManager(sourceManager)
+{
+}
+
SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo)
{
String combinedPath;
@@ -119,6 +132,8 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob>
sourceFile = m_sourceManager->createSourceFileWithBlob(pathInfo, foundSourceBlob);
m_sourceManager->addSourceFile(pathInfo.uniqueIdentity, sourceFile);
+ sourceFile->maybeAddArtifact(m_fileSystemExt);
+
outBlob = foundSourceBlob;
return SLANG_OK;
}
@@ -137,6 +152,8 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob>
}
sourceFile->setContents(foundSourceBlob);
+ sourceFile->maybeAddArtifact(m_fileSystemExt);
+
outBlob = foundSourceBlob;
return SLANG_OK;
}
diff --git a/source/compiler-core/slang-include-system.h b/source/compiler-core/slang-include-system.h
index 1fc8eac6e..108c4901b 100644
--- a/source/compiler-core/slang-include-system.h
+++ b/source/compiler-core/slang-include-system.h
@@ -33,13 +33,6 @@ struct SearchDirectoryList
/* A helper class that builds basic include handling on top of searchDirectories/fileSystemExt and optionally a sourceManager */
struct IncludeSystem
{
- IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr) :
- m_searchDirectories(searchDirectories),
- m_fileSystemExt(fileSystemExt),
- m_sourceManager(sourceManager)
- {
- }
-
SlangResult findFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo);
SlangResult findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo);
String simplifyPath(const String& path);
@@ -51,6 +44,9 @@ struct IncludeSystem
ISlangFileSystemExt* getFileSystem() const { return m_fileSystemExt; }
SourceManager* getSourceManager() const { return m_sourceManager; }
+ /// Ctor
+ IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr);
+
protected:
SearchDirectoryList* m_searchDirectories;
diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp
index 2c01dc633..1a112d67f 100644
--- a/source/compiler-core/slang-nvrtc-compiler.cpp
+++ b/source/compiler-core/slang-nvrtc-compiler.cpp
@@ -645,12 +645,14 @@ 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.count > 0)
+ // This compiler can only deal with a single artifact
+ if (options.sourceArtifacts.count != 1)
{
return SLANG_FAIL;
}
+ IArtifact* sourceArtifact = options.sourceArtifacts[0];
+
CommandLine cmdLine;
switch (options.debugInfoType)
@@ -819,9 +821,17 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt
SLANG_ASSERT(headers.getCount() == headerIncludeNames.getCount());
+ ComPtr<ISlangBlob> sourceBlob;
+ SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef()));
+
+ auto sourcePath = ArtifactUtil::findPath(sourceArtifact);
+
+ StringBuilder storage;
+ auto sourceContents = SliceUtil::toTerminatedCharSlice(storage, sourceBlob);
+
nvrtcProgram program = nullptr;
- nvrtcResult res = m_nvrtcCreateProgram(&program, options.sourceContents, options.sourceContentsPath,
- (int) headers.getCount(),
+ nvrtcResult res = m_nvrtcCreateProgram(&program, sourceContents, String(sourcePath).getBuffer(),
+ (int)headers.getCount(),
headers.getBuffer(),
headerIncludeNames.getBuffer());
if (res != NVRTC_SUCCESS)
@@ -860,7 +870,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt
SLANG_NVRTC_RETURN_ON_FAIL(m_nvrtcGetProgramLog(program, dst));
rawDiagnostics.appendInPlace(dst, Index(logSize));
- diagnostics->setRaw(SliceCaster::asCharSlice(rawDiagnostics));
+ diagnostics->setRaw(SliceUtil::asCharSlice(rawDiagnostics));
}
SliceAllocator allocator;
diff --git a/source/compiler-core/slang-slice-allocator.cpp b/source/compiler-core/slang-slice-allocator.cpp
index 9985f6b19..9a0620ced 100644
--- a/source/compiler-core/slang-slice-allocator.cpp
+++ b/source/compiler-core/slang-slice-allocator.cpp
@@ -5,9 +5,9 @@
namespace Slang {
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceConverter !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-/* static */ List<String> SliceConverter::toList(const Slice<TerminatedCharSlice>& in)
+/* static */ List<String> SliceUtil::toList(const Slice<TerminatedCharSlice>& in)
{
List<String> list;
const auto count = in.count;
@@ -20,20 +20,21 @@ namespace Slang {
return list;
}
-/* static */TerminatedCharSlice SliceConverter::toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob)
+/* static */const char* SliceUtil::getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice)
{
const auto size = blob->getBufferSize();
-
if (size == 0)
{
- return TerminatedCharSlice();
+ outSlice = TerminatedCharSlice();
+ return outSlice.begin();
}
// 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));
+ outSlice = TerminatedCharSlice(chars, Count(size - 1));
+ return chars;
}
// See if it has a castable interface
@@ -42,15 +43,44 @@ namespace Slang {
{
if (castable->castAs(SlangTerminatedChars::getTypeGuid()))
{
- return TerminatedCharSlice(chars, Count(size));
+ outSlice = TerminatedCharSlice(chars, Count(size));
+ return chars;
}
}
+ return nullptr;
+}
+
+/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob)
+{
+ TerminatedCharSlice slice;
+ if (SliceUtil::getTerminated(blob, slice))
+ {
+ return slice;
+ }
+ const auto size = blob->getBufferSize();
// We are out of options, we just have to allocate with zero termination which allocateString does
- auto dst = allocator.getArena().allocateString(chars, Count(size));
+ auto dst = allocator.getArena().allocateString((const char*)blob->getBufferPointer(), Count(size));
return TerminatedCharSlice(dst, Count(size));
}
+/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob)
+{
+ TerminatedCharSlice slice;
+ if (SliceUtil::getTerminated(blob, slice))
+ {
+ return slice;
+ }
+
+ const auto size = blob->getBufferSize();
+ auto chars = (const char*)blob->getBufferPointer();
+
+ storage.Clear();
+ storage.append(UnownedStringSlice(chars, size));
+
+ return TerminatedCharSlice(storage.getBuffer(), Count(size));
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceAllocator !!!!!!!!!!!!!!!!!!!!!!!!!!! */
TerminatedCharSlice SliceAllocator::allocate(const char* in)
diff --git a/source/compiler-core/slang-slice-allocator.h b/source/compiler-core/slang-slice-allocator.h
index 41ed3943a..984ad32eb 100644
--- a/source/compiler-core/slang-slice-allocator.h
+++ b/source/compiler-core/slang-slice-allocator.h
@@ -10,43 +10,35 @@
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
+
+struct SliceAllocator;
+
+struct SliceUtil
{
+ /// Convert into a list of strings
+ static List<String> toList(const Slice<TerminatedCharSlice>& in);
+
+ /// Gets a 0 terminated string from a blob. If not possible returns nullptr
+ static const char* getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice);
+
+ /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does
+ static TerminatedCharSlice toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob);
+ ///
+ static TerminatedCharSlice toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob);
+
/// 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()); }
+ /// Get string as a char slice
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()); }
+ 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)
{
@@ -57,6 +49,20 @@ struct SliceConverter
for (Index i = 0; i < in.count; ++i) list[i] = ComPtr<T>(in[i]);
return list;
}
+
+private:
+
+ /*
+ A 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.
+ */
+
+ /// 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;
};
SLANG_FORCE_INLINE UnownedStringSlice asStringSlice(const CharSlice& slice)
diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp
index f245d1e0c..c82636248 100644
--- a/source/compiler-core/slang-source-loc.cpp
+++ b/source/compiler-core/slang-source-loc.cpp
@@ -4,6 +4,9 @@
#include "../core/slang-string-util.h"
#include "../core/slang-string-escape-util.h"
+#include "slang-artifact-representation-impl.h"
+#include "slang-artifact-impl.h"
+
namespace Slang {
/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceView !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -22,6 +25,20 @@ const String PathInfo::getMostUniqueIdentity() const
}
}
+String PathInfo::getName() const
+{
+ switch (type)
+ {
+ case Type::Normal:
+ case Type::FromString:
+ case Type::FoundPath:
+ {
+ return foundPath;
+ }
+ }
+ return String();
+}
+
bool PathInfo::operator==(const ThisType& rhs) const
{
// They must be the same type
@@ -415,6 +432,77 @@ String SourceFile::calcVerbosePath() const
return m_pathInfo.foundPath;
}
+void SourceFile::maybeAddArtifact(ISlangFileSystemExt* ext)
+{
+ if (!m_contentBlob)
+ {
+ return;
+ }
+
+ // If there already is an artifact, or we are not using OSFile system then
+ if (m_artifact)
+ {
+ // TODO(JS):
+ // Check if it has the blob or not
+ SLANG_ASSERT(m_contentBlob == findRepresentation<ISlangBlob>(m_artifact));
+ return;
+ }
+
+ // We don't know how the source will be used
+ m_artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Unknown, ArtifactStyle::Unknown));
+
+ // Add the blob as a representation.
+ m_artifact->addRepresentationUnknown(m_contentBlob);
+
+ // If we have the file system see if we can set up a path too
+ if (ext)
+ {
+ const auto osPathKind = ext->getOSPathKind();
+
+ if (osPathKind != OSPathKind::None)
+ {
+ String path;
+ switch (osPathKind)
+ {
+ case OSPathKind::Canonical:
+ {
+ // Get the canonical path
+ ComPtr<ISlangBlob> canonicalPath;
+ if (SLANG_SUCCEEDED(ext->getCanonicalPath(getPathInfo().foundPath.getBuffer(), canonicalPath.writeRef())))
+ {
+ path = StringUtil::getString(canonicalPath);
+ }
+ break;
+ }
+ case OSPathKind::Direct:
+ {
+ path = getPathInfo().foundPath;
+ break;
+ }
+ }
+
+ if (path.getLength())
+ {
+ // We can sanity check that this works
+ SlangPathType pathType;
+ if (SLANG_SUCCEEDED(ext->getPathType(path.getBuffer(), &pathType)))
+ {
+ // We can add a file representation
+ FileArtifactRepresentation* fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice(), nullptr, nullptr);
+ m_artifact->addRepresentation(fileRep);
+ }
+ }
+ }
+ }
+
+ // Get the name
+ auto name = getPathInfo().getName();
+ if (name.getLength())
+ {
+ m_artifact->setName(name.getBuffer());
+ }
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
void SourceManager::initialize(
diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h
index 24471f3b0..461f09e96 100644
--- a/source/compiler-core/slang-source-loc.h
+++ b/source/compiler-core/slang-source-loc.h
@@ -9,6 +9,8 @@
#include "../../slang-com-ptr.h"
#include "../../slang.h"
+#include "slang-artifact-representation.h"
+
namespace Slang {
/** Overview:
@@ -60,6 +62,8 @@ struct PathInfo
SLANG_FORCE_INLINE bool hasFoundPath() const { return type == Type::Normal || type == Type::FoundPath || (type == Type::FromString && foundPath.getLength() > 0); }
/// True if has a found path that has originated from a file (as opposed to string or some other origin)
SLANG_FORCE_INLINE bool hasFileFoundPath() const { return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; }
+ /// Get the 'name'/path of the item. Will return an empty string if not applicable or not set.
+ String getName() const;
bool operator==(const ThisType& rhs) const;
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
@@ -232,11 +236,19 @@ public:
/// Get path info
const PathInfo& getPathInfo() const { return m_pathInfo; }
+ /// Get the (optional) assoicated artifact. Note its desc might be Source/Unknown
+ IArtifact* getArtifact() const { return m_artifact; }
+ /// Set the artifact
+ void setArtifact(IArtifact* artifact) { m_artifact = artifact; }
+
/// Set the content as a blob
void setContents(ISlangBlob* blob);
/// Set the content as a string
void setContents(const String& content);
+ /// If artifact isn't defined will try and associate one. The pathInfo must be the one associated with the PathInfo
+ void maybeAddArtifact(ISlangFileSystemExt* ext);
+
/// Calculate a display path -> can canonicalize if necessary
String calcVerbosePath() const;
@@ -250,11 +262,13 @@ public:
protected:
- SourceManager* m_sourceManager; ///< The source manager this belongs to
- PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span.
- ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents
- UnownedStringSlice m_content; ///< The actual contents of the file.
- size_t m_contentSize; ///< The size of the actual contents
+ SourceManager* m_sourceManager; ///< The source manager this belongs to
+ PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span.
+
+ ComPtr<IArtifact> m_artifact; ///< Optional artifact
+ ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents
+ UnownedStringSlice m_content; ///< The actual contents of the file.
+ size_t m_contentSize; ///< The size of the actual contents
// In order to speed up lookup of line number information,
// we will cache the starting offset of each line break in
diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp
index c1fb89555..17fb96ee8 100644
--- a/source/compiler-core/slang-visual-studio-compiler-util.cpp
+++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp
@@ -74,7 +74,6 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact
/* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
{
- 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
@@ -236,12 +235,17 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact
// https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2019
// /Eha - Specifies the model of exception handling. (a, s, c, r are options)
- // Files to compile
- for (const auto& sourceFile : options.sourceFiles)
+ // Files to compile, need to be on the file system.
+ for (IArtifact* sourceArtifact : options.sourceArtifacts)
{
- cmdLine.addArg(asString(sourceFile));
- }
+ ComPtr<IFileArtifactRepresentation> fileRep;
+ // TODO(JS):
+ // Do we want to keep the file on the file system? It's probably reasonable to do so.
+ SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef()));
+ cmdLine.addArg(fileRep->getPath());
+ }
+
// Link options (parameters past /link go to linker)
cmdLine.addArg("/link");
@@ -430,7 +434,7 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown
{
diagnostics->reset();
- diagnostics->setRaw(SliceCaster::asTerminatedCharSlice(exeRes.standardOutput));
+ diagnostics->setRaw(SliceUtil::asTerminatedCharSlice(exeRes.standardOutput));
SliceAllocator allocator;