summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-02-23 16:39:46 -0800
committerGitHub <noreply@github.com>2024-02-23 16:39:46 -0800
commit401d8cdb12ae69aeb216c80c9bb90240d8359649 (patch)
tree4548c9de52bdeff424a0a3969ad407fccb3c0f09
parent58eb6f7da01af1767282ee12b0b4b25c57e52afb (diff)
Add slangc interface to compile and use ir modules. (#3615)
* Add slangc interface to compile and use ir modules. * Fix glsl scalar layout settings not copied to target. * Fix. * Cleanups.
-rw-r--r--examples/platform-test/main.cpp4
-rw-r--r--slang.h4
-rw-r--r--source/compiler-core/slang-source-loc.h2
-rw-r--r--source/slang/slang-api.cpp3
-rw-r--r--source/slang/slang-check-decl.cpp15
-rw-r--r--source/slang/slang-check-modifier.cpp1
-rw-r--r--source/slang/slang-compiler.cpp11
-rwxr-xr-xsource/slang/slang-compiler.h19
-rw-r--r--source/slang/slang-ir-link.cpp9
-rw-r--r--source/slang/slang-module-library.cpp30
-rw-r--r--source/slang/slang-module-library.h6
-rw-r--r--source/slang/slang-options.cpp106
-rw-r--r--source/slang/slang-serialize-container.cpp72
-rw-r--r--source/slang/slang-serialize-container.h19
-rw-r--r--source/slang/slang-serialize-factory.cpp38
-rw-r--r--source/slang/slang.cpp137
-rw-r--r--tests/serialization/extern/extern-test.slang12
-rw-r--r--tests/serialization/extern/module-a.slang6
-rw-r--r--tests/serialization/extern/module-b.slang6
-rw-r--r--tests/serialization/obfuscated-loc-module.slang4
-rw-r--r--tests/serialization/obfuscated-module-check-loc.slang4
-rw-r--r--tests/serialization/obfuscated-serialized-module-shared.slang5
-rw-r--r--tests/serialization/obfuscated-serialized-module-test.slang14
-rw-r--r--tests/serialization/obfuscated-serialized-module.slang9
-rw-r--r--tests/serialization/serialized-module-shared.slang5
-rw-r--r--tests/serialization/serialized-module-test.slang9
-rw-r--r--tests/serialization/serialized-module.slang8
-rw-r--r--tools/render-test/slang-support.cpp164
-rw-r--r--tools/slang-test/slangc-tool.cpp8
29 files changed, 389 insertions, 341 deletions
diff --git a/examples/platform-test/main.cpp b/examples/platform-test/main.cpp
index 24673db1c..bfa00c5da 100644
--- a/examples/platform-test/main.cpp
+++ b/examples/platform-test/main.cpp
@@ -25,12 +25,12 @@ void onLostFocus()
void onKeyDown(platform::KeyEventArgs args)
{
- printf("onKeyDown(key=0x%02x, buttons=0x%02x)\n", args.key, args.buttons);
+ printf("onKeyDown(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons);
}
void onKeyUp(platform::KeyEventArgs args)
{
- printf("okKeyUp(key=0x%02x, buttons=0x%02x)\n", args.key, args.buttons);
+ printf("okKeyUp(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons);
}
void onKeyPress(platform::KeyEventArgs args)
diff --git a/slang.h b/slang.h
index 30aa8f2a8..e217f9ab4 100644
--- a/slang.h
+++ b/slang.h
@@ -855,7 +855,6 @@ extern "C"
ReportDownstreamTime, // bool
ReportPerfBenchmark, // bool
SkipSPIRVValidation, // bool
-
SourceEmbedStyle,
SourceEmbedName,
SourceEmbedLanguage,
@@ -1845,6 +1844,7 @@ extern "C"
/*! @see slang::ICompileRequest::addLibraryReference */
SLANG_API SlangResult spAddLibraryReference(
SlangCompileRequest* request,
+ const char* basePath,
const void* libData,
size_t libDataSize);
@@ -3952,10 +3952,12 @@ namespace slang
/** Add a slang library - such that its contents can be referenced during linking.
This is equivalent to the -r command line option.
+ @param basePath The base path used to lookup referenced modules.
@param libData The library data
@param libDataSize The size of the library data
*/
virtual SLANG_NO_THROW SlangResult SLANG_MCALL addLibraryReference(
+ const char* basePath,
const void* libData,
size_t libDataSize) = 0;
diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h
index a5919d809..0a94980d1 100644
--- a/source/compiler-core/slang-source-loc.h
+++ b/source/compiler-core/slang-source-loc.h
@@ -61,7 +61,7 @@ struct PathInfo
/// True if has a canonical path
SLANG_FORCE_INLINE bool hasUniqueIdentity() const { return type == Type::Normal && uniqueIdentity.getLength() > 0; }
/// True if has a regular found path
- SLANG_FORCE_INLINE bool hasFoundPath() const { return type == Type::Normal || type == Type::FoundPath || (type == Type::FromString && foundPath.getLength() > 0); }
+ 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.
diff --git a/source/slang/slang-api.cpp b/source/slang/slang-api.cpp
index 864bc8b7d..7284f2468 100644
--- a/source/slang/slang-api.cpp
+++ b/source/slang/slang-api.cpp
@@ -495,11 +495,12 @@ SLANG_API void spSetDefaultModuleName(
SLANG_API SlangResult spAddLibraryReference(
slang::ICompileRequest* request,
+ const char* basePath,
const void* libData,
size_t libDataSize)
{
SLANG_ASSERT(request);
- return request->addLibraryReference(libData, libDataSize);
+ return request->addLibraryReference(basePath, libData, libDataSize);
}
SLANG_API void spTranslationUnit_addPreprocessorDefine(
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 28db66c45..25f535825 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -1712,7 +1712,7 @@ namespace Slang
{
if (auto varDeclRefType = as<DeclRefType>(varDecl->type.type))
{
- parentAggTypeDecl->unionTagsWith(getTypeTags(varDecl->type.type));
+ parentAggTypeDecl->unionTagsWith(getTypeTags(varDeclRefType));
}
}
@@ -9321,20 +9321,21 @@ namespace Slang
else if (as<PrivateModifier>(modifier))
return DeclVisibility::Private;
}
-
// Interface members will always have the same visibility as the interface itself.
if (auto interfaceDecl = findParentInterfaceDecl(decl))
{
return getDeclVisibility(interfaceDecl);
}
- else if (as<NamespaceDecl>(decl))
+ auto defaultVis = DeclVisibility::Default;
+ if (auto parentModule = getModuleDecl(decl))
+ defaultVis = parentModule->isInLegacyLanguage ? DeclVisibility::Public : DeclVisibility::Internal;
+
+ // Members of other agg type decls will have their default visibility capped to the parents'.
+ if (as<NamespaceDecl>(decl))
{
return DeclVisibility::Public;
}
- if (auto parentModule = getModuleDecl(decl))
- return parentModule->isInLegacyLanguage ? DeclVisibility::Public : DeclVisibility::Internal;
-
- return DeclVisibility::Default;
+ return defaultVis;
}
void diagnoseCapabilityProvenance(DiagnosticSink* sink, Decl* decl, CapabilityAtom missingAtom)
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index a4e906ac9..2d9107431 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -989,7 +989,6 @@ namespace Slang
case ASTNodeType::PreciseModifier:
case ASTNodeType::IntrinsicOpModifier:
case ASTNodeType::InlineModifier:
- case ASTNodeType::ExternModifier:
case ASTNodeType::HLSLExportModifier:
case ASTNodeType::ExternCppModifier:
case ASTNodeType::ExportedModifier:
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index c0be68723..78aa4a18b 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1488,7 +1488,7 @@ namespace Slang
// Add all of the module libraries
libraries.addRange(linkage->m_libModules.getBuffer(), linkage->m_libModules.getCount());
}
-
+
options.compilerSpecificArguments = allocator.allocate(compilerSpecificArguments);
options.requiredCapabilityVersions = SliceUtil::asSlice(requiredCapabilityVersions);
options.libraries = SliceUtil::asSlice(libraries);
@@ -1879,14 +1879,7 @@ namespace Slang
SerialContainerUtil::WriteOptions options;
options.compressionType = linkage->m_optionSet.getEnumOption<SerialCompressionType>(CompilerOptionName::IrCompression);
- if (linkage->m_optionSet.getBoolOption(CompilerOptionName::Obfuscate))
- {
- // If code is obfuscated, we *disable* AST output as it is not obfuscated and will reveal
- // too much about IR.
- // Also currently only IR is needed.
- options.optionFlags &= ~SerialOptionFlag::ASTModule;
- }
-
+
// If debug information is enabled, enable writing out source locs
if (_shouldWriteSourceLocs(linkage))
{
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 6c55a7807..ece552cec 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -25,12 +25,10 @@
#include "slang-capability.h"
#include "slang-diagnostics.h"
-
#include "slang-preprocessor.h"
#include "slang-profile.h"
#include "slang-syntax.h"
#include "slang-content-assist-info.h"
-
#include "slang-hlsl-to-vulkan-layout-options.h"
#include "slang-compiler-options.h"
#include "slang-serialize-ir-types.h"
@@ -1475,7 +1473,7 @@ namespace Slang
RefPtr<EntryPoint> findEntryPointByName(UnownedStringSlice const& name);
- List<RefPtr<EntryPoint>> const& getEntryPoints() { return m_entryPoints; }
+ List<RefPtr<EntryPoint>>& getEntryPoints() { return m_entryPoints; }
void _addEntryPoint(EntryPoint* entryPoint);
void _processFindDeclsExportSymbolsRec(Decl* decl);
@@ -1551,6 +1549,8 @@ namespace Slang
public:
TranslationUnitRequest(
FrontEndCompileRequest* compileRequest);
+ TranslationUnitRequest(
+ FrontEndCompileRequest* compileRequest, Module* m);
// The parent compile request
FrontEndCompileRequest* compileRequest = nullptr;
@@ -1596,6 +1596,8 @@ namespace Slang
/// Result of compiling this translation unit (a module)
RefPtr<Module> module;
+ bool isChecked = false;
+
Module* getModule() { return module; }
ModuleDecl* getModuleDecl() { return module->getModuleDecl(); }
@@ -1755,6 +1757,8 @@ namespace Slang
Source, IR
};
+ struct SerialContainerDataModule;
+
/// A context for loading and re-using code modules.
class Linkage : public RefObject, public slang::ISession
{
@@ -1959,6 +1963,11 @@ namespace Slang
SourceLoc const& loc,
DiagnosticSink* sink,
const LoadedModuleDictionary* additionalLoadedModules);
+ RefPtr<Module> loadDeserializedModule(
+ Name* name,
+ const PathInfo& filePathInfo,
+ SerialContainerDataModule& m,
+ DiagnosticSink* sink);
SourceFile* loadSourceFile(String pathFrom, String path);
@@ -1979,7 +1988,7 @@ namespace Slang
DiagnosticSink* sink,
const LoadedModuleDictionary* loadedModules = nullptr);
- void prepareDeserializedModule(Module* module, DiagnosticSink* sink);
+ void prepareDeserializedModule(SerialContainerDataModule& moduleEntry, const PathInfo& pathInfo, Module* module, DiagnosticSink* sink);
SourceFile* findFile(Name* name, SourceLoc loc, IncludeSystem& outIncludeSystem);
struct IncludeResult
@@ -2661,7 +2670,7 @@ namespace Slang
virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitPreprocessorDefine(int translationUnitIndex, const char* key, const char* value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceFile(int translationUnitIndex, char const* path) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceString(int translationUnitIndex, char const* path, char const* source) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL addLibraryReference(const void* libData, size_t libDataSize) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL addLibraryReference(const char* basePath, const void* libData, size_t libDataSize) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceStringSpan(int translationUnitIndex, char const* path, char const* sourceBegin, char const* sourceEnd) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceBlob(int translationUnitIndex, char const* path, ISlangBlob* sourceBlob) SLANG_OVERRIDE;
virtual SLANG_NO_THROW int SLANG_MCALL addEntryPoint(int translationUnitIndex, char const* name, SlangStage stage) SLANG_OVERRIDE;
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index eb0068657..be0b87b60 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -1477,14 +1477,7 @@ LinkedIR linkIR(
{
irModules.add(irModule);
});
- for (IArtifact* artifact : linkage->m_libModules)
- {
- if (auto library = findRepresentation<ModuleLibrary>(artifact))
- {
- irModules.addRange(library->m_modules.getBuffer()->readRef(), library->m_modules.getCount());
- }
- }
-
+
// Add any modules that were loaded as libraries
for (IRModule* irModule : irModules)
{
diff --git a/source/slang/slang-module-library.cpp b/source/slang/slang-module-library.cpp
index 0975d6e8f..02ace07d3 100644
--- a/source/slang/slang-module-library.cpp
+++ b/source/slang/slang-module-library.cpp
@@ -39,7 +39,7 @@ void* ModuleLibrary::castAs(const Guid& guid)
return getObject(guid);
}
-SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary)
+SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, String path, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary)
{
auto library = new ModuleLibrary;
ComPtr<IModuleLibrary> scopeLibrary(library);
@@ -51,10 +51,6 @@ SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCo
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;
@@ -65,15 +61,29 @@ SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCo
options.sourceManager = linkage->getSourceManager();
options.linkage = req->getLinkage();
options.sink = req->getSink();
-
+ options.astBuilder = linkage->getASTBuilder();
+ options.modulePath = path;
SLANG_RETURN_ON_FAIL(SerialContainerUtil::read(&riffContainer, options, nullptr, containerData));
+ DiagnosticSink sink;
- for (const auto& module : containerData.modules)
+ // Modules in the container should be serialized in its depedency order,
+ // so that we always load the dependencies before the consuming module.
+ for (auto& module : containerData.modules)
{
// If the irModule is set, add it
if (module.irModule)
{
- library->m_modules.add(module.irModule);
+ if (module.dependentFiles.getCount() == 0)
+ return SLANG_FAIL;
+ if (!module.astRootNode)
+ return SLANG_FAIL;
+ auto loadedModule = linkage->loadDeserializedModule(
+ as<ModuleDecl>(module.astRootNode)->getName(),
+ PathInfo::makePath(module.dependentFiles.getFirst()),
+ module, &sink);
+ if (!loadedModule)
+ return SLANG_FAIL;
+ library->m_modules.add(loadedModule);
}
}
@@ -93,7 +103,7 @@ SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCo
return SLANG_OK;
}
-SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary)
+SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, String path, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary)
{
if (auto foundLibrary = findRepresentation<IModuleLibrary>(artifact))
{
@@ -107,7 +117,7 @@ SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCo
// Load the module
ComPtr<IModuleLibrary> library;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)blob->getBufferPointer(), blob->getBufferSize(), req, library));
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)blob->getBufferPointer(), blob->getBufferSize(), path, req, library));
if (canKeep(keep))
{
diff --git a/source/slang/slang-module-library.h b/source/slang/slang-module-library.h
index 698e4e014..9e3d7a2e8 100644
--- a/source/slang/slang-module-library.h
+++ b/source/slang/slang-module-library.h
@@ -30,16 +30,16 @@ public:
virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return true; }
List<FrontEndCompileRequest::ExtraEntryPointInfo> m_entryPoints;
- List<RefPtr<IRModule>> m_modules;
+ List<RefPtr<Module>> m_modules;
void* getInterface(const Guid& uuid);
void* getObject(const Guid& uuid);
};
-SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule);
+SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, String Path, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule);
// Given a product make available as a module
-SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule);
+SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, String Path, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule);
} // namespace Slang
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 8e94b73cc..39578a1ea 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -557,7 +557,7 @@ void initCommandOptions(CommandOptions& options)
SLANG_ASSERT(options.hasContiguousUserValueRange(CommandOptions::LookupKind::Category, UserValue(0), UserValue(ValueCategory::CountOf)));
}
-SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifact);
+SlangResult _addLibraryReference(EndToEndCompileRequest* req, String path, IArtifact* artifact, bool includeEntryPoint);
class ReproPathVisitor : public Slang::Path::Visitor
{
@@ -650,7 +650,6 @@ struct OptionsParser
struct RawTarget
{
CodeGenTarget format = CodeGenTarget::Unknown;
- SlangTargetFlags targetFlags = kDefaultTargetFlags;
int targetID = -1;
CompilerOptionSet optionSet;
@@ -736,6 +735,7 @@ struct OptionsParser
void _appendMinimalUsage(StringBuilder& out);
void _outputMinimalUsage();
+ SlangResult addReferencedModule(String path, SourceLoc loc, bool includeEntryPoint);
SlangResult _parseReferenceModule(const CommandLineArg& arg);
SlangResult _parseReproFileSystem(const CommandLineArg& arg);
SlangResult _parseLoadRepro(const CommandLineArg& arg);
@@ -772,9 +772,6 @@ struct OptionsParser
// If not, it will be `-1`.
int m_slangTranslationUnitIndex = -1;
- // The number of input files that have been specified
- int m_inputPathCount = 0;
-
int m_translationUnitCount = 0;
int m_currentTranslationUnitIndex = -1;
@@ -931,13 +928,15 @@ SlangSourceLanguage findSourceLanguageFromPath(const String& path, Stage& outImp
SlangResult OptionsParser::addInputPath(char const* inPath, SourceLanguage langOverride )
{
- m_inputPathCount++;
-
// look at the extension on the file name to determine
// how we should handle it.
String path = String(inPath);
- if (path.endsWith(".slang") || langOverride == SourceLanguage::Slang)
+ if (path.endsWith(".slang-module") || path.endsWith(".slang-lib"))
+ {
+ return addReferencedModule(path, SourceLoc(), false);
+ }
+ else if (path.endsWith(".slang") || langOverride == SourceLanguage::Slang)
{
// Plain old slang code
addInputSlangPath(path);
@@ -1298,20 +1297,13 @@ SlangResult OptionsParser::_expectInt(const CommandLineArg& initArg, Int& outInt
return SLANG_OK;
}
-SlangResult OptionsParser::_parseReferenceModule(const CommandLineArg& arg)
+SlangResult OptionsParser::addReferencedModule(String path, SourceLoc loc, bool includeEntryPoint)
{
- SLANG_UNUSED(arg);
-
- CommandLineArg referenceModuleName;
- SLANG_RETURN_ON_FAIL(m_reader.expectArg(referenceModuleName));
-
- const auto path = referenceModuleName.value;
-
auto desc = ArtifactDescUtil::getDescFromPath(path.getUnownedSlice());
if (desc.kind == ArtifactKind::Unknown)
{
- m_sink->diagnose(referenceModuleName.loc, Diagnostics::unknownLibraryKind, Path::getPathExt(path));
+ m_sink->diagnose(loc, Diagnostics::unknownLibraryKind, Path::getPathExt(path));
return SLANG_FAIL;
}
@@ -1329,7 +1321,7 @@ SlangResult OptionsParser::_parseReferenceModule(const CommandLineArg& arg)
if (!ArtifactDescUtil::isLinkable(desc))
{
- m_sink->diagnose(referenceModuleName.loc, Diagnostics::kindNotLinkable, Path::getPathExt(path));
+ m_sink->diagnose(loc, Diagnostics::kindNotLinkable, Path::getPathExt(path));
return SLANG_FAIL;
}
@@ -1354,16 +1346,36 @@ SlangResult OptionsParser::_parseReferenceModule(const CommandLineArg& arg)
fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice(), nullptr);
if (!fileRep->exists())
{
- m_sink->diagnose(referenceModuleName.loc, Diagnostics::libraryDoesNotExist, path);
+ m_sink->diagnose(loc, Diagnostics::libraryDoesNotExist, path);
return SLANG_FAIL;
}
}
artifact->addRepresentation(fileRep);
- SLANG_RETURN_ON_FAIL(_addLibraryReference(m_requestImpl, artifact));
+ SLANG_RETURN_ON_FAIL(_addLibraryReference(m_requestImpl, path, artifact, includeEntryPoint));
+ for (Index i = m_rawTranslationUnits.getCount(); i < m_requestImpl->getTranslationUnitCount(); i++)
+ {
+ RawTranslationUnit rawTU;
+ rawTU.translationUnitID = (int)i;
+ rawTU.impliedStage = Stage::Unknown;
+ rawTU.sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG;
+ m_rawTranslationUnits.add(rawTU);
+ }
+ m_currentTranslationUnitIndex = m_requestImpl->getTranslationUnitCount() - 1;
+ m_slangTranslationUnitIndex = m_currentTranslationUnitIndex;
return SLANG_OK;
}
+SlangResult OptionsParser::_parseReferenceModule(const CommandLineArg& arg)
+{
+ SLANG_UNUSED(arg);
+
+ CommandLineArg referenceModuleName;
+ SLANG_RETURN_ON_FAIL(m_reader.expectArg(referenceModuleName));
+
+ return addReferencedModule(referenceModuleName.value, referenceModuleName.loc, true);
+}
+
SlangResult OptionsParser::_parseReproFileSystem(const CommandLineArg& arg)
{
SLANG_UNUSED(arg);
@@ -2171,13 +2183,9 @@ SlangResult OptionsParser::_parse(
return SLANG_FAIL;
}
case OptionKind::EmitSpirvViaGLSL:
- {
- getCurrentTarget()->targetFlags &= ~SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY;
- }
- break;
case OptionKind::EmitSpirvDirectly:
{
- getCurrentTarget()->targetFlags |= SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY;
+ getCurrentTarget()->optionSet.add(optionKind, true);
}
break;
case OptionKind::SPIRVCoreGrammarJSON:
@@ -2367,7 +2375,8 @@ SlangResult OptionsParser::_parse(
entryPoint.translationUnitIndex = 0;
}
}
- else
+ else if (m_frontEndReq->additionalLoadedModules &&
+ m_frontEndReq->additionalLoadedModules->getCount() == 0)
{
// Otherwise, we require that all entry points be specified after
// the translation unit to which tye belong.
@@ -2610,21 +2619,7 @@ SlangResult OptionsParser::_parse(
if (m_rawTargets.getCount() == 1)
{
- if (m_defaultTarget.optionSet.getProfileVersion() != ProfileVersion::Unknown)
- {
- setProfileVersion(getCurrentTarget(), m_defaultTarget.optionSet.getProfileVersion());
- }
- for (auto atom : m_defaultTarget.optionSet.getArray(CompilerOptionName::Capability))
- {
- addCapabilityAtom(getCurrentTarget(), (CapabilityName)atom.intValue);
- }
-
- getCurrentTarget()->targetFlags |= m_defaultTarget.targetFlags;
-
- if (defaultTargetFloatingPointMode != FloatingPointMode::Default)
- {
- setFloatingPointMode(getCurrentTarget(), defaultTargetFloatingPointMode);
- }
+ m_rawTargets[0].optionSet.overrideWith(m_defaultTarget.optionSet);
}
else
{
@@ -2648,18 +2643,6 @@ SlangResult OptionsParser::_parse(
}
}
- if (m_defaultTarget.targetFlags != kDefaultTargetFlags)
- {
- if (m_rawTargets.getCount() == 0)
- {
- m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseNoTargets);
- }
- else
- {
- m_sink->diagnose(SourceLoc(), Diagnostics::targetFlagsIgnoredBecauseBeforeAllTargets);
- }
- }
-
if (defaultTargetFloatingPointMode != FloatingPointMode::Default)
{
if (m_rawTargets.getCount() == 0)
@@ -2705,11 +2688,6 @@ SlangResult OptionsParser::_parse(
m_requestImpl->addTargetCapability(targetID, SlangCapabilityID(atom.intValue));
}
- if (rawTarget.targetFlags)
- {
- m_compileRequest->setTargetFlags(targetID, rawTarget.targetFlags);
- }
-
auto floatingPointMode = rawTarget.optionSet.getEnumOption<FloatingPointMode>(CompilerOptionName::FloatingPointMode);
if (floatingPointMode != FloatingPointMode::Default)
{
@@ -2826,7 +2804,7 @@ SlangResult OptionsParser::_parse(
break;
case CodeGenTarget::SPIRV:
case CodeGenTarget::SPIRVAssembly:
- if (getCurrentTarget()->targetFlags & SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY)
+ if (getCurrentTarget()->optionSet.shouldEmitSPIRVDirectly())
{
rawOutput.isWholeProgram = true;
}
@@ -2857,7 +2835,7 @@ SlangResult OptionsParser::_parse(
targetInfo = new EndToEndCompileRequest::TargetInfo();
m_requestImpl->m_targetInfos[target] = targetInfo;
}
-
+ target->getOptionSet().overrideWith(m_rawTargets[rawOutput.targetIndex].optionSet);
if (rawOutput.isWholeProgram)
{
if (targetInfo->wholeTargetOutputPath != "")
@@ -2874,7 +2852,13 @@ SlangResult OptionsParser::_parse(
{
if (rawOutput.entryPointIndex == -1) continue;
- Int entryPointID = m_rawEntryPoints[rawOutput.entryPointIndex].entryPointID;
+ auto entryPoint = m_rawEntryPoints[rawOutput.entryPointIndex];
+ Int entryPointID = entryPoint.entryPointID;
+ if (entryPointID == -1)
+ {
+ m_sink->diagnose(SourceLoc(), Diagnostics::entryPointFunctionNotFound, entryPoint.name);
+ continue;
+ }
auto entryPointReq = m_requestImpl->getFrontEndReq()->getEntryPointReqs()[entryPointID];
//String outputPath;
diff --git a/source/slang/slang-serialize-container.cpp b/source/slang/slang-serialize-container.cpp
index c9db7ff5e..0622c2bd4 100644
--- a/source/slang/slang-serialize-container.cpp
+++ b/source/slang/slang-serialize-container.cpp
@@ -83,21 +83,29 @@ namespace Slang {
DigestBuilder<SHA1> digestBuilder;
module->getOptionSet().buildHash(digestBuilder);
auto fileDependencies = module->getFileDependencies();
- String canonicalModulePath;
+ String canonicalModulePath, moduleDir;
if (auto modulePath = module->getFilePath())
{
- canonicalModulePath = Path::getParentDirectory(modulePath);
+ canonicalModulePath = modulePath;
Path::getCanonical(canonicalModulePath, canonicalModulePath);
+ moduleDir = Path::getParentDirectory(canonicalModulePath);
}
for (auto file : fileDependencies)
{
digestBuilder.append(file->getDigest());
if (file->getPathInfo().hasFoundPath())
{
- String canonicalFilePath = file->getPathInfo().foundPath;
- Path::getCanonical(file->getPathInfo().foundPath, canonicalFilePath);
- canonicalFilePath = Path::getRelativePath(canonicalModulePath, canonicalFilePath);
- dstModule.dependentFiles.add(canonicalFilePath);
+ if (file->getPathInfo().foundPath == canonicalModulePath)
+ {
+ dstModule.dependentFiles.add(Path::getFileName(canonicalModulePath));
+ }
+ else
+ {
+ String canonicalFilePath = file->getPathInfo().foundPath;
+ Path::getCanonical(file->getPathInfo().foundPath, canonicalFilePath);
+ canonicalFilePath = Path::getRelativePath(moduleDir, canonicalFilePath);
+ dstModule.dependentFiles.add(canonicalFilePath);
+ }
}
else
{
@@ -112,6 +120,20 @@ namespace Slang {
}
+static SlangResult _addModuleRecursive(HashSet<Module*>& processedModuleSet, const SerialContainerUtil::WriteOptions& options, SerialContainerData& container, Module* module)
+{
+ if (processedModuleSet.contains(module))
+ return SLANG_OK;
+ for (auto m : module->getModuleDependencies())
+ {
+ if (m != module)
+ _addModuleRecursive(processedModuleSet, options, container, m);
+ }
+ processedModuleSet.add(module);
+ return SerialContainerUtil::addModuleToData(module, options, container);
+}
+
+
/* static */SlangResult SerialContainerUtil::addFrontEndRequestToData(FrontEndCompileRequest* frontEndReq, const WriteOptions& options, SerialContainerData& outData)
{
// Go through translation units, adding modules
@@ -124,12 +146,12 @@ namespace Slang {
}
/* static */SlangResult SerialContainerUtil::addEndToEndRequestToData(EndToEndCompileRequest* request, const WriteOptions& options, SerialContainerData& out)
-{
+{
auto linkage = request->getLinkage();
auto sink = request->getSink();
- // Output the front end request data
- SLANG_RETURN_ON_FAIL(addFrontEndRequestToData(request->getFrontEndReq(), options, out));
+ // Output the parsed modules.
+ addFrontEndRequestToData(request->getFrontEndReq(), options, out);
//
auto program = request->getSpecializedGlobalAndEntryPointsComponentType();
@@ -388,6 +410,19 @@ static List<ExtensionDecl*>& _getCandidateExtensionList(
SLANG_RETURN_ON_FAIL(sourceLocReader->read(&sourceLocData, options.sourceManager));
}
+ // Create a source loc representing the binary module.
+ SourceLoc binaryModuleLoc = SourceLoc();
+
+ if (options.modulePath.getLength())
+ {
+ auto srcManager = options.linkage->getSourceManager();
+ auto modulePathInfo = PathInfo::makePath(options.modulePath);
+ auto srcFile = srcManager->createSourceFileWithString(modulePathInfo, String());
+ srcManager->addSourceFile(options.modulePath, srcFile);
+ auto srcView = srcManager->createSourceView(srcFile, &modulePathInfo, SourceLoc());
+ binaryModuleLoc = srcView->getRange().begin;
+ }
+
// Add modules
if (RiffContainer::ListChunk* moduleList = containerChunk->findContainedList(SerialBinary::kModuleListFourCc))
{
@@ -400,10 +435,8 @@ static List<ExtensionDecl*>& _getCandidateExtensionList(
NodeBase* astRootNode = nullptr;
RefPtr<IRModule> irModule;
SerialContainerData::Module module;
- bool hasHeader = false;
if (auto headerChunk = as<RiffContainer::DataChunk>(chunk, SerialBinary::kModuleHeaderFourCc))
{
- hasHeader = true;
MemoryStreamBase memStream(
FileAccess::Read,
headerChunk->getSingleData()->getPayload(),
@@ -507,10 +540,18 @@ static List<ExtensionDecl*>& _getCandidateExtensionList(
const SerialInfo::Entry* entry = entries[i];
if (entry->typeKind == SerialTypeKind::ImportSymbol)
{
+ // Import symbols are always serialized with a mangled name in the form of
+ // <module_name>!<symbol_mangled_name>.
+ // As symbol_mangled_name may not contain the name of its parent module
+ // in the case of an `extern` or `export` symbol.
+ //
UnownedStringSlice mangledName = reader.getStringSlice(SerialIndex(i));
-
- String moduleName;
- SLANG_RETURN_ON_FAIL(MangledNameParser::parseModuleName(mangledName, moduleName));
+ List<UnownedStringSlice> slicesOut;
+ StringUtil::split(mangledName, '!', slicesOut);
+ if (slicesOut.getCount() != 2)
+ return SLANG_FAIL;
+ auto moduleName = slicesOut[0];
+ mangledName = slicesOut[1];
// If we already have looked up this module and it has the same name just use what we have
Module* readModule = nullptr;
@@ -525,8 +566,7 @@ static List<ExtensionDecl*>& _getCandidateExtensionList(
NamePool* namePool = linkage->getNamePool();
Name* moduleNameName = namePool->getName(moduleName);
-
- readModule = linkage->findOrImportModule(moduleNameName, SourceLoc::fromRaw(0), options.sink, additionalLoadedModules);
+ readModule = linkage->findOrImportModule(moduleNameName, binaryModuleLoc, options.sink, additionalLoadedModules);
if (!readModule)
{
return SLANG_FAIL;
diff --git a/source/slang/slang-serialize-container.h b/source/slang/slang-serialize-container.h
index 9b9fbe6a1..4b35e931f 100644
--- a/source/slang/slang-serialize-container.h
+++ b/source/slang/slang-serialize-container.h
@@ -30,6 +30,15 @@ struct SerialContainerBinary
};
};
+struct SerialContainerDataModule
+{
+ RefPtr<IRModule> irModule; ///< The IR for the module
+ RefPtr<ASTBuilder> astBuilder; ///< The astBuilder that owns the astRootNode
+ NodeBase* astRootNode = nullptr; ///< The module decl
+ List<String> dependentFiles;
+ SHA1::Digest digest;
+};
+
/* Struct that holds all the data that can be held in a 'container' */
struct SerialContainerData
{
@@ -48,14 +57,7 @@ struct SerialContainerData
RefPtr<IRModule> irModule;
};
- struct Module
- {
- RefPtr<IRModule> irModule; ///< The IR for the module
- RefPtr<ASTBuilder> astBuilder; ///< The astBuilder that owns the astRootNode
- NodeBase* astRootNode = nullptr; ///< The module decl
- List<String> dependentFiles;
- SHA1::Digest digest;
- };
+ typedef SerialContainerDataModule Module;
struct EntryPoint
{
@@ -95,6 +97,7 @@ struct SerialContainerUtil
Linkage* linkage = nullptr;
DiagnosticSink* sink = nullptr;
bool readHeaderOnly = false;
+ String modulePath;
};
/// Add module to outData
diff --git a/source/slang/slang-serialize-factory.cpp b/source/slang/slang-serialize-factory.cpp
index 5eae5e740..e8cb82dc1 100644
--- a/source/slang/slang-serialize-factory.cpp
+++ b/source/slang/slang-serialize-factory.cpp
@@ -78,8 +78,14 @@ SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBas
{
ASTBuilder* astBuilder = m_moduleDecl->module->getASTBuilder();
- // It's a reference to a declaration in another module, so first get the symbol name.
- String mangledName = getMangledName(astBuilder, decl);
+ // It's a reference to a declaration in another module, so first get the symbol name.
+ // Note that we will always name an import symbol in the form of
+ // <module_name>!<symbol_mangled_name> for serialization.
+ // This is because <symbol_mangled_name> does not necessarily include the name of its
+ // parent module when it is qualified as `extern` or `export`.
+ //
+ String mangledName = getText(moduleDecl->getName()) +"!"+ getMangledName(astBuilder, decl);
+
// Add as an import symbol
return writer->addImportSymbol(mangledName);
}
@@ -89,34 +95,6 @@ SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBas
return writer->writeObject(ptr);
}
}
-
- // TODO(JS): If I enable this section then the stdlib doesn't work correctly, it appears to be because of
- // `addCatchAllIntrinsicDecorationIfNeeded`. If this is enabled when AST is serialized, the 'body' (ie Stmt)
- // will not be serialized. When serialized back in, it will appear to be a function without a body.
- // In that case `addCatchAllIntrinsicDecorationIfNeeded` will add an intrinsic which in some cases is incorrect.
- // This happens during lowering.
- //
- // So it seems the fix is for some other mechanism. Another solution is perhaps to run something like `addCatchAllIntrinsicDecorationIfNeeded`
- // on the stdlib after compilation, and before serialization. Then removing it from lowering.
-
-#if 0
- // TODO(JS): What we really want to do here is to ignore bodies functions.
- // It's not 100% clear if this is even right though - for example does type inference
- // imply the body is needed to say infer a return type?
- // Also not clear if statements in other scenarios (if there are others) might need to be kept.
- //
- // For now we just ignore all stmts
-
- // TODO(yong): We should by default serialize everything. The logic to skip bodies need to be
- // behind a option flag.
- if (Stmt* stmt = as<Stmt>(ptr))
- {
- //
- writer->setPointerIndex(stmt, SerialIndex(0));
- return SerialIndex(0);
- }
-#endif
-
// For now for everything else just write it
return writer->writeObject(ptr);
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index c0f89b0dc..bc91622f0 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -1559,7 +1559,7 @@ TargetRequest::TargetRequest(Linkage* linkage, CodeGenTarget format)
}
TargetRequest::TargetRequest(const TargetRequest& other)
- : linkage(other.linkage), optionSet(other.optionSet)
+ : RefObject(), linkage(other.linkage), optionSet(other.optionSet)
{
}
@@ -1721,6 +1721,12 @@ TranslationUnitRequest::TranslationUnitRequest(
module = new Module(compileRequest->getLinkage());
}
+TranslationUnitRequest::TranslationUnitRequest(
+ FrontEndCompileRequest* compileRequest, Module* m)
+ : compileRequest(compileRequest), module(m), isChecked(true)
+{
+ moduleName = getNamePool()->getName(m->getName());
+}
Session* TranslationUnitRequest::getSession()
{
@@ -2388,6 +2394,9 @@ static void _outputIncludes(const List<SourceFile*>& sourceFiles, SourceManager*
void FrontEndCompileRequest::parseTranslationUnit(
TranslationUnitRequest* translationUnit)
{
+ if (translationUnit->isChecked)
+ return;
+
auto linkage = getLinkage();
SLANG_AST_BUILDER_RAII(linkage->getASTBuilder());
@@ -2549,6 +2558,9 @@ void FrontEndCompileRequest::checkAllTranslationUnits()
// apply the semantic checking logic.
for( auto& translationUnit : translationUnits )
{
+ if (translationUnit->isChecked)
+ continue;
+
checkTranslationUnit(translationUnit.Ptr(), loadedModules);
// Add the checked module to list of loadedModules so that they can be
@@ -2577,6 +2589,10 @@ void FrontEndCompileRequest::generateIR()
// in isolation.
for( auto& translationUnit : translationUnits )
{
+ // Skip if the module is precompiled.
+ if (translationUnit->getModule()->getIRModule())
+ continue;
+
// We want to only run generateIRForTranslationUnit once here. This is for two side effects:
// * it can dump ir
// * it can generate diagnostics
@@ -2943,18 +2959,6 @@ SlangResult EndToEndCompileRequest::executeActions()
int FrontEndCompileRequest::addTranslationUnit(SourceLanguage language, Name* moduleName)
{
- if (!moduleName)
- {
- // We want to ensure that symbols defined in different translation
- // units get unique mangled names, so that we can, e.g., tell apart
- // a `main()` function in `vertex.hlsl` and a `main()` in `fragment.hlsl`,
- // even when they are being compiled together.
- //
- String generatedName = "tu";
- generatedName.append(translationUnits.getCount());
- moduleName = getNamePool()->getName(generatedName);
- }
-
RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(this);
translationUnit->compileRequest = this;
translationUnit->sourceLanguage = SourceLanguage(language);
@@ -2978,6 +2982,14 @@ void FrontEndCompileRequest::addTranslationUnitSourceArtifact(
// Add the source file
translationUnit->addSourceArtifact(sourceArtifact);
+
+ if (!translationUnit->moduleName)
+ {
+ translationUnit->setModuleName(
+ getNamePool()->getName(Path::getFileNameWithoutExt(sourceArtifact->getName())));
+ }
+ if (translationUnit->module->getFilePath() == nullptr)
+ translationUnit->module->setPathInfo(PathInfo::makePath(sourceArtifact->getName()));
}
void FrontEndCompileRequest::addTranslationUnitSourceBlob(
@@ -2991,7 +3003,7 @@ void FrontEndCompileRequest::addTranslationUnitSourceBlob(
auto artifact = ArtifactUtil::createArtifact(sourceDesc, path.getBuffer());
artifact->addRepresentationUnknown(sourceBlob);
- translationUnit->addSourceArtifact(artifact);
+ addTranslationUnitSourceArtifact(translationUnitIndex, artifact);
}
void FrontEndCompileRequest::addTranslationUnitSourceFile(
@@ -3011,7 +3023,7 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile(
auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(asExternal(translationUnit->sourceLanguage));
- auto sourceArtifact = ArtifactUtil::createArtifact(sourceDesc);
+ auto sourceArtifact = ArtifactUtil::createArtifact(sourceDesc, path.getBuffer());
auto extRep = new ExtFileArtifactRepresentation(path.getUnownedSlice(), fileSystemExt);
sourceArtifact->addRepresentation(extRep);
@@ -3044,7 +3056,7 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile(
return;
}
- translationUnit->addSourceArtifact(sourceArtifact);
+ addTranslationUnitSourceArtifact(translationUnitIndex, sourceArtifact);
}
int FrontEndCompileRequest::addEntryPoint(
@@ -3146,6 +3158,27 @@ void Linkage::loadParsedModule(
loadedModulesList.add(loadedModule);
}
+RefPtr<Module> Linkage::loadDeserializedModule(Name* name,
+ const PathInfo& filePathInfo,
+ SerialContainerData::Module& moduleEntry,
+ DiagnosticSink* sink)
+{
+ SLANG_AST_BUILDER_RAII(m_astBuilder);
+ RefPtr<Module> resultModule;
+ if (mapNameToLoadedModules.tryGetValue(name, resultModule))
+ return resultModule;
+ if (mapPathToLoadedModule.tryGetValue(filePathInfo.getMostUniqueIdentity(), resultModule))
+ return resultModule;
+
+ resultModule = new Module(this, m_astBuilder);
+ prepareDeserializedModule(moduleEntry, filePathInfo, resultModule, sink);
+
+ loadedModulesList.add(resultModule);
+ mapPathToLoadedModule.add(filePathInfo.getMostUniqueIdentity(), resultModule);
+ mapNameToLoadedModules.add(name, resultModule);
+ return resultModule;
+}
+
RefPtr<Module> Linkage::loadModuleFromIRBlobImpl(
Name* name,
const PathInfo& filePathInfo,
@@ -3154,6 +3187,8 @@ RefPtr<Module> Linkage::loadModuleFromIRBlobImpl(
DiagnosticSink* sink,
const LoadedModuleDictionary* additionalLoadedModules)
{
+ SLANG_AST_BUILDER_RAII(m_astBuilder);
+
RefPtr<Module> resultModule = new Module(this, getASTBuilder());
resultModule->setName(name);
ModuleBeingImportedRAII moduleBeingImported(
@@ -3195,19 +3230,8 @@ RefPtr<Module> Linkage::loadModuleFromIRBlobImpl(
return nullptr;
}
auto moduleEntry = containerData.modules.getFirst();
- resultModule->setIRModule(moduleEntry.irModule);
- resultModule->setModuleDecl(as<ModuleDecl>(moduleEntry.astRootNode));
- resultModule->clearFileDependency();
- for (auto file : moduleEntry.dependentFiles)
- {
- auto sourceFile = loadSourceFile(filePathInfo.foundPath, file);
- if (sourceFile)
- {
- resultModule->addFileDependency(sourceFile);
- }
- }
- prepareDeserializedModule(resultModule, sink);
+ prepareDeserializedModule(moduleEntry, filePathInfo, resultModule, sink);
loadedModulesList.add(resultModule);
resultModule->setPathInfo(filePathInfo);
@@ -5062,8 +5086,21 @@ void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
getSourceManager()->setFileSystemExt(m_fileSystemExt);
}
-void Linkage::prepareDeserializedModule(Module* module, DiagnosticSink* sink)
+void Linkage::prepareDeserializedModule(SerialContainerData::Module& moduleEntry, const PathInfo& filePathInfo, Module* module, DiagnosticSink* sink)
{
+ module->setIRModule(moduleEntry.irModule);
+ module->setModuleDecl(as<ModuleDecl>(moduleEntry.astRootNode));
+ module->clearFileDependency();
+ for (auto file : moduleEntry.dependentFiles)
+ {
+ auto sourceFile = loadSourceFile(filePathInfo.foundPath, file);
+ if (sourceFile)
+ {
+ module->addFileDependency(sourceFile);
+ }
+ }
+ module->setPathInfo(filePathInfo);
+
module->_collectShaderParams();
module->_discoverEntryPoints(sink);
@@ -5472,19 +5509,29 @@ void EndToEndCompileRequest::setDefaultModuleName(const char* defaultModuleName)
frontEndReq->m_defaultModuleName = namePool->getName(defaultModuleName);
}
-SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifact, ModuleLibrary* moduleLibrary)
+SlangResult _addLibraryReference(EndToEndCompileRequest* req, ModuleLibrary* moduleLibrary, bool includeEntryPoint)
{
FrontEndCompileRequest* frontEndRequest = req->getFrontEndReq();
- frontEndRequest->m_extraEntryPoints.addRange(moduleLibrary->m_entryPoints.getBuffer(), moduleLibrary->m_entryPoints.getCount());
- // Add to the m_libModules
- auto linkage = req->getLinkage();
- linkage->m_libModules.add(ComPtr<IArtifact>(artifact));
+ if (includeEntryPoint)
+ {
+ frontEndRequest->m_extraEntryPoints.addRange(
+ moduleLibrary->m_entryPoints.getBuffer(), moduleLibrary->m_entryPoints.getCount());
+ }
+ for (auto m : moduleLibrary->m_modules)
+ {
+ RefPtr<TranslationUnitRequest> tu = new TranslationUnitRequest(frontEndRequest, m);
+ frontEndRequest->translationUnits.add(tu);
+ // For modules loaded for EndToEndCompileRequest,
+ // we don't need the automatically discovered entrypoints.
+ if (!includeEntryPoint)
+ m->getEntryPoints().clear();
+ }
return SLANG_OK;
}
-SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifact)
+SlangResult _addLibraryReference(EndToEndCompileRequest* req, String path, IArtifact* artifact, bool includeEntryPoint)
{
auto desc = artifact->getDesc();
@@ -5507,7 +5554,7 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
}
ComPtr<IModuleLibrary> libraryIntf;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, container, req, libraryIntf));
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, container, path, req, libraryIntf));
auto library = as<ModuleLibrary>(libraryIntf);
@@ -5536,9 +5583,9 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
// for leaking.
//
// That isn't a risk from -r though because, it doesn't create a translation unit(s).
- for (auto irModule : library->m_modules)
+ for (auto module : library->m_modules)
{
- irModule->setObfuscatedSourceMap(sourceMap);
+ module->getIRModule()->setObfuscatedSourceMap(sourceMap);
}
// Look up the source file
@@ -5554,7 +5601,7 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
}
}
- SLANG_RETURN_ON_FAIL(_addLibraryReference(req, container, library));
+ SLANG_RETURN_ON_FAIL(_addLibraryReference(req, library, includeEntryPoint));
return SLANG_OK;
}
@@ -5562,7 +5609,7 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
{
ComPtr<IModuleLibrary> libraryIntf;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, artifact, req, libraryIntf));
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, artifact, path, req, libraryIntf));
auto library = as<ModuleLibrary>(libraryIntf);
if (!library)
@@ -5570,7 +5617,7 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
return SLANG_FAIL;
}
- SLANG_RETURN_ON_FAIL(_addLibraryReference(req, artifact, library));
+ SLANG_RETURN_ON_FAIL(_addLibraryReference(req, library, includeEntryPoint));
return SLANG_OK;
}
@@ -5584,18 +5631,18 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
return SLANG_OK;
}
-SlangResult EndToEndCompileRequest::addLibraryReference(const void* libData, size_t libDataSize)
+SlangResult EndToEndCompileRequest::addLibraryReference(const char* basePath, const void* libData, size_t libDataSize)
{
// We need to deserialize and add the modules
ComPtr<IModuleLibrary> library;
- SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)libData, libDataSize, this, library));
+ SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)libData, libDataSize, basePath, this, library));
// Create an artifact without any name (as one is not provided)
auto artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR));
artifact->addRepresentation(library);
- return _addLibraryReference(this, artifact);
+ return _addLibraryReference(this, basePath, artifact, true);
}
void EndToEndCompileRequest::addTranslationUnitPreprocessorDefine(int translationUnitIndex, const char* key, const char* value)
@@ -5631,7 +5678,7 @@ void EndToEndCompileRequest::addTranslationUnitSourceStringSpan(int translationU
const auto slice = UnownedStringSlice(sourceBegin, sourceEnd);
auto blob = RawBlob::create(slice.begin(), slice.getLength());
-
+
frontEndReq->addTranslationUnitSourceBlob(translationUnitIndex, path, blob);
}
diff --git a/tests/serialization/extern/extern-test.slang b/tests/serialization/extern/extern-test.slang
index 1efb221dc..c46724603 100644
--- a/tests/serialization/extern/extern-test.slang
+++ b/tests/serialization/extern/extern-test.slang
@@ -1,18 +1,18 @@
// extern-test.slang
-//TEST:COMPILE: -module-name module -no-codegen tests/serialization/extern/module-a.slang -o tests/serialization/extern/module-a.slang-lib
-//TEST:COMPILE: -module-name module -no-codegen tests/serialization/extern/module-b.slang -o tests/serialization/extern/module-b.slang-lib
-//TEST:COMPARE_COMPUTE_EX: -xslang -module-name -xslang module -slang -compute -xslang -r -xslang tests/serialization/extern/module-a.slang-lib -xslang -r -xslang tests/serialization/extern/module-b.slang-lib -shaderobj
+//TEST:COMPILE: -no-codegen tests/serialization/extern/module-a.slang -o tests/serialization/extern/module-a.slang-lib
+//TEST:COMPILE: -no-codegen tests/serialization/extern/module-b.slang -o tests/serialization/extern/module-b.slang-lib
+//TEST:COMPARE_COMPUTE_EX: -slang -compute -xslang -r -xslang tests/serialization/extern/module-a.slang-lib -xslang -r -xslang tests/serialization/extern/module-b.slang-lib -shaderobj
//TEST_INPUT:ubuffer(data=[0 0 0 0 ], stride=4):out,name outputBuffer
RWStructuredBuffer<int> outputBuffer;
// Declare the type exists
-[__extern] struct Thing {};
+extern struct Thing {};
// A mechanism to make a Thing without knowing the specific fields.
-[__extern] Thing makeThing(int a, int b);
+extern Thing makeThing(int a, int b);
-[__extern] int doSomething(Thing a, Thing b);
+extern int doSomething(Thing a, Thing b);
[numthreads(4, 1, 1)]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
diff --git a/tests/serialization/extern/module-a.slang b/tests/serialization/extern/module-a.slang
index 81816a213..59ccf7bcd 100644
--- a/tests/serialization/extern/module-a.slang
+++ b/tests/serialization/extern/module-a.slang
@@ -2,13 +2,13 @@
// module-a.slang
-struct Thing
+export struct Thing
{
int a;
int b;
};
-Thing makeThing(int a, int b)
+export Thing makeThing(int a, int b)
{
Thing thing;
thing.a = a;
@@ -16,7 +16,7 @@ Thing makeThing(int a, int b)
return thing;
}
-int foo(Thing thing)
+export int foo(Thing thing)
{
return thing.a + thing.b * 2;
}
diff --git a/tests/serialization/extern/module-b.slang b/tests/serialization/extern/module-b.slang
index 20371f156..2bc646db8 100644
--- a/tests/serialization/extern/module-b.slang
+++ b/tests/serialization/extern/module-b.slang
@@ -3,10 +3,10 @@
// module-b.slang
// This looks like a definition (and it is) but with [__extern] it's definition will be replaced at link time with a defintion
-[__extern] struct Thing {};
-[__extern] int foo(Thing thing);
+extern struct Thing {};
+extern int foo(Thing thing);
-int doSomething(Thing a, Thing b)
+export int doSomething(Thing a, Thing b)
{
return foo(a) + foo(b);
}
diff --git a/tests/serialization/obfuscated-loc-module.slang b/tests/serialization/obfuscated-loc-module.slang
index 63c4f61ee..4837e6486 100644
--- a/tests/serialization/obfuscated-loc-module.slang
+++ b/tests/serialization/obfuscated-loc-module.slang
@@ -3,13 +3,13 @@
// obfuscated-loc-module.slang
-int billy(int v)
+export int billy(int v)
{
return v + 1;
}
// This function is designed to fail during IR passes/emit.
-int silly(int a)
+export int silly(int a)
{
int t = 0;
[ForceUnroll(10)]
diff --git a/tests/serialization/obfuscated-module-check-loc.slang b/tests/serialization/obfuscated-module-check-loc.slang
index 49251760c..87236b576 100644
--- a/tests/serialization/obfuscated-module-check-loc.slang
+++ b/tests/serialization/obfuscated-module-check-loc.slang
@@ -11,8 +11,8 @@ RWStructuredBuffer<float> outputBuffer;
// We *don't* import because if we do we'll get a fresh compilation from source... we want to make sure it's using the -r module
//import obfuscated_loc_module;
-int silly(int v);
-int billy(int v);
+extern int silly(int v);
+extern int billy(int v);
[numthreads(1, 1, 1)]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
diff --git a/tests/serialization/obfuscated-serialized-module-shared.slang b/tests/serialization/obfuscated-serialized-module-shared.slang
new file mode 100644
index 000000000..76b7e3f5c
--- /dev/null
+++ b/tests/serialization/obfuscated-serialized-module-shared.slang
@@ -0,0 +1,5 @@
+struct Thing
+{
+ int a;
+ int b;
+};
diff --git a/tests/serialization/obfuscated-serialized-module-test.slang b/tests/serialization/obfuscated-serialized-module-test.slang
index 927ee06bc..8afe1fb09 100644
--- a/tests/serialization/obfuscated-serialized-module-test.slang
+++ b/tests/serialization/obfuscated-serialized-module-test.slang
@@ -3,20 +3,12 @@
// A test to try out the basics of module
// serialization, obfuscation and source maps.
-//TEST:COMPILE: tests/serialization/serialized-module.slang -o tests/serialization/obfuscated-serialized-module.slang-module -g -obfuscate
+//TEST:COMPILE: tests/serialization/obfuscated-serialized-module.slang -o tests/serialization/obfuscated-serialized-module.slang-module -g -obfuscate
//TEST:COMPARE_COMPUTE_EX:-slang -compute -Xslang... -r tests/serialization/obfuscated-serialized-module.slang-module -obfuscate -X. -shaderobj
-//import obfuscated_serialized_module;
+import obfuscated_serialized_module_shared;
-// This is fragile - needs match the definition in obfuscated_serialized_module
-struct Thing
-{
- int a;
- int b;
-};
-
-// TODO: need to get the name mangling to line up!
-int foo(Thing thing);
+extern int foo(Thing thing);
//TEST_INPUT:ubuffer(data=[0 0 0 0 ], stride=4):out,name outputBuffer
RWStructuredBuffer<int> outputBuffer;
diff --git a/tests/serialization/obfuscated-serialized-module.slang b/tests/serialization/obfuscated-serialized-module.slang
index 17ddfa662..3aa3b8978 100644
--- a/tests/serialization/obfuscated-serialized-module.slang
+++ b/tests/serialization/obfuscated-serialized-module.slang
@@ -1,14 +1,9 @@
//TEST_IGNORE_FILE:
// obfuscated-serialized-module.slang
+import obfuscated_serialized_module_shared;
-struct Thing
-{
- int a;
- int b;
-};
-
-int foo(Thing thing)
+export int foo(Thing thing)
{
return (thing.a + thing.b) - thing.b;
}
diff --git a/tests/serialization/serialized-module-shared.slang b/tests/serialization/serialized-module-shared.slang
new file mode 100644
index 000000000..143cff6fa
--- /dev/null
+++ b/tests/serialization/serialized-module-shared.slang
@@ -0,0 +1,5 @@
+struct Thing
+{
+ int a;
+ int b;
+};
diff --git a/tests/serialization/serialized-module-test.slang b/tests/serialization/serialized-module-test.slang
index d27fe0458..3e7588a2a 100644
--- a/tests/serialization/serialized-module-test.slang
+++ b/tests/serialization/serialized-module-test.slang
@@ -9,14 +9,9 @@
//import serialized_module;
// This is fragile - needs match the definition in serialized_module
-struct Thing
-{
- int a;
- int b;
-};
+import serialized_module_shared;
-// TODO: need to get the name mangling to line up!
-int foo(Thing thing);
+extern int foo(Thing thing);
//TEST_INPUT:ubuffer(data=[0 0 0 0 ], stride=4):out,name outputBuffer
RWStructuredBuffer<int> outputBuffer;
diff --git a/tests/serialization/serialized-module.slang b/tests/serialization/serialized-module.slang
index e94edf8d4..861ddb300 100644
--- a/tests/serialization/serialized-module.slang
+++ b/tests/serialization/serialized-module.slang
@@ -2,13 +2,9 @@
// serialized-module.slang
-struct Thing
-{
- int a;
- int b;
-};
+import serialized_module_shared;
-int foo(Thing thing)
+export int foo(Thing thing)
{
return (thing.a + thing.b) - thing.b;
}
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index f585abe5b..dd0394fdf 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -85,19 +85,22 @@ void ShaderCompilerUtil::Output::reset()
out.m_requestForKernels = slangRequest;
out.session = globalSession;
+ bool hasRepro = false;
+
// Parse all the extra args
{
List<const char*> args;
for (const auto& arg : options.downstreamArgs.getArgsByName("slang"))
{
args.add(arg.value.getBuffer());
+ if (arg.value == "-load-repro")
+ hasRepro = true;
}
// If there are additional args parse them
if (args.getCount())
{
const auto res = slangRequest->processCommandLineArguments(args.getBuffer(), int(args.getCount()));
-
// If there is a parse failure and diagnostic, output it
if (SLANG_FAILED(res))
{
@@ -109,100 +112,105 @@ void ShaderCompilerUtil::Output::reset()
}
}
}
- spSetCodeGenTarget(slangRequest, input.target);
- spSetTargetProfile(slangRequest, 0, spFindProfile(out.session, input.profile.getBuffer()));
- if (options.generateSPIRVDirectly)
- spSetTargetFlags(slangRequest, 0, SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY);
-
- slangRequest->setAllowGLSLInput(options.allowGLSL);
- // Define a macro so that shader code in a test can detect what language we
- // are nominally working with.
- char const* langDefine = nullptr;
- switch (input.sourceLanguage)
+ // Only proceed if the command line arguments are not loading a repro.
+ if (!hasRepro)
{
- case SLANG_SOURCE_LANGUAGE_GLSL:
- spAddPreprocessorDefine(slangRequest, "__GLSL__", "1");
- break;
+ spSetCodeGenTarget(slangRequest, input.target);
+ spSetTargetProfile(slangRequest, 0, spFindProfile(out.session, input.profile.getBuffer()));
+ if (options.generateSPIRVDirectly)
+ spSetTargetFlags(slangRequest, 0, SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY);
- case SLANG_SOURCE_LANGUAGE_SLANG:
- spAddPreprocessorDefine(slangRequest, "__SLANG__", "1");
- // fall through
- case SLANG_SOURCE_LANGUAGE_HLSL:
- spAddPreprocessorDefine(slangRequest, "__HLSL__", "1");
- break;
- case SLANG_SOURCE_LANGUAGE_C:
- spAddPreprocessorDefine(slangRequest, "__C__", "1");
- break;
- case SLANG_SOURCE_LANGUAGE_CPP:
- spAddPreprocessorDefine(slangRequest, "__CPP__", "1");
- break;
- case SLANG_SOURCE_LANGUAGE_CUDA:
- spAddPreprocessorDefine(slangRequest, "__CUDA__", "1");
- break;
+ slangRequest->setAllowGLSLInput(options.allowGLSL);
- default:
- assert(!"unexpected");
- break;
- }
+ // Define a macro so that shader code in a test can detect what language we
+ // are nominally working with.
+ char const* langDefine = nullptr;
+ switch (input.sourceLanguage)
+ {
+ case SLANG_SOURCE_LANGUAGE_GLSL:
+ spAddPreprocessorDefine(slangRequest, "__GLSL__", "1");
+ break;
- if (input.passThrough != SLANG_PASS_THROUGH_NONE)
- {
- spSetPassThrough(slangRequest, input.passThrough);
- }
- else
- {
- spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CODEGEN);
- }
+ case SLANG_SOURCE_LANGUAGE_SLANG:
+ spAddPreprocessorDefine(slangRequest, "__SLANG__", "1");
+ // fall through
+ case SLANG_SOURCE_LANGUAGE_HLSL:
+ spAddPreprocessorDefine(slangRequest, "__HLSL__", "1");
+ break;
+ case SLANG_SOURCE_LANGUAGE_C:
+ spAddPreprocessorDefine(slangRequest, "__C__", "1");
+ break;
+ case SLANG_SOURCE_LANGUAGE_CPP:
+ spAddPreprocessorDefine(slangRequest, "__CPP__", "1");
+ break;
+ case SLANG_SOURCE_LANGUAGE_CUDA:
+ spAddPreprocessorDefine(slangRequest, "__CUDA__", "1");
+ break;
+
+ default:
+ assert(!"unexpected");
+ break;
+ }
-
- const auto sourceLanguage = input.sourceLanguage;
+ if (input.passThrough != SLANG_PASS_THROUGH_NONE)
+ {
+ spSetPassThrough(slangRequest, input.passThrough);
+ }
+ else
+ {
+ spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CODEGEN);
+ }
- int translationUnitIndex = 0;
- {
- translationUnitIndex = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, translationUnitIndex, request.source.path, request.source.dataBegin);
- }
- const int globalSpecializationArgCount = int(request.globalSpecializationArgs.getCount());
- for(int ii = 0; ii < globalSpecializationArgCount; ++ii )
- {
- spSetTypeNameForGlobalExistentialTypeParam(slangRequest, ii, request.globalSpecializationArgs[ii].getBuffer());
- }
+ const auto sourceLanguage = input.sourceLanguage;
- const int entryPointSpecializationArgCount = int(request.entryPointSpecializationArgs.getCount());
- auto setEntryPointSpecializationArgs = [&](int entryPoint)
- {
- for( int ii = 0; ii < entryPointSpecializationArgCount; ++ii )
+ int translationUnitIndex = 0;
{
- spSetTypeNameForEntryPointExistentialTypeParam(slangRequest, entryPoint, ii, request.entryPointSpecializationArgs[ii].getBuffer());
+ translationUnitIndex = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
+ spAddTranslationUnitSourceString(slangRequest, translationUnitIndex, request.source.path, request.source.dataBegin);
}
- };
- Index explicitEntryPointCount = request.entryPoints.getCount();
- for(Index ee = 0; ee < explicitEntryPointCount; ++ee)
- {
- if(options.dontAddDefaultEntryPoints)
+ const int globalSpecializationArgCount = int(request.globalSpecializationArgs.getCount());
+ for (int ii = 0; ii < globalSpecializationArgCount; ++ii)
{
- // If default entry points are not to be added, then
- // the `request.entryPoints` array should have been
- // left empty.
- //
- SLANG_ASSERT(false);
+ spSetTypeNameForGlobalExistentialTypeParam(slangRequest, ii, request.globalSpecializationArgs[ii].getBuffer());
}
- auto& entryPointInfo = request.entryPoints[ee];
- int entryPointIndex = spAddEntryPoint(
- slangRequest,
- translationUnitIndex,
- entryPointInfo.name,
- entryPointInfo.slangStage);
- SLANG_ASSERT(entryPointIndex == ee);
+ const int entryPointSpecializationArgCount = int(request.entryPointSpecializationArgs.getCount());
+ auto setEntryPointSpecializationArgs = [&](int entryPoint)
+ {
+ for (int ii = 0; ii < entryPointSpecializationArgCount; ++ii)
+ {
+ spSetTypeNameForEntryPointExistentialTypeParam(slangRequest, entryPoint, ii, request.entryPointSpecializationArgs[ii].getBuffer());
+ }
+ };
- setEntryPointSpecializationArgs(entryPointIndex);
- }
+ Index explicitEntryPointCount = request.entryPoints.getCount();
+ for (Index ee = 0; ee < explicitEntryPointCount; ++ee)
+ {
+ if (options.dontAddDefaultEntryPoints)
+ {
+ // If default entry points are not to be added, then
+ // the `request.entryPoints` array should have been
+ // left empty.
+ //
+ SLANG_ASSERT(false);
+ }
+
+ auto& entryPointInfo = request.entryPoints[ee];
+ int entryPointIndex = spAddEntryPoint(
+ slangRequest,
+ translationUnitIndex,
+ entryPointInfo.name,
+ entryPointInfo.slangStage);
+ SLANG_ASSERT(entryPointIndex == ee);
- spSetLineDirectiveMode(slangRequest, SLANG_LINE_DIRECTIVE_MODE_NONE);
+ setEntryPointSpecializationArgs(entryPointIndex);
+ }
+
+ spSetLineDirectiveMode(slangRequest, SLANG_LINE_DIRECTIVE_MODE_NONE);
+ }
const SlangResult res = spCompile(slangRequest);
diff --git a/tools/slang-test/slangc-tool.cpp b/tools/slang-test/slangc-tool.cpp
index 55788d06b..13e6b192e 100644
--- a/tools/slang-test/slangc-tool.cpp
+++ b/tools/slang-test/slangc-tool.cpp
@@ -7,13 +7,6 @@
using namespace Slang;
-static void _diagnosticCallback(char const* message, void* /*userData*/)
-{
- auto stdError = StdWriters::getError();
- stdError.put(message);
- stdError.flush();
-}
-
SlangResult SlangCTool::innerMain(StdWriters* stdWriters, slang::IGlobalSession* sharedSession, int argc, const char*const* argv)
{
StdWriters::setSingleton(stdWriters);
@@ -42,7 +35,6 @@ SlangResult SlangCTool::innerMain(StdWriters* stdWriters, slang::IGlobalSession*
compileRequest->setWriter(channel, stdWriters->getWriter(channel));
}
- compileRequest->setDiagnosticCallback(&_diagnosticCallback, nullptr);
compileRequest->setCommandLineCompilerMode();
SLANG_RETURN_ON_FAIL(compileRequest->processCommandLineArguments(&argv[1], argc - 1));