summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--slang.h14
-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
-rw-r--r--source/core/slang-file-system.cpp17
-rw-r--r--source/core/slang-file-system.h6
-rw-r--r--source/core/slang-riff-file-system.h1
-rw-r--r--source/core/slang-zip-file-system.cpp1
-rw-r--r--source/slang/slang-compiler.cpp35
-rw-r--r--source/slang/slang-preprocessor.cpp5
-rw-r--r--source/slang/slang.cpp7
-rw-r--r--tools/slang-test/slang-test-main.cpp24
33 files changed, 663 insertions, 240 deletions
diff --git a/slang.h b/slang.h
index a224bf6f6..5be05bb61 100644
--- a/slang.h
+++ b/slang.h
@@ -1085,6 +1085,14 @@ extern "C"
The name is the name of a file system object (directory/file) in the specified path (ie it is without a path) */
typedef void (*FileSystemContentsCallBack)(SlangPathType pathType, const char* name, void* userData);
+ /* Determines how paths map to files on the OS file system */
+ enum class OSPathKind : uint8_t
+ {
+ None, ///< Paths do not map to the file system
+ Direct, ///< Paths map directly to the file system
+ Canonical, ///< Only canonical paths map to the file system
+ };
+
/** An extended file system abstraction.
Implementing and using this interface over ISlangFileSystem gives much more control over how paths
@@ -1200,6 +1208,12 @@ extern "C"
const char* path,
FileSystemContentsCallBack callback,
void* userData) = 0;
+
+ /** Returns how paths map to the OS file system
+
+ @returns true if this
+ */
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() = 0;
};
#define SLANG_UUID_ISlangFileSystemExt ISlangFileSystemExt::getTypeGuid()
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;
diff --git a/source/core/slang-file-system.cpp b/source/core/slang-file-system.cpp
index 6d9ad4324..208c4d834 100644
--- a/source/core/slang-file-system.cpp
+++ b/source/core/slang-file-system.cpp
@@ -291,6 +291,9 @@ void CacheFileSystem::setInnerFileSystem(ISlangFileSystem* fileSystem, UniqueIde
fileSystem->queryInterface(ISlangFileSystemExt::getTypeGuid(), (void**)m_fileSystemExt.writeRef());
}
+ // Determine how paths map
+ m_osPathKind = m_fileSystemExt ? m_fileSystemExt->getOSPathKind() : OSPathKind::None;
+
switch (m_uniqueIdentityMode)
{
case UniqueIdentityMode::Default:
@@ -746,6 +749,20 @@ RelativeFileSystem::RelativeFileSystem(ISlangFileSystem* fileSystem, const Strin
m_stripPath(stripPath)
{
m_style = _getFileSystemStyle(fileSystem, m_fileSystem);
+
+ m_osPathKind = OSPathKind::None;
+
+ ComPtr<ISlangFileSystemExt> ext;
+ if (SLANG_SUCCEEDED(fileSystem->queryInterface(ISlangFileSystemExt::getTypeGuid(), (void**)ext.writeRef())))
+ {
+ m_osPathKind = ext->getOSPathKind();
+
+ // If it's direct, but we have a relative path, canonical should work
+ if (m_osPathKind == OSPathKind::Direct && relativePath.getLength())
+ {
+ m_osPathKind = OSPathKind::Canonical;
+ }
+ }
}
ISlangUnknown* RelativeFileSystem::getInterface(const Guid& guid)
diff --git a/source/core/slang-file-system.h b/source/core/slang-file-system.h
index 3df05b6e1..c24d837b2 100644
--- a/source/core/slang-file-system.h
+++ b/source/core/slang-file-system.h
@@ -41,6 +41,7 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE {}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE { return OSPathKind::Direct; }
// ISlangModifyableFileSystem
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
@@ -155,6 +156,7 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE { return m_osPathKind; }
/// Get the unique identity mode
UniqueIdentityMode getUniqueIdentityMode() const { return m_uniqueIdentityMode; }
@@ -202,6 +204,8 @@ protected:
ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set
ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if nullptr will fall back on the m_fileSystem and emulate all the other methods of ISlangFileSystemExt
+
+ OSPathKind m_osPathKind = OSPathKind::None; ///< OS path kind
};
class RelativeFileSystem : public ISlangMutableFileSystem, public RefObject
@@ -220,6 +224,7 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE { return m_osPathKind; }
// ISlangModifyableFileSystem
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
@@ -245,6 +250,7 @@ protected:
ComPtr<ISlangFileSystem> m_fileSystem; ///< NOTE! Has to match what's in style, such style can be reached via reinterpret_cast
String m_relativePath;
+ OSPathKind m_osPathKind = OSPathKind::None; ///< OS path kind
};
}
diff --git a/source/core/slang-riff-file-system.h b/source/core/slang-riff-file-system.h
index 830fed71a..0f424b5ef 100644
--- a/source/core/slang-riff-file-system.h
+++ b/source/core/slang-riff-file-system.h
@@ -51,6 +51,7 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE {}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE { return OSPathKind::None; }
// ISlangModifyableFileSystem
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
diff --git a/source/core/slang-zip-file-system.cpp b/source/core/slang-zip-file-system.cpp
index 64ed64e13..636fd7d9e 100644
--- a/source/core/slang-zip-file-system.cpp
+++ b/source/core/slang-zip-file-system.cpp
@@ -37,6 +37,7 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE {}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE { return OSPathKind::None; }
// ISlangModifyableFileSystem
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 18c92ec1a..15a1ceb4b 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1051,14 +1051,16 @@ 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 = allocator.allocate(calcSourcePathForEntryPoints());
-
CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker);
SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(sourceArtifact));
+ // 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.
+ // We set the name to the path as this will be used for downstream reporting.
+ auto sourcePath = calcSourcePathForEntryPoints();
+ sourceArtifact->setName(sourcePath.getBuffer());
+
sourceCodeGenContext.maybeDumpIntermediate(sourceArtifact);
}
else
@@ -1067,10 +1069,17 @@ namespace Slang
const auto& sourceFiles = translationUnit->getSourceFiles();
SLANG_ASSERT(sourceFiles.getCount() == 1);
- const SourceFile* sourceFile = sourceFiles[0];
-
- options.sourceContentsPath = SliceCaster::asTerminatedCharSlice(sourceFile->getPathInfo().foundPath);
- options.sourceContents = SliceConverter::toTerminatedCharSlice(allocator, sourceFile->getContentBlob());
+ SourceFile* sourceFile = sourceFiles[0];
+
+ // Make it have an artifact if doesn't have one already
+ // This is useful because it will mean any reps will be kept in scope
+ //
+ // For example if file backing is needed, the file rep will last the lifetime of the
+ // SourceFile
+ sourceFile->maybeAddArtifact(nullptr);
+
+ sourceArtifact = sourceFile->getArtifact();
+ SLANG_ASSERT(sourceArtifact);
}
}
else
@@ -1087,11 +1096,9 @@ namespace Slang
if (sourceArtifact)
{
metadata = findAssociated<IArtifactPostEmitMetadata>(sourceArtifact);
-
- ComPtr<ISlangBlob> blob;
- SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()));
- options.sourceContents = SliceConverter::toTerminatedCharSlice(allocator, blob);
+ // Set the source artifacts
+ options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1);
}
// Add any preprocessor definitions associated with the linkage
@@ -1368,8 +1375,8 @@ namespace Slang
}
options.compilerSpecificArguments = allocator.allocate(compilerSpecificArguments);
- options.requiredCapabilityVersions = SliceCaster::asSlice(requiredCapabilityVersions);
- options.libraries = SliceCaster::asSlice(libraries);
+ options.requiredCapabilityVersions = SliceUtil::asSlice(requiredCapabilityVersions);
+ options.libraries = SliceUtil::asSlice(libraries);
options.libraryPaths = allocator.allocate(libraryPaths);
// Compile
diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp
index 0167b4a58..f1f7cffa4 100644
--- a/source/slang/slang-preprocessor.cpp
+++ b/source/slang/slang-preprocessor.cpp
@@ -3055,8 +3055,11 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
return;
}
-
sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob);
+
+ auto fileSystemExt = context->m_preprocessor->fileSystem;
+ sourceFile->maybeAddArtifact(fileSystemExt);
+
sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile);
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 6101a5298..a9868898e 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -2575,6 +2575,8 @@ void FrontEndCompileRequest::addTranslationUnitSourceBlob(
// The path specified may or may not be a file path - mark as being constructed 'FromString'.
SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(PathInfo::makeFromString(path), sourceBlob);
+ sourceFile->maybeAddArtifact(nullptr);
+
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
@@ -2586,6 +2588,8 @@ void FrontEndCompileRequest::addTranslationUnitSourceString(
// The path specified may or may not be a file path - mark as being constructed 'FromString'.
SourceFile* sourceFile = getSourceManager()->createSourceFileWithString(PathInfo::makeFromString(path), source);
+ sourceFile->maybeAddArtifact(nullptr);
+
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
@@ -2617,6 +2621,9 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile(
// Was loaded from the specified path
SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(pathInfo, sourceBlob);
+
+ sourceFile->maybeAddArtifact(getLinkage()->getFileSystemExt());
+
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index cd783bb05..ef5d16b2c 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -7,6 +7,9 @@
#include "../../source/core/slang-type-text-util.h"
#include "../../source/core/slang-memory-arena.h"
+#include "../../source/compiler-core/slang-artifact-desc-util.h"
+#include "../../source/compiler-core/slang-artifact-helper.h"
+
#include "../../slang-com-helper.h"
#include "../../source/core/slang-string-util.h"
@@ -2232,13 +2235,17 @@ static TestResult runCPPCompilerSharedLibrary(TestContext* context, TestInput& i
// Build a shared library
options.targetType = SLANG_SHADER_SHARED_LIBRARY;
+ auto helper = DefaultArtifactHelper::getSingleton();
+
// Compile this source
- TerminatedCharSlice sourceFiles[] = { SliceCaster::asTerminatedCharSlice(filePath) };
+ ComPtr<IArtifact> sourceArtifact;
+ helper->createFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef());
+
TerminatedCharSlice includePaths[] = { TerminatedCharSlice(".") };
- options.sourceFiles = makeSlice(sourceFiles, 1);
+ options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1);
options.includePaths = makeSlice(includePaths, 1);
- options.modulePath = SliceCaster::asTerminatedCharSlice(modulePath);
+ options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath);
ComPtr<IArtifact> artifact;
if (SLANG_FAILED(compiler->compile(options, artifact.writeRef())))
@@ -2353,11 +2360,16 @@ static TestResult runCPPCompilerExecute(TestContext* context, TestInput& input)
options.sourceLanguage = (ext == "c") ? SLANG_SOURCE_LANGUAGE_C : SLANG_SOURCE_LANGUAGE_CPP;
- TerminatedCharSlice filePaths[] = { SliceCaster::asTerminatedCharSlice(filePath) };
+ TerminatedCharSlice filePaths[] = { SliceUtil::asTerminatedCharSlice(filePath) };
+
+ auto helper = DefaultArtifactHelper::getSingleton();
+
+ ComPtr<IArtifact> sourceArtifact;
+ helper->createFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef());
// Compile this source
- options.sourceFiles = makeSlice(filePaths, 1);
- options.modulePath = SliceCaster::asTerminatedCharSlice(modulePath);
+ options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1);
+ options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath);
ComPtr<IArtifact> artifact;
if (SLANG_FAILED(compiler->compile(options, artifact.writeRef())))