summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-04-26 12:09:32 -0400
committerGitHub <noreply@github.com>2022-04-26 12:09:32 -0400
commit79dd12c21e8f5c5ce01051a280679cf6ac8ffe97 (patch)
tree705df0ab9047e4418a6218993cd0ddb2a46dffbc
parent66ad0072821b58318c6dc5d2d64c966e312951dd (diff)
Linking in DXC (#2190)
* #include an absolute path didn't work - because paths were taken to always be relative. * Compile to a dxil library. * Added CompileProduct. * Support handling of ModuleLibrary. * CacheBehavior -> Cache * Use CompileProduct for -r references. * CompileProduct -> Artifact. * Determining an artifact type on binding. * Determine binary linkability. * Added Artifact::exists. * Added ArtifactKeep. * Small fixes. * Small improvements to Artifact. * Add zip extension. * Fix some comments. * Fix multiple adding of PublicDecoration. Make public output export for DXIL/lib. Add checking for simpleDecorations such that only added once. * Use 'whole program' to identify library build. * Move slang-artifact into compiler-core. * Split out Keep free functions. * Artifact::Keep -> ArtifactKeep. * Handle libraries as artifacts. * Add -target dxil so test infrastructure knows it needs DXC. * Linking working in DXC. * Improve handling around emit for 'export'. * Add comment around Artifact name. * Render test working with linking. Co-authored-by: Theresa Foley <10618364+tangent-vector@users.noreply.github.com>
-rw-r--r--build/visual-studio/compiler-core/compiler-core.vcxproj2
-rw-r--r--build/visual-studio/compiler-core/compiler-core.vcxproj.filters6
-rw-r--r--build/visual-studio/slang/slang.vcxproj4
-rw-r--r--build/visual-studio/slang/slang.vcxproj.filters12
-rw-r--r--source/compiler-core/slang-artifact.cpp (renamed from source/slang/slang-artifact.cpp)135
-rw-r--r--source/compiler-core/slang-artifact.h (renamed from source/slang/slang-artifact.h)64
-rw-r--r--source/compiler-core/slang-downstream-compiler.h4
-rw-r--r--source/compiler-core/slang-dxc-compiler.cpp236
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp51
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp14
-rw-r--r--source/core/slang-command-line.cpp11
-rw-r--r--source/slang/slang-compiler.cpp11
-rw-r--r--source/slang/slang-emit-hlsl.cpp13
-rw-r--r--source/slang/slang-ir-link.cpp5
-rw-r--r--source/slang/slang-module-library.cpp95
-rw-r--r--source/slang/slang-module-library.h28
-rw-r--r--source/slang/slang-options.cpp3
-rw-r--r--source/slang/slang.cpp6
-rw-r--r--tests/library/library-test.slang7
-rw-r--r--tests/library/library-test.slang.expected.txt4
20 files changed, 504 insertions, 207 deletions
diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj b/build/visual-studio/compiler-core/compiler-core.vcxproj
index 028b85bce..8b71c250a 100644
--- a/build/visual-studio/compiler-core/compiler-core.vcxproj
+++ b/build/visual-studio/compiler-core/compiler-core.vcxproj
@@ -274,6 +274,7 @@
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="..\..\..\source\compiler-core\slang-artifact.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-command-line-args.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-core-diagnostics.h" />
<ClInclude Include="..\..\..\source\compiler-core\slang-diagnostic-sink.h" />
@@ -307,6 +308,7 @@
<ClInclude Include="..\..\..\source\compiler-core\windows\slang-win-visual-studio-util.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\source\compiler-core\slang-artifact.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-command-line-args.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-core-diagnostics.cpp" />
<ClCompile Include="..\..\..\source\compiler-core\slang-diagnostic-sink.cpp" />
diff --git a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters
index 76255bedf..2188afdd0 100644
--- a/build/visual-studio/compiler-core/compiler-core.vcxproj.filters
+++ b/build/visual-studio/compiler-core/compiler-core.vcxproj.filters
@@ -9,6 +9,9 @@
</Filter>
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="..\..\..\source\compiler-core\slang-artifact.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\compiler-core\slang-command-line-args.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -104,6 +107,9 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\source\compiler-core\slang-artifact.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\compiler-core\slang-command-line-args.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj
index a19bd40f5..a2cdcbb50 100644
--- a/build/visual-studio/slang/slang.vcxproj
+++ b/build/visual-studio/slang/slang.vcxproj
@@ -305,7 +305,6 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\slang.h" />
- <ClInclude Include="..\..\..\source\slang\slang-artifact.h" />
<ClInclude Include="..\..\..\source\slang\slang-ast-all.h" />
<ClInclude Include="..\..\..\source\slang\slang-ast-base.h" />
<ClInclude Include="..\..\..\source\slang\slang-ast-builder.h" />
@@ -405,6 +404,7 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClInclude Include="..\..\..\source\slang\slang-lower-to-ir.h" />
<ClInclude Include="..\..\..\source\slang\slang-mangle.h" />
<ClInclude Include="..\..\..\source\slang\slang-mangled-lexer.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-module-library.h" />
<ClInclude Include="..\..\..\source\slang\slang-options.h" />
<ClInclude Include="..\..\..\source\slang\slang-parameter-binding.h" />
<ClInclude Include="..\..\..\source\slang\slang-parser.h" />
@@ -438,7 +438,6 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClCompile Include="..\..\..\prelude\slang-cuda-prelude.h.cpp" />
<ClCompile Include="..\..\..\prelude\slang-hlsl-prelude.h.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-api.cpp" />
- <ClCompile Include="..\..\..\source\slang\slang-artifact.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-builder.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-decl.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-dump.cpp" />
@@ -542,6 +541,7 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClCompile Include="..\..\..\source\slang\slang-lower-to-ir.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-mangle.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-mangled-lexer.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-module-library.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-options.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-parameter-binding.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-parser.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters
index 1c7395675..e088ebbd0 100644
--- a/build/visual-studio/slang/slang.vcxproj.filters
+++ b/build/visual-studio/slang/slang.vcxproj.filters
@@ -12,9 +12,6 @@
<ClInclude Include="..\..\..\slang.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\..\..\source\slang\slang-artifact.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ast-all.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -312,6 +309,9 @@
<ClInclude Include="..\..\..\source\slang\slang-mangled-lexer.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-module-library.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-options.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -407,9 +407,6 @@
<ClCompile Include="..\..\..\source\slang\slang-api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\..\..\source\slang\slang-artifact.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ast-builder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -719,6 +716,9 @@
<ClCompile Include="..\..\..\source\slang\slang-mangled-lexer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-module-library.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-options.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/slang/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp
index 770f2202a..5d9f8692c 100644
--- a/source/slang/slang-artifact.cpp
+++ b/source/compiler-core/slang-artifact.cpp
@@ -1,15 +1,8 @@
// slang-artifact.cpp
#include "slang-artifact.h"
-#include <assert.h>
-
-#include "../core/slang-blob.h"
-#include "../core/slang-riff.h"
#include "../core/slang-type-text-util.h"
-
-// Serialization
-#include "slang-serialize-ir.h"
-#include "slang-serialize-container.h"
+#include "../core/slang-io.h"
namespace Slang {
@@ -70,41 +63,41 @@ static const KindExtension g_cpuKindExts[] =
}
}
- const auto target = (CodeGenTarget)TypeTextUtil::findCompileTargetFromExtension(slice);
+ const auto target = TypeTextUtil::findCompileTargetFromExtension(slice);
- return make(target);
+ return makeFromCompileTarget(target);
}
-/* static */ArtifactDesc ArtifactDesc::make(CodeGenTarget target)
+/* static */ArtifactDesc ArtifactDesc::makeFromCompileTarget(SlangCompileTarget target)
{
switch (target)
{
- case CodeGenTarget::Unknown: return make(Kind::Unknown, Payload::None, Style::Unknown, 0);
- case CodeGenTarget::None: return make(Kind::None, Payload::None, Style::Unknown, 0);
- case CodeGenTarget::GLSL_Vulkan:
- case CodeGenTarget::GLSL_Vulkan_OneDesc:
- case CodeGenTarget::GLSL:
+ case SLANG_TARGET_UNKNOWN: return make(Kind::Unknown, Payload::None, Style::Unknown, 0);
+ case SLANG_TARGET_NONE: return make(Kind::None, Payload::None, Style::Unknown, 0);
+ case SLANG_GLSL_VULKAN:
+ case SLANG_GLSL_VULKAN_ONE_DESC:
+ case SLANG_GLSL:
{
// For the moment we make all just map to GLSL, but we could use flags
// or some other mechanism to distinguish the types
return make(Kind::Text, Payload::GLSL, Style::Kernel, 0);
}
- case CodeGenTarget::HLSL: return make(Kind::Text, Payload::HLSL, Style::Kernel, 0);
- case CodeGenTarget::SPIRV: return make(Kind::Executable, Payload::SPIRV, Style::Kernel, 0);
- case CodeGenTarget::SPIRVAssembly: return make(Kind::Text, Payload::SPIRVAssembly, Style::Kernel, 0);
- case CodeGenTarget::DXBytecode: return make(Kind::Executable, Payload::DXBC, Style::Kernel, 0);
- case CodeGenTarget::DXBytecodeAssembly: return make(Kind::Text, Payload::DXBCAssembly, Style::Kernel, 0);
- case CodeGenTarget::DXIL: return make(Kind::Executable, Payload::DXIL, Style::Kernel, 0);
- case CodeGenTarget::DXILAssembly: return make(Kind::Text, Payload::DXILAssembly, Style::Kernel, 0);
- case CodeGenTarget::CSource: return make(Kind::Text, Payload::C, Style::Kernel, 0);
- case CodeGenTarget::CPPSource: return make(Kind::Text, Payload::CPP, Style::Kernel, 0);
- case CodeGenTarget::HostCPPSource: return make(Kind::Text, Payload::CPP, Style::Host, 0);
- case CodeGenTarget::HostExecutable: return make(Kind::Executable, Payload::HostCPU, Style::Host, 0);
- case CodeGenTarget::ShaderSharedLibrary: return make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0);
- case CodeGenTarget::ShaderHostCallable: return make(Kind::Callable, Payload::HostCPU, Style::Kernel, 0);
- case CodeGenTarget::CUDASource: return make(Kind::Text, Payload::CUDA, Style::Kernel, 0);
- case CodeGenTarget::PTX: return make(Kind::Executable, Payload::PTX, Style::Kernel, 0);
- case CodeGenTarget::ObjectCode: return make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_HLSL: return make(Kind::Text, Payload::HLSL, Style::Kernel, 0);
+ case SLANG_SPIRV: return make(Kind::Executable, Payload::SPIRV, Style::Kernel, 0);
+ case SLANG_SPIRV_ASM: return make(Kind::Text, Payload::SPIRVAssembly, Style::Kernel, 0);
+ case SLANG_DXBC: return make(Kind::Executable, Payload::DXBC, Style::Kernel, 0);
+ case SLANG_DXBC_ASM: return make(Kind::Text, Payload::DXBCAssembly, Style::Kernel, 0);
+ case SLANG_DXIL: return make(Kind::Executable, Payload::DXIL, Style::Kernel, 0);
+ case SLANG_DXIL_ASM: return make(Kind::Text, Payload::DXILAssembly, Style::Kernel, 0);
+ case SLANG_C_SOURCE: return make(Kind::Text, Payload::C, Style::Kernel, 0);
+ case SLANG_CPP_SOURCE: return make(Kind::Text, Payload::CPP, Style::Kernel, 0);
+ case SLANG_HOST_CPP_SOURCE: return make(Kind::Text, Payload::CPP, Style::Host, 0);
+ case SLANG_HOST_EXECUTABLE: return make(Kind::Executable, Payload::HostCPU, Style::Host, 0);
+ case SLANG_SHADER_SHARED_LIBRARY: return make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_SHADER_HOST_CALLABLE: return make(Kind::Callable, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_CUDA_SOURCE: return make(Kind::Text, Payload::CUDA, Style::Kernel, 0);
+ case SLANG_PTX: return make(Kind::Executable, Payload::PTX, Style::Kernel, 0);
+ case SLANG_OBJECT_CODE: return make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0);
default: break;
}
@@ -463,82 +456,4 @@ SlangResult Artifact::loadBlob(Keep keep, ComPtr<ISlangBlob>& outBlob)
return SLANG_OK;
}
-SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary)
-{
- RefPtr<ModuleLibrary> library = new ModuleLibrary;
-
- // Load up the module
- MemoryStreamBase memoryStream(FileAccess::Read, inBytes, bytesCount);
-
- RiffContainer riffContainer;
- SLANG_RETURN_ON_FAIL(RiffUtil::read(&memoryStream, riffContainer));
-
- auto linkage = req->getLinkage();
-
- // TODO(JS): May be better to have a ITypeComponent that encapsulates a collection of modules
- // For now just add to the linkage
-
- {
- SerialContainerData containerData;
-
- SerialContainerUtil::ReadOptions options;
- options.namePool = req->getNamePool();
- options.session = req->getSession();
- options.sharedASTBuilder = linkage->getASTBuilder()->getSharedASTBuilder();
- options.sourceManager = linkage->getSourceManager();
- options.linkage = req->getLinkage();
- options.sink = req->getSink();
-
- SLANG_RETURN_ON_FAIL(SerialContainerUtil::read(&riffContainer, options, containerData));
-
- for (const auto& module : containerData.modules)
- {
- // If the irModule is set, add it
- if (module.irModule)
- {
- library->m_modules.add(module.irModule);
- }
- }
-
- for (const auto& entryPoint : containerData.entryPoints)
- {
- FrontEndCompileRequest::ExtraEntryPointInfo dst;
- dst.mangledName = entryPoint.mangledName;
- dst.name = entryPoint.name;
- dst.profile = entryPoint.profile;
-
- // Add entry point
- library->m_entryPoints.add(dst);
- }
- }
-
- outLibrary = library;
- return SLANG_OK;
-}
-
-SlangResult loadModuleLibrary(Artifact::Keep keep, Artifact* product, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary)
-{
- if (auto foundLibrary = product->findObjectInstance<ModuleLibrary>())
- {
- outLibrary = foundLibrary;
- return SLANG_OK;
- }
-
- // Load the blob
- ComPtr<ISlangBlob> blob;
- SLANG_RETURN_ON_FAIL(product->loadBlob(Artifact::getIntermediateKeep(keep), blob));
-
- // Load the module
- RefPtr<ModuleLibrary> library;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)blob->getBufferPointer(), blob->getBufferSize(), req, library));
-
- if (Artifact::canKeep(keep))
- {
- product->add(Artifact::Entry::Style::Artifact, library);
- }
-
- outLibrary = library;
- return SLANG_OK;
-}
-
} // namespace Slang
diff --git a/source/slang/slang-artifact.h b/source/compiler-core/slang-artifact.h
index 0e009e990..232e9a8eb 100644
--- a/source/slang/slang-artifact.h
+++ b/source/compiler-core/slang-artifact.h
@@ -2,7 +2,10 @@
#ifndef SLANG_ARTIFACT_H
#define SLANG_ARTIFACT_H
-#include "slang-compiler.h"
+#include "../core/slang-basic.h"
+
+#include "../../slang-com-helper.h"
+#include "../../slang-com-ptr.h"
namespace Slang
{
@@ -88,6 +91,14 @@ struct ArtifactFlag
};
};
+// Controls what items can be kept.
+enum class ArtifactKeep
+{
+ No, ///< Don't keep the item
+ Yes, ///< Yes keep the final item
+ All, ///< Keep the final item and any intermediataries
+};
+
/**
A value type to describe aspects of the contents of an Artifact.
@@ -143,7 +154,7 @@ public:
bool operator!=(const This& rhs) const { return !(*this == rhs); }
/// Given a code gen target, get the equivalent ArtifactDesc
- static This make(CodeGenTarget target);
+ static This makeFromCompileTarget(SlangCompileTarget target);
/// Construct from the elements
static This make(Kind inKind, Payload inPayload, Style inStyle = Style::Kernel, Flags flags = 0)
@@ -211,7 +222,15 @@ A more long term goal would be to
* Make Artifact an interface (such that it can work long term over binary boundaries)
* Make Diagnostics into an interface (such it can be added to a Artifact result)
-* Use Artifact and related types for downstream compiler
+* Use Artifact and related types for downstream compiler
+
+TODO(JS): There is an issue here around libraries in that downstream compilers can use
+named libraries, but the name doesn't directly relate to a file. If it is a file it may
+not be easily possible to determine it's location. So there is a desire to indicate the
+`name` as opposed to the path.
+
+As a second related issue. Lets say we have a blob (and not a file).
+
*/
class Artifact : public RefObject
{
@@ -223,15 +242,8 @@ public:
typedef ArtifactPayload Payload;
typedef ArtifactStyle Style;
typedef ArtifactFlags Flags;
-
- // Controls what items can be kept.
- enum class Keep
- {
- No, ///< Don't keep the item
- Yes, ///< Yes keep the final item
- All, ///< Keep the final item and any intermediataries
- };
-
+ typedef ArtifactKeep Keep;
+
enum PathType
{
None,
@@ -304,14 +316,6 @@ public:
const List<Entry>& getEntries() const { return m_entries; }
- /// True if can keep an intermediate item
- static bool canKeepIntermediate(Keep keep) { return keep == Keep::All; }
- /// True if can keep
- static bool canKeep(Keep keep) { return Index(keep) >= Index(Keep::Yes); }
-
- /// Returns the keep type for an intermediate
- static Keep getIntermediateKeep(Keep keep) { return (keep == Keep::All) ? Keep::All : Keep::No; }
-
/// Ctor
Artifact(const Desc& desc) :m_desc(desc) {}
/// Dtor
@@ -350,20 +354,12 @@ T* Artifact::findObjectInstance()
return nullptr;
}
-
-// Class to hold information serialized in from a -r slang-lib/slang-module
-class ModuleLibrary : public RefObject
-{
-public:
-
- List<FrontEndCompileRequest::ExtraEntryPointInfo> m_entryPoints;
- List<RefPtr<IRModule>> m_modules;
-};
-
-SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module);
-
-// Given a product make available as a module
-SlangResult loadModuleLibrary(Artifact::Keep keep, Artifact* artifact, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module);
+/// True if can keep an intermediate item
+SLANG_INLINE bool canKeepIntermediate(ArtifactKeep keep) { return keep == ArtifactKeep::All; }
+ /// True if can keep
+SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(ArtifactKeep::Yes); }
+ /// Returns the keep type for an intermediate
+SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; }
} // namespace Slang
diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h
index e40ffc13a..e6c1f7a40 100644
--- a/source/compiler-core/slang-downstream-compiler.h
+++ b/source/compiler-core/slang-downstream-compiler.h
@@ -13,6 +13,8 @@
#include "../../slang-com-ptr.h"
+#include "slang-artifact.h"
+
namespace Slang
{
@@ -303,7 +305,7 @@ public:
List<String> libraryPaths;
/// Libraries to link against.
- List<String> libraries;
+ List<RefPtr<Artifact>> libraries;
List<CapabilityVersion> requiredCapabilityVersions;
diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp
index f5db290b1..eb26dd3cc 100644
--- a/source/compiler-core/slang-dxc-compiler.cpp
+++ b/source/compiler-core/slang-dxc-compiler.cpp
@@ -50,6 +50,52 @@ static UnownedStringSlice _getSlice(IDxcBlob* blob) { return StringUtil::getSlic
// 7f61fc7d-950d-467f-b3e3-3c02fb49187c
static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } };
+namespace { // anonymous
+
+class LibraryNameList
+{
+public:
+ void addName(Artifact* library)
+ {
+ String name;
+ if (library->getPathType() == Artifact::Existing)
+ {
+ name = Path::getFileNameWithoutExt(library->getPath());
+ }
+ addName(name);
+ }
+ void addName(const String& inName)
+ {
+ String name(inName);
+ if (name.getLength() == 0)
+ {
+ name = "unnamed";
+ }
+
+ if (m_names.indexOf(name) >= 0)
+ {
+ StringBuilder buf;
+ for (Index i = 1; ; ++i)
+ {
+ buf.Clear();
+ buf << name << "_" << i;
+
+ if (m_names.indexOf(buf) < 0)
+ {
+ name = buf;
+ break;
+ }
+ }
+ }
+
+ m_names.add(name);
+ }
+
+ List<String> m_names;
+};
+
+} // anonymous
+
class DxcIncludeHandler : public IDxcIncludeHandler
{
public:
@@ -137,6 +183,8 @@ public:
protected:
DxcCreateInstanceProc m_createInstance = nullptr;
+
+
ComPtr<ISlangSharedLibrary> m_sharedLibrary;
};
@@ -183,6 +231,60 @@ static SlangResult _parseDiagnosticLine(const UnownedStringSlice& line, List<Uno
return SLANG_OK;
}
+static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, DownstreamDiagnostics& ioDiagnostics, ComPtr<IDxcBlob>& outBlob)
+{
+ // Retrieve result.
+ HRESULT resultCode = S_OK;
+ SLANG_RETURN_ON_FAIL(dxcResult->GetStatus(&resultCode));
+
+ // Note: it seems like the dxcompiler interface
+ // doesn't support querying diagnostic output
+ // *unless* the compile failed (no way to get
+ // warnings out!?).
+
+ if (SLANG_SUCCEEDED(ioDiagnostics.result))
+ {
+ ioDiagnostics.result = resultCode;
+ }
+
+ // Try getting the error/diagnostics blob
+ ComPtr<IDxcBlobEncoding> dxcErrorBlob;
+ dxcResult->GetErrorBuffer(dxcErrorBlob.writeRef());
+
+ if (dxcErrorBlob)
+ {
+ const UnownedStringSlice diagnosticsSlice = _getSlice(dxcErrorBlob);
+ if (diagnosticsSlice.getLength())
+ {
+ if (ioDiagnostics.rawDiagnostics.getLength() > 0)
+ {
+ ioDiagnostics.rawDiagnostics.append("\n");
+ }
+ ioDiagnostics.rawDiagnostics.append(diagnosticsSlice);
+
+ SlangResult diagnosticParseRes = DownstreamDiagnostic::parseColonDelimitedDiagnostics(diagnosticsSlice, 0, _parseDiagnosticLine, ioDiagnostics.diagnostics);
+
+ SLANG_UNUSED(diagnosticParseRes);
+ SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes));
+ }
+ }
+
+ // If it failed, make sure we have an error in the diagnostics
+ if (SLANG_FAILED(resultCode))
+ {
+ // In case the parsing failed, we still have an error -> so require there is one in the diagnostics
+ ioDiagnostics.requireErrorDiagnostic();
+ }
+ else
+ {
+ // Okay, the compile supposedly succeeded, so we
+ // just need to grab the buffer with the output DXIL.
+ SLANG_RETURN_ON_FAIL(dxcResult->GetResult(outBlob.writeRef()));
+ }
+
+ return SLANG_OK;
+}
+
SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult)
{
// This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath
@@ -197,6 +299,22 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr
return SLANG_FAIL;
}
+ // Find all of the libraries
+ List<Artifact*> libraries;
+ for (Artifact* library : options.libraries)
+ {
+ const auto desc = library->getDesc();
+
+ if (desc.kind == ArtifactKind::Library && desc.payload == ArtifactPayload::DXIL)
+ {
+ // Make sure they all have blobs
+ ComPtr<ISlangBlob> libraryBlob;
+ SLANG_RETURN_ON_FAIL(library->loadBlob(ArtifactKeep::Yes, libraryBlob));
+
+ libraries.add(library);
+ }
+ }
+
ComPtr<IDxcCompiler> dxcCompiler;
SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef()));
ComPtr<IDxcLibrary> dxcLibrary;
@@ -289,8 +407,28 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr
//
args.add(L"-no-warnings");
+ String profileName = options.profileName;
+ // If we are going to link we have to compile in the lib profile style
+ if (libraries.getCount())
+ {
+ if (!profileName.startsWith("lib"))
+ {
+ const Index index = profileName.indexOf('_');
+ if (index < 0)
+ {
+ profileName = "lib_6_3";
+ }
+ else
+ {
+ StringBuilder buf;
+ buf << "lib" << profileName.getUnownedSlice().tail(index);
+ profileName = buf;
+ }
+ }
+ }
+
OSString wideEntryPointName = options.entryPointName.toWString();
- OSString wideProfileName = options.profileName.toWString();
+ OSString wideProfileName = profileName.toWString();
if (options.flags & CompileOptions::Flag::EnableFloat16)
{
@@ -319,50 +457,80 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr
&includeHandler, // `#include` handler
dxcResult.writeRef()));
- // Retrieve result.
- HRESULT resultCode = S_OK;
- SLANG_RETURN_ON_FAIL(dxcResult->GetStatus(&resultCode));
-
- // Note: it seems like the dxcompiler interface
- // doesn't support querying diagnostic output
- // *unless* the compile failed (no way to get
- // warnings out!?).
-
DownstreamDiagnostics diagnostics;
- diagnostics.result = resultCode;
- // Try getting the error/diagnostics blob
- ComPtr<IDxcBlobEncoding> dxcErrorBlob;
- dxcResult->GetErrorBuffer(dxcErrorBlob.writeRef());
+ ComPtr<IDxcBlob> dxcResultBlob;
- if (dxcErrorBlob)
+ SLANG_RETURN_ON_FAIL(_handleOperationResult(dxcResult, diagnostics, dxcResultBlob));
+
+ // If we have libraries then we need to link...
+ if (libraries.getCount())
{
- const UnownedStringSlice diagnosticsSlice = _getSlice(dxcErrorBlob);
- if (diagnosticsSlice.getLength())
+ ComPtr<IDxcLinker> linker;
+ SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef()));
+
+ List<ComPtr<ISlangBlob>> libraryBlobs;
+
+ LibraryNameList libraryNames;
+
+ for (Artifact* library : libraries)
{
- diagnostics.rawDiagnostics = String(diagnosticsSlice);
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(library->loadBlob(ArtifactKeep::Yes, blob));
- SlangResult diagnosticParseRes = DownstreamDiagnostic::parseColonDelimitedDiagnostics(diagnosticsSlice, 0, _parseDiagnosticLine, diagnostics.diagnostics);
+ libraryBlobs.add(blob);
+ libraryNames.addName(library);
+ }
- SLANG_UNUSED(diagnosticParseRes);
- SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes));
+ // Add the compiled blob name
+
+ {
+ auto blob = (ISlangBlob*)dxcResultBlob.get();
+ libraryBlobs.add(ComPtr<ISlangBlob>(blob));
}
- }
- ComPtr<IDxcBlob> dxcResultBlob;
+ if (options.modulePath.getLength())
+ {
+ libraryNames.addName(Path::getFileNameWithoutExt(options.modulePath));
+ }
+ else if (options.sourceContentsPath.getLength())
+ {
+ libraryNames.addName(Path::getFileNameWithoutExt(options.sourceContentsPath));
+ }
+ else
+ {
+ libraryNames.addName("");
+ }
- // If it failed, make sure we have an error in the diagnostics
- if (SLANG_FAILED(resultCode))
- {
- // In case the parsing failed, we still have an error -> so require there is one in the diagnostics
- diagnostics.requireErrorDiagnostic();
+ const Index librariesCount = libraryNames.m_names.getCount();
+ SLANG_ASSERT(libraryBlobs.getCount() == librariesCount);
+
+ List<const wchar_t*> linkLibraryNames;
+ List<OSString> wideLibraryNames;
+
+ linkLibraryNames.setCount(librariesCount);
+ wideLibraryNames.setCount(librariesCount);
+
+ for (Index i = 0; i < librariesCount; ++i)
+ {
+ wideLibraryNames[i] = libraryNames.m_names[i].toWString();
+ linkLibraryNames[i] = wideLibraryNames[i].begin();
+
+ // Register the library
+ SLANG_RETURN_ON_FAIL(linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get()));
+ }
+
+ // Use the original profile name
+ wideProfileName = options.profileName.toWString();
+
+ ComPtr<IDxcOperationResult> linkDxcResult;
+ SLANG_RETURN_ON_FAIL(linker->Link(wideEntryPointName.begin(), wideProfileName.begin(), linkLibraryNames.getBuffer(), UINT32(librariesCount), nullptr, 0, linkDxcResult.writeRef()));
+
+ ComPtr<IDxcBlob> linkedBlob;
+ SLANG_RETURN_ON_FAIL(_handleOperationResult(linkDxcResult, diagnostics, linkedBlob));
+
+ dxcResultBlob = linkedBlob;
}
- else
- {
- // Okay, the compile supposedly succeeded, so we
- // just need to grab the buffer with the output DXIL.
- SLANG_RETURN_ON_FAIL(dxcResult->GetResult(dxcResultBlob.writeRef()));
- }
outResult = new BlobDownstreamCompileResult(diagnostics, (ISlangBlob*)dxcResultBlob.get());
return SLANG_OK;
diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp
index 8d1b87b68..7d1b7b86a 100644
--- a/source/compiler-core/slang-gcc-compiler-util.cpp
+++ b/source/compiler-core/slang-gcc-compiler-util.cpp
@@ -619,6 +619,56 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
cmdLine.addArg(sourceFile);
}
+ // Add the library paths
+ List<String> libraryPaths;
+ libraryPaths.addRange(options.libraryPaths.getBuffer(), options.libraryPaths.getCount());
+
+ // Artifacts might add library paths
+ for (Artifact* artifact : options.libraries)
+ {
+ const auto desc = artifact->getDesc();
+ // If it's a library for CPU types, try and use it
+ if (desc.isCpuBinary())
+ {
+ if (desc.kind == ArtifactKind::Library)
+ {
+ String path;
+ SLANG_RETURN_ON_FAIL(artifact->requireFilePath(ArtifactKeep::No, path));
+
+ String parentDir = Path::getParentDirectory(parentDir);
+ if (parentDir.getLength())
+ {
+ // Check if we already have the library path, only add it if it's not found
+ if (libraryPaths.indexOf(parentDir) < 0)
+ {
+ libraryPaths.add(parentDir);
+ }
+ path = Path::getFileName(path);
+ }
+
+ // If it starts with lib strip it
+ if (path.startsWith("lib"))
+ {
+ const String stripLib = path.getUnownedSlice().tail(3);
+ path = stripLib;
+ }
+
+ // Strip the extension if it's a match
+ auto extension = Path::getPathExt(path);
+ if (extension.getLength())
+ {
+ auto libExt = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU).getDefaultExtension();
+ if (extension == libExt)
+ {
+ path = Path::getFileNameWithoutExt(path);
+ }
+ }
+
+ cmdLine.addPrefixPathArg("-l", path);
+ }
+ }
+ }
+
for (const auto& libPath : options.libraryPaths)
{
// Note that any escaping of the path is handled in the ProcessUtil::
@@ -628,6 +678,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
cmdLine.addArg(libPath);
}
+
if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind))
{
// Make STD libs available
diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp
index 2ba69c1ce..df64ed821 100644
--- a/source/compiler-core/slang-visual-studio-compiler-util.cpp
+++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp
@@ -257,9 +257,19 @@ namespace Slang
}
// Link libraries.
- for (const auto& lib : options.libraries)
+ for (Artifact* artifact : options.libraries)
{
- cmdLine.addPrefixPathArg("", lib, ".lib");
+ if (artifact->getDesc().isCpuBinary())
+ {
+ String path;
+ SLANG_RETURN_ON_FAIL(artifact->requireFilePath(ArtifactKeep::No, path));
+
+ if (Path::getPathExt(path).getLength() == 0)
+ {
+ path.append(".lib");
+ }
+ cmdLine.addArg(path);
+ }
}
return SLANG_OK;
diff --git a/source/core/slang-command-line.cpp b/source/core/slang-command-line.cpp
index 973bb46d0..f8b5ff10f 100644
--- a/source/core/slang-command-line.cpp
+++ b/source/core/slang-command-line.cpp
@@ -71,7 +71,16 @@ void ExecutableLocation::append(StringBuilder& out) const
void CommandLine::addPrefixPathArg(const char* prefix, const String& path, const char* pathPostfix)
{
StringBuilder builder;
- builder << prefix << path;
+ builder << prefix;
+
+ // TODO(JS): The assumption here is that quoting will be added as necessary and
+ // -prefixSomething Else
+ // is okay as
+ // "-prefixSomething Else" rather than
+ // -prefix"Something Else"
+
+ builder << path;
+
if (pathPostfix)
{
// Work out the path with the postfix
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 881194bcb..789103ff8 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1285,7 +1285,13 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
if (_isCPUHostTarget(target))
{
options.libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath()));
- options.libraries.add("slang-rt");
+
+ // Set up the library artifact
+ const ArtifactDesc desc = ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU, ArtifactStyle::Unknown);
+ RefPtr<Artifact> artifact = new Artifact(desc);
+ artifact->setPath(Artifact::PathType::Existing, "slang-rt");
+
+ options.libraries.add(artifact);
}
}
@@ -1386,6 +1392,9 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
options.defines.add(define);
}
}
+
+ // Add all of the module libraries
+ options.libraries.addRange(linkage->m_libModules.getBuffer(), linkage->m_libModules.getCount());
}
// Compile
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 059a3f641..03566f9df 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -739,14 +739,11 @@ void HLSLSourceEmitter::emitFuncDecorationImpl(IRDecoration* decoration)
const auto stage = profile.getStage();
const auto version = profile.getVersion();
- // I would perhaps ideally know that this was being compiled for 'library' stage.
- // Stage::Unknown is currently also used for lib profiles.
-
- // TODO(JS): Potentially can do export for fxc too, but for now we don't add.
-
- if (family == ProfileFamily::DX &&
- version >= ProfileVersion::DX_6_1 &&
- stage == Stage::Unknown)
+ // If it's whole program and it's for a late enough version of shader model
+ // output with 'export'
+ if (getTargetReq()->isWholeProgramRequest() &&
+ family == ProfileFamily::DX &&
+ version >= ProfileVersion::DX_6_1)
{
m_writer->emit("export\n");
}
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index b03d48764..fd91d81bb 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -6,7 +6,10 @@
#include "slang-ir-insts.h"
#include "slang-mangle.h"
#include "slang-ir-string-hash.h"
-#include "slang-artifact.h"
+
+#include "slang-module-library.h"
+
+#include "../compiler-core/slang-artifact.h"
namespace Slang
{
diff --git a/source/slang/slang-module-library.cpp b/source/slang/slang-module-library.cpp
new file mode 100644
index 000000000..76bb85ebb
--- /dev/null
+++ b/source/slang/slang-module-library.cpp
@@ -0,0 +1,95 @@
+// slang-module-library.cpp
+#include "slang-module-library.h"
+#include <assert.h>
+
+#include "../core/slang-blob.h"
+#include "../core/slang-riff.h"
+
+#include "../core/slang-type-text-util.h"
+
+// Serialization
+#include "slang-serialize-ir.h"
+#include "slang-serialize-container.h"
+
+namespace Slang {
+
+
+SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary)
+{
+ RefPtr<ModuleLibrary> library = new ModuleLibrary;
+
+ // Load up the module
+ MemoryStreamBase memoryStream(FileAccess::Read, inBytes, bytesCount);
+
+ RiffContainer riffContainer;
+ SLANG_RETURN_ON_FAIL(RiffUtil::read(&memoryStream, riffContainer));
+
+ auto linkage = req->getLinkage();
+
+ // TODO(JS): May be better to have a ITypeComponent that encapsulates a collection of modules
+ // For now just add to the linkage
+
+ {
+ SerialContainerData containerData;
+
+ SerialContainerUtil::ReadOptions options;
+ options.namePool = req->getNamePool();
+ options.session = req->getSession();
+ options.sharedASTBuilder = linkage->getASTBuilder()->getSharedASTBuilder();
+ options.sourceManager = linkage->getSourceManager();
+ options.linkage = req->getLinkage();
+ options.sink = req->getSink();
+
+ SLANG_RETURN_ON_FAIL(SerialContainerUtil::read(&riffContainer, options, containerData));
+
+ for (const auto& module : containerData.modules)
+ {
+ // If the irModule is set, add it
+ if (module.irModule)
+ {
+ library->m_modules.add(module.irModule);
+ }
+ }
+
+ for (const auto& entryPoint : containerData.entryPoints)
+ {
+ FrontEndCompileRequest::ExtraEntryPointInfo dst;
+ dst.mangledName = entryPoint.mangledName;
+ dst.name = entryPoint.name;
+ dst.profile = entryPoint.profile;
+
+ // Add entry point
+ library->m_entryPoints.add(dst);
+ }
+ }
+
+ outLibrary = library;
+ return SLANG_OK;
+}
+
+SlangResult loadModuleLibrary(ArtifactKeep keep, Artifact* product, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary)
+{
+ if (auto foundLibrary = product->findObjectInstance<ModuleLibrary>())
+ {
+ outLibrary = foundLibrary;
+ return SLANG_OK;
+ }
+
+ // Load the blob
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(product->loadBlob(getIntermediateKeep(keep), blob));
+
+ // Load the module
+ RefPtr<ModuleLibrary> library;
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)blob->getBufferPointer(), blob->getBufferSize(), req, library));
+
+ if (canKeep(keep))
+ {
+ product->add(Artifact::Entry::Style::Artifact, library);
+ }
+
+ outLibrary = library;
+ return SLANG_OK;
+}
+
+} // namespace Slang
diff --git a/source/slang/slang-module-library.h b/source/slang/slang-module-library.h
new file mode 100644
index 000000000..dc709a684
--- /dev/null
+++ b/source/slang/slang-module-library.h
@@ -0,0 +1,28 @@
+// slang-module-library.h
+#ifndef SLANG_MODULE_LIBRARY_H
+#define SLANG_MODULE_LIBRARY_H
+
+#include "../compiler-core/slang-artifact.h"
+
+#include "slang-compiler.h"
+
+namespace Slang
+{
+
+// Class to hold information serialized in from a -r slang-lib/slang-module
+class ModuleLibrary : public RefObject
+{
+public:
+
+ List<FrontEndCompileRequest::ExtraEntryPointInfo> m_entryPoints;
+ List<RefPtr<IRModule>> m_modules;
+};
+
+SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module);
+
+// Given a product make available as a module
+SlangResult loadModuleLibrary(ArtifactKeep keep, Artifact* artifact, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module);
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index d4199154f..4c7234753 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -9,7 +9,8 @@
#include "slang-compiler.h"
#include "slang-profile.h"
-#include "slang-artifact.h"
+
+#include "../compiler-core/slang-artifact.h"
#include "slang-repro.h"
#include "slang-serialize-ir.h"
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 5d4e61cc0..5b65cd15a 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -7,7 +7,9 @@
#include "../core/slang-type-text-util.h"
#include "../core/slang-type-convert-util.h"
-#include "slang-artifact.h"
+#include "../compiler-core/slang-artifact.h"
+
+#include "slang-module-library.h"
#include "slang-check.h"
#include "slang-parameter-binding.h"
@@ -4335,7 +4337,7 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, Artifact* artifact
{
RefPtr<ModuleLibrary> library;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary(Artifact::Keep::Yes, artifact, req, library));
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, artifact, req, library));
FrontEndCompileRequest* frontEndRequest = req->getFrontEndReq();
frontEndRequest->m_extraEntryPoints.addRange(library->m_entryPoints.getBuffer(), library->m_entryPoints.getCount());
diff --git a/tests/library/library-test.slang b/tests/library/library-test.slang
index 143b1cbe1..3543ced10 100644
--- a/tests/library/library-test.slang
+++ b/tests/library/library-test.slang
@@ -6,12 +6,11 @@
// This didn't work for lib_6_2 when compiling via DXC (!). Even though it's stated elsewhere the feature is available from 6.1
//TEST:COMPILE: tests/library/library.slang -profile lib_6_3 -target dxil -o tests/library/library.dxil
-//TEST:COMPILE: tests/library/library-test.slang -profile lib_6_3 -target dxil -o tests/library/library-test.dxil
+//TEST:COMPILE: tests/library/library-test.slang -entry computeMain -profile cs_6_3 -target dxil -r tests/library/library.dxil -o tests/library/library-test.dxil
-// It seems that I can't just compile the source containing the entry point/stage with the library/s.
-// Instead I have to compile all the parts with lib profile, and then link together at the end.
+// Test the produced kernel.
-//DISABLE_TEST:COMPARE_COMPUTE_EX:-slang -compute -xslang -r -xslang tests/serialization/serialized-module.slang-module -shaderobj
+//TEST:COMPARE_COMPUTE_EX:-slang -compute -profile cs_6_3 -dx12 -use-dxil -shaderobj -Xslang... -r tests/library/library.dxil -X.
extern int foo(int a);
diff --git a/tests/library/library-test.slang.expected.txt b/tests/library/library-test.slang.expected.txt
new file mode 100644
index 000000000..c0e0beb96
--- /dev/null
+++ b/tests/library/library-test.slang.expected.txt
@@ -0,0 +1,4 @@
+6
+9
+E
+15