diff options
| author | Yong He <yonghe@outlook.com> | 2024-02-23 16:39:46 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-23 16:39:46 -0800 |
| commit | 401d8cdb12ae69aeb216c80c9bb90240d8359649 (patch) | |
| tree | 4548c9de52bdeff424a0a3969ad407fccb3c0f09 | |
| parent | 58eb6f7da01af1767282ee12b0b4b25c57e52afb (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.
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) @@ -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)); |
