diff options
| -rw-r--r-- | slang.h | 1 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-container-util.cpp | 100 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-container-util.h | 8 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-desc-util.cpp | 10 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-util.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 257 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 22 | ||||
| -rw-r--r-- | source/slang/slang-emit-source-writer.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 84 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 22 | ||||
| -rw-r--r-- | tests/feature/source-map/emit-source-map.slang | 16 | ||||
| -rw-r--r-- | tests/serialization/obfuscated-check-loc.slang | 2 | ||||
| -rw-r--r-- | tests/serialization/obfuscated-module-check-loc.slang | 2 | ||||
| -rw-r--r-- | tests/serialization/obfuscated-serialized-module-test.slang | 4 |
15 files changed, 364 insertions, 174 deletions
@@ -721,6 +721,7 @@ extern "C" SLANG_LINE_DIRECTIVE_MODE_NONE, /**< Don't emit line directives at all. */ SLANG_LINE_DIRECTIVE_MODE_STANDARD, /**< Emit standard C-style `#line` directives. */ SLANG_LINE_DIRECTIVE_MODE_GLSL, /**< Emit GLSL-style directives with file *number* instead of name */ + SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP, /**< Use a source map to track line mappings (ie no #line will appear in emitting source) */ }; typedef int SlangSourceLanguageIntegral; diff --git a/source/compiler-core/slang-artifact-container-util.cpp b/source/compiler-core/slang-artifact-container-util.cpp index 6121df964..dfc385f9a 100644 --- a/source/compiler-core/slang-artifact-container-util.cpp +++ b/source/compiler-core/slang-artifact-container-util.cpp @@ -191,34 +191,24 @@ SlangResult ArtifactContainerWriter::getBaseName(IArtifact* artifact, String& ou SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const String& baseName) { - // TODO(JS): // We could now output information about the desc/artifact, say as some json. // For now we assume the extension is good enough for most purposes. + // If it's an "arbitrary" container, we don't need to write it + if (artifact->getDesc().kind != ArtifactKind::Container) { // We can't write it without a blob ComPtr<ISlangBlob> blob; - const auto res = artifact->loadBlob(ArtifactKeep::No, blob.writeRef()); + SLANG_RETURN_ON_FAIL(artifact->loadBlob(ArtifactKeep::No, blob.writeRef())); - if (SLANG_FAILED(res)) - { - // If it failed and it's significant the whole write fails - if (ArtifactUtil::isSignificant(artifact)) - { - return res; - } - } - - { - // Get the name of the artifact - StringBuilder artifactName; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName)); + // Get the name of the artifact + StringBuilder artifactName; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName)); - const auto combinedPath = Path::combine(m_entry.path, artifactName); - // Write out the blob - SLANG_RETURN_ON_FAIL(m_fileSystem->saveFileBlob(combinedPath.getBuffer(), blob)); - } + const auto combinedPath = Path::combine(m_entry.path, artifactName); + // Write out the blob + SLANG_RETURN_ON_FAIL(m_fileSystem->saveFileBlob(combinedPath.getBuffer(), blob)); } { @@ -837,4 +827,76 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr return SLANG_OK; } +/* static */SlangResult ArtifactContainerUtil::filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact) +{ + outArtifact.setNull(); + + // Copy the artifact + auto dstArtifact = ArtifactUtil::createArtifact(artifact->getDesc(), artifact->getName()); + + ComPtr<ISlangBlob> blob; + + if (artifact->getDesc().kind != ArtifactKind::Container) + { + // We can't write it without a blob + const auto res = artifact->loadBlob(ArtifactKeep::No, blob.writeRef()); + + if (SLANG_FAILED(res)) + { + // If it failed and it's significant the whole write fails + if (ArtifactUtil::isSignificant(artifact)) + { + return res; + } + } + else + { + // Add the blob to the destination + dstArtifact->addRepresentationUnknown(blob); + } + } + + // Copy the children after filtering + { + for (IArtifact* child : artifact->getChildren()) + { + ComPtr<IArtifact> dstChild; + SLANG_RETURN_ON_FAIL(filter(child, dstChild)); + + if (dstChild) + { + dstArtifact->addChild(dstChild); + } + } + } + + // Copy the associated after filtering + { + for (IArtifact* assoc : artifact->getAssociated()) + { + ComPtr<IArtifact> dstAssoc; + SLANG_RETURN_ON_FAIL(filter(assoc, dstAssoc)); + + if (dstAssoc) + { + dstArtifact->addAssociated(dstAssoc); + } + } + } + + // We only return the artifact if any of the following are true + // 1) It has a blob representation + // 2) It contains children or associated artifacts + + if (blob || + dstArtifact->getChildren().count || + dstArtifact->getAssociated().count) + { + outArtifact = dstArtifact; + } + + // If we return an artifact or not, this was successful + return SLANG_OK; +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-container-util.h b/source/compiler-core/slang-artifact-container-util.h index c6e836245..0ee99de26 100644 --- a/source/compiler-core/slang-artifact-container-util.h +++ b/source/compiler-core/slang-artifact-container-util.h @@ -36,6 +36,14 @@ struct ArtifactContainerUtil /// Read an artifact that represents a container as an artifact hierarchy static SlangResult readContainer(IArtifact* artifact, ComPtr<IArtifact>& outArtifact); + + /// Creates a copy of artifact where + /// * All artifacts are blobs + /// * Any generic containers that are empty are dropped + /// * Any sub artifact that can't be blobed and isn't significant is ignored + /// + /// A future improvement would be to take a function to also control what makes it to the output + static SlangResult filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact); }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 67501782a..e10ceee07 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -753,6 +753,16 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S default: break; } + if (ArtifactDescUtil::isGpuUsable(desc)) + { + auto ext = _getPayloadExtension(desc.payload); + if (ext.getLength()) + { + out << ext; + return SLANG_OK; + } + } + if (ArtifactDescUtil::isCpuLikeTarget(desc) && !isDerivedFrom(desc.payload, ArtifactPayload::Source)) { return appendCpuExtensionForKind(desc.kind, out); diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 00884c96f..7420f6843 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -83,6 +83,12 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) return false; } + /* We currently can't write out diagnostics, so for now we'll say they are insignificant */ + if (isDerivedFrom(desc.payload, ArtifactPayload::Diagnostics)) + { + return false; + } + return true; } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index b5fd27d55..825849b7f 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1116,11 +1116,8 @@ namespace Slang sourceLanguage = (SourceLanguage)TypeConvertUtil::getSourceLanguageFromTarget((SlangCompileTarget)sourceTarget); } - ComPtr<IArtifactPostEmitMetadata> metadata; if (sourceArtifact) { - metadata = findAssociatedRepresentation<IArtifactPostEmitMetadata>(sourceArtifact); - // Set the source artifacts options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1); } @@ -1468,7 +1465,14 @@ namespace Slang return SLANG_FAIL; } - ArtifactUtil::addAssociated(artifact, metadata); + // Copy over all of the information associated with the source into the output + if (sourceArtifact) + { + for (auto associatedArtifact : sourceArtifact->getAssociated()) + { + artifact->addAssociated(associatedArtifact); + } + } // Set the artifact outArtifact.swap(artifact); @@ -1613,24 +1617,18 @@ namespace Slang ArtifactOutputUtil::maybeConvertAndWrite(session, artifact, sink, toSlice("stdout"), getWriter(WriterChannel::StdOutput)); } - void EndToEndCompileRequest::writeWholeProgramResult( - TargetRequest* targetReq) + String EndToEndCompileRequest::_getWholeProgramPath(TargetRequest* targetReq) { - auto program = getSpecializedGlobalAndEntryPointsComponentType(); - auto targetProgram = program->getTargetProgram(targetReq); - - IArtifact* artifact = targetProgram->getExistingWholeProgramResult(); - - // Skip the case with no output - if (artifact == nullptr) - return; - - CodeGenContext::EntryPointIndices entryPointIndices; - for (Index i = 0; i < program->getEntryPointCount(); ++i) - entryPointIndices.add(i); - CodeGenContext::Shared sharedCodeGenContext(targetProgram, entryPointIndices, getSink(), this); - CodeGenContext codeGenContext(&sharedCodeGenContext); + RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo; + if (m_targetInfos.TryGetValue(targetReq, targetInfo)) + { + return targetInfo->wholeTargetOutputPath; + } + return String(); + } + String EndToEndCompileRequest::_getEntryPointPath(TargetRequest* targetReq, Index entryPointIndex) + { // It is possible that we are dynamically discovering entry // points (using `[shader(...)]` attributes), so that there // might be entry points added to the program that did not @@ -1639,53 +1637,35 @@ namespace Slang RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo; if (m_targetInfos.TryGetValue(targetReq, targetInfo)) { - String outputPath = targetInfo->wholeTargetOutputPath; - if (outputPath != "") + String outputPath; + if (targetInfo->entryPointOutputPaths.TryGetValue(entryPointIndex, outputPath)) { - ArtifactOutputUtil::writeToFile(artifact, codeGenContext.getSink(), outputPath); - return; + return outputPath; } } - writeArtifactToStandardOutput(artifact, codeGenContext.getSink()); + + return String(); } - void EndToEndCompileRequest::writeEntryPointResult( - TargetRequest* targetReq, - Int entryPointIndex) + SlangResult EndToEndCompileRequest::_maybeWriteArtifact(const String& path, IArtifact* artifact) { - auto program = getSpecializedGlobalAndEntryPointsComponentType(); - auto targetProgram = program->getTargetProgram(targetReq); - - IArtifact* artifact = targetProgram->getExistingEntryPointResult(entryPointIndex); - - // Skip the case with no output - if (artifact == nullptr) - return; - - CodeGenContext::EntryPointIndices entryPointIndices; - entryPointIndices.add(entryPointIndex); - - CodeGenContext::Shared sharedCodeGenContext(targetProgram, entryPointIndices, getSink(), this); - CodeGenContext codeGenContext(&sharedCodeGenContext); - - // It is possible that we are dynamically discovering entry - // points (using `[shader(...)]` attributes), so that there - // might be entry points added to the program that did not - // get paths specified via command-line options. - // - RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo; - auto entryPoint = program->getEntryPoint(entryPointIndex); - if(m_targetInfos.TryGetValue(targetReq, targetInfo)) + // We don't have to do anything if there is no artifact + if (artifact) { - String outputPath; - if(targetInfo->entryPointOutputPaths.TryGetValue(entryPointIndex, outputPath)) + if (path.getLength()) { - ArtifactOutputUtil::writeToFile(artifact, codeGenContext.getSink(), outputPath); - return; + SLANG_RETURN_ON_FAIL(ArtifactOutputUtil::writeToFile(artifact, getSink(), path)); + return SLANG_OK; + } + + // If we aren't writing to a container and we didn't write to a file, we can output to + if (m_containerFormat == ContainerFormat::None) + { + writeArtifactToStandardOutput(artifact, getSink()); } } - writeArtifactToStandardOutput(artifact, codeGenContext.getSink()); + return SLANG_OK; } IArtifact* TargetProgram::_createWholeProgramResult( @@ -1860,11 +1840,54 @@ namespace Slang return SLANG_OK; } - SlangResult EndToEndCompileRequest::_createContainer() + static IBoxValue<SourceMap>* _getObfuscatedSourceMap(TranslationUnitRequest* translationUnit) { - switch (m_containerFormat) + if (auto module = translationUnit->getModule()) + { + if (auto irModule = module->getIRModule()) + { + return irModule->getObfuscatedSourceMap(); + } + } + return nullptr; + } + + SlangResult EndToEndCompileRequest::maybeCreateContainer() + { + m_containerArtifact.setNull(); + + List<ComPtr<IArtifact>> artifacts; + + auto linkage = getLinkage(); + + auto program = getSpecializedGlobalAndEntryPointsComponentType(); + + for (auto targetReq : linkage->targets) { - case ContainerFormat::SlangModule: + auto targetProgram = program->getTargetProgram(targetReq); + + if (targetReq->isWholeProgramRequest()) + { + if (auto artifact = targetProgram->getExistingWholeProgramResult()) + { + artifacts.add(ComPtr<IArtifact>(artifact)); + } + } + else + { + Index entryPointCount = program->getEntryPointCount(); + for (Index ee = 0; ee < entryPointCount; ++ee) + { + if (auto artifact = targetProgram->getExistingEntryPointResult(ee)) + { + artifacts.add(ComPtr<IArtifact>(artifact)); + } + } + } + } + + // If IR emitting is enabled, add IR to the artifacts + if (m_emitIr) { OwnedMemoryStream stream(FileAccess::Write); SlangResult res = writeContainerToStream(&stream); @@ -1880,78 +1903,74 @@ namespace Slang auto containerBlob = ListBlob::moveCreate(blobData); - m_containerArtifact = Artifact::create(ArtifactDesc::make(Artifact::Kind::CompileBinary, ArtifactPayload::SlangIR, ArtifactStyle::Unknown)); - m_containerArtifact->addRepresentationUnknown(containerBlob); - - return res; - } - default: break; + auto irArtifact = Artifact::create(ArtifactDesc::make(Artifact::Kind::CompileBinary, ArtifactPayload::SlangIR, ArtifactStyle::Unknown)); + irArtifact->addRepresentationUnknown(containerBlob); + + // Add the IR artifact + artifacts.add(irArtifact); } - return SLANG_OK; - } - SlangResult EndToEndCompileRequest::_completeContainer() - { - SLANG_ASSERT(m_containerArtifact); - if (!m_containerArtifact) + // If there is only one artifact we can use that as the container + if (artifacts.getCount() == 1) { - return SLANG_FAIL; + m_containerArtifact = artifacts[0]; } + else + { + m_containerArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::CompileResults)); - auto frontEndReq = getFrontEndReq(); + for (IArtifact* childArtifact : artifacts) + { + m_containerArtifact->addChild(childArtifact); + } + } - for (auto translationUnit : frontEndReq->translationUnits) + // Get all of the source obfuscated source maps and add those + if (m_containerArtifact) { - // Hmmm do I have to therefore add a map for all translation units(!) - // I guess this is okay in so far as an association can always be looked up by name - - auto sourceMap = translationUnit->getModule()->getIRModule()->getObfuscatedSourceMap(); + auto frontEndReq = getFrontEndReq(); - // If we have a source map *and* we want to generate them for output add to the container - if (sourceMap && getLinkage()->m_generateSourceMap) + for (auto translationUnit : frontEndReq->translationUnits) { - auto artifactDesc = ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::Obfuscated); + // Hmmm do I have to therefore add a map for all translation units(!) + // I guess this is okay in so far as an association can always be looked up by name + if (auto sourceMap = _getObfuscatedSourceMap(translationUnit)) + { + auto artifactDesc = ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::Obfuscated); - // Create the source map artifact - auto sourceMapArtifact = Artifact::create(artifactDesc, sourceMap->get().m_file.getUnownedSlice()); + // Create the source map artifact + auto sourceMapArtifact = Artifact::create(artifactDesc, sourceMap->get().m_file.getUnownedSlice()); - // Add the repesentation - sourceMapArtifact->addRepresentation(sourceMap); + // Add the repesentation + sourceMapArtifact->addRepresentation(sourceMap); - // Associate with the container - m_containerArtifact->addAssociated(sourceMapArtifact); + // Associate with the container + m_containerArtifact->addAssociated(sourceMapArtifact); + } } } return SLANG_OK; } - SlangResult EndToEndCompileRequest::maybeCreateContainer() + SlangResult EndToEndCompileRequest::maybeWriteContainer(const String& fileName) { - m_containerArtifact.setNull(); - - if (m_containerFormat == ContainerFormat::None) + // If there is no container, or filename, don't write anything + if (fileName.getLength() == 0 || !m_containerArtifact) { return SLANG_OK; } - // Create the container - SLANG_RETURN_ON_FAIL(_createContainer()); + // Filter the containerArtifact into things that can be written + ComPtr<IArtifact> writeArtifact; + SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::filter(m_containerArtifact, writeArtifact)); - // Associate any other stuff with the container artifact - SLANG_RETURN_ON_FAIL(_completeContainer()); - - return SLANG_OK; - } - - SlangResult EndToEndCompileRequest::maybeWriteContainer(const String& fileName) - { - // If there is no container, or filename, don't write anything - if (fileName.getLength() == 0 || !m_containerArtifact) + // Only write if there is something to write + if (writeArtifact) { - return SLANG_OK; + SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::writeContainer(writeArtifact, fileName)); } - SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::writeContainer(m_containerArtifact, fileName)); + return SLANG_OK; } @@ -2109,26 +2128,38 @@ namespace Slang { auto linkage = getLinkage(); auto program = getSpecializedGlobalAndEntryPointsComponentType(); + for (auto targetReq : linkage->targets) { + auto targetProgram = program->getTargetProgram(targetReq); + if (targetReq->isWholeProgramRequest()) { - writeWholeProgramResult( - targetReq); + const auto path = _getWholeProgramPath(targetReq); + const auto artifact = targetProgram->getExistingWholeProgramResult(); + + _maybeWriteArtifact(path, artifact); } else { Index entryPointCount = program->getEntryPointCount(); for (Index ee = 0; ee < entryPointCount; ++ee) - { - writeEntryPointResult( - targetReq, - ee); + { + const auto path = _getEntryPointPath(targetReq, ee); + const auto artifact = targetProgram->getExistingEntryPointResult(ee); + + _maybeWriteArtifact(path, artifact); } } - } + } + } - maybeCreateContainer(); + // Maybe create the container + maybeCreateContainer(); + + // If it's a command line compile we may need to write the container to a file + if (m_isCommandLineCompile) + { maybeWriteContainer(m_containerOutputPath); _writeDependencyFile(this); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 0c366f485..d0827e2e6 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -104,6 +104,7 @@ namespace Slang None = SLANG_LINE_DIRECTIVE_MODE_NONE, Standard = SLANG_LINE_DIRECTIVE_MODE_STANDARD, GLSL = SLANG_LINE_DIRECTIVE_MODE_GLSL, + SourceMap = SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP, }; enum class ResultFormat @@ -1771,8 +1772,7 @@ namespace Slang SourceManager* m_sourceManager = nullptr; bool m_obfuscateCode = false; - bool m_generateSourceMap = false; - + /// Holds any args that are destined for downstream compilers/tools etc DownstreamArgs m_downstreamArgs; @@ -2626,6 +2626,9 @@ namespace Slang ~EndToEndCompileRequest(); + // If enabled will emit IR + bool m_emitIr = false; + // What container format are we being asked to generate? // If it's set to a format, the container blob will be calculated during compile ContainerFormat m_containerFormat = ContainerFormat::None; @@ -2650,6 +2653,7 @@ namespace Slang // Are we being driven by the command-line `slangc`, and should act accordingly? bool m_isCommandLineCompile = false; + String m_diagnosticOutput; @@ -2769,11 +2773,12 @@ namespace Slang String m_dumpIntermediatePrefix; private: - void writeWholeProgramResult( - TargetRequest* targetReq); - void writeEntryPointResult( - TargetRequest* targetReq, - Int entryPointIndex); + + String _getWholeProgramPath(TargetRequest* targetReq); + String _getEntryPointPath(TargetRequest* targetReq, Index entryPointIndex); + + /// Maybe write the artifact to the path (if set), or stdout (if there is no container or path) + SlangResult _maybeWriteArtifact(const String& path, IArtifact* artifact); ISlangUnknown* getInterface(const Guid& guid); @@ -2782,9 +2787,6 @@ namespace Slang void init(); - SlangResult _createContainer(); - SlangResult _completeContainer(); - Session* m_session = nullptr; RefPtr<Linkage> m_linkage; DiagnosticSink m_sink; diff --git a/source/slang/slang-emit-source-writer.cpp b/source/slang/slang-emit-source-writer.cpp index 985d0a0bf..27cbd1932 100644 --- a/source/slang/slang-emit-source-writer.cpp +++ b/source/slang/slang-emit-source-writer.cpp @@ -391,6 +391,7 @@ void SourceWriter::_emitLineDirectiveIfNeeded(const HumaneSourceLoc& sourceLocat auto mode = getLineDirectiveMode(); switch (mode) { + case LineDirectiveMode::SourceMap: case LineDirectiveMode::None: return; @@ -451,6 +452,7 @@ void SourceWriter::_emitLineDirective(const HumaneSourceLoc& sourceLocation) switch (mode) { default: + case LineDirectiveMode::SourceMap: case LineDirectiveMode::None: SLANG_UNEXPECTED("should not be trying to emit '#line' directive"); return; diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index f9284d001..0b88bd057 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -972,7 +972,7 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr<IArtifact>& outAr ComPtr<IBoxValue<SourceMap>> sourceMap; // If SourceMap is enabled, we create one and associate it with the sourceWriter - if (targetRequest->getLinkage()->m_generateSourceMap) + if (lineDirectiveMode == LineDirectiveMode::SourceMap) { sourceMap = new BoxValue<SourceMap>; } diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index b1e1b93d2..a8ac88f81 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -332,9 +332,24 @@ struct OptionsParser String path = String(inPath); String ext = Path::getPathExt(path); - if (ext == "slang-module" || ext == "slang-lib" || ext == "dir" || ext == "zip") + if (ext == toSlice("slang-module") || + ext == toSlice("slang-lib") || + ext == toSlice("dir") || + ext == toSlice("zip")) { - compileRequest->setOutputContainerFormat(SLANG_CONTAINER_FORMAT_SLANG_MODULE); + // These extensions don't indicate a artifact container, just that we want to emit IR + if (ext == toSlice("slang-module") || + ext == toSlice("slang-lib")) + { + // We want to emit IR + requestImpl->m_emitIr = true; + } + else + { + // We want to write out in an artfact "container", that can hold multiple artifacts. + compileRequest->setOutputContainerFormat(SLANG_CONTAINER_FORMAT_SLANG_MODULE); + } + requestImpl->m_containerOutputPath = path; } else @@ -591,6 +606,8 @@ struct OptionsParser " -line-directive-mode <mode>: Sets how the `#line` directives should be\n" " produced. Available options are:\n" " none : Don't emit `#line` directives at all\n" + " source-map : Use source map to track line associations (doen't emit #line)\n" + " default : Default behavior\n" " If not specified, default behavior is to use C-style `#line` directives\n" " for HLSL and C/C++ output, and traditional GLSL-style `#line` directives\n" " for GLSL output.\n" @@ -890,6 +907,11 @@ struct OptionsParser { flags |= SLANG_COMPILE_FLAG_NO_MANGLING; } + else if (argValue == toSlice("-emit-ir")) + { + // Enable emitting IR + requestImpl->m_emitIr = true; + } else if (argValue == "-load-stdlib") { CommandLineArg fileName; @@ -1178,10 +1200,6 @@ struct OptionsParser { getCurrentTarget()->targetFlags |= SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES; } - else if(argValue == "-source-map") - { - requestImpl->getLinkage()->m_generateSourceMap = true; - } else if (argValue == "-ir-compression") { CommandLineArg name; @@ -1448,10 +1466,19 @@ struct OptionsParser SLANG_RETURN_ON_FAIL(reader.expectArg(name)); SlangLineDirectiveMode mode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; - if(name.value == "none") + + if(name.value == toSlice("none")) { mode = SLANG_LINE_DIRECTIVE_MODE_NONE; } + else if (name.value == toSlice("source-map")) + { + mode = SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP; + } + else if (name.value == toSlice("default")) + { + mode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; + } else { sink->diagnose(name.loc, Diagnostics::unknownLineDirectiveMode, name.value); @@ -1459,7 +1486,6 @@ struct OptionsParser } compileRequest->setLineDirectiveMode(mode); - } else if( argValue == "-fp-mode" || argValue == "-floating-point-mode" ) { @@ -1954,26 +1980,38 @@ struct OptionsParser // if(rawTargets.getCount() == 0) { - for(auto& rawOutput : rawOutputs) + // If there are no targets and no outputs + if (rawOutputs.getCount() == 0) { - // Some outputs don't imply a target format, and we shouldn't use those for inference. - auto impliedFormat = rawOutput.impliedFormat; - if( impliedFormat == CodeGenTarget::Unknown ) - continue; - - int targetIndex = 0; - if( !mapFormatToTargetIndex.TryGetValue(impliedFormat, targetIndex) ) + // And we have a container for output, then enable emitting SlangIR module + if (requestImpl->m_containerFormat != ContainerFormat::None) + { + requestImpl->m_emitIr = true; + } + } + else + { + for(auto& rawOutput : rawOutputs) { - targetIndex = (int) rawTargets.getCount(); + // Some outputs don't imply a target format, and we shouldn't use those for inference. + auto impliedFormat = rawOutput.impliedFormat; + if( impliedFormat == CodeGenTarget::Unknown ) + continue; - RawTarget rawTarget; - rawTarget.format = impliedFormat; - rawTargets.add(rawTarget); + int targetIndex = 0; + if( !mapFormatToTargetIndex.TryGetValue(impliedFormat, targetIndex) ) + { + targetIndex = (int) rawTargets.getCount(); - mapFormatToTargetIndex[impliedFormat] = targetIndex; - } + RawTarget rawTarget; + rawTarget.format = impliedFormat; + rawTargets.add(rawTarget); - rawOutput.targetIndex = targetIndex; + mapFormatToTargetIndex[impliedFormat] = targetIndex; + } + + rawOutput.targetIndex = targetIndex; + } } } else diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 6b2814ca7..637b22090 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -4887,8 +4887,16 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac auto sourceMap = asBoxValue<SourceMap>(castable); SLANG_ASSERT(sourceMap); - // I guess we add to all ir modules? - + // TODO(JS): + // There is perhaps (?) a risk here that we might copy the obfuscated map + // into some output container. Currently that only happens for source maps + // that are from translation units. + // + // On the other hand using "import" is a way that such source maps *would* be + // copied into the output, and that is something that could be a vector + // 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) { irModule->setObfuscatedSourceMap(sourceMap); @@ -5316,9 +5324,15 @@ ISlangMutableFileSystem* EndToEndCompileRequest::getCompileRequestResultAsFileSy if (m_containerArtifact) { ComPtr<ISlangMutableFileSystem> fileSystem(new MemoryFileSystem); - if (SLANG_SUCCEEDED(ArtifactContainerUtil::writeContainer(m_containerArtifact, "", fileSystem))) + + // Filter the containerArtifact into things that can be written + ComPtr<IArtifact> writeArtifact; + if (SLANG_SUCCEEDED(ArtifactContainerUtil::filter(m_containerArtifact, writeArtifact))) { - m_containerFileSystem.swap(fileSystem); + if (SLANG_SUCCEEDED(ArtifactContainerUtil::writeContainer(writeArtifact, "", fileSystem))) + { + m_containerFileSystem.swap(fileSystem); + } } } } diff --git a/tests/feature/source-map/emit-source-map.slang b/tests/feature/source-map/emit-source-map.slang new file mode 100644 index 000000000..95779c368 --- /dev/null +++ b/tests/feature/source-map/emit-source-map.slang @@ -0,0 +1,16 @@ +//TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2 -line-directive-mode source-map -o tests/feature/source-map/emit-source-map.zip + +RWStructuredBuffer<int> outputBuffer; + +int doThing(int a) +{ + return a + a - 1; +} + +[numthreads(4, 4, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int x = (int)dispatchThreadID.x; + + outputBuffer[x] = doThing(x); +}
\ No newline at end of file diff --git a/tests/serialization/obfuscated-check-loc.slang b/tests/serialization/obfuscated-check-loc.slang index 8575a2650..09cc86706 100644 --- a/tests/serialization/obfuscated-check-loc.slang +++ b/tests/serialization/obfuscated-check-loc.slang @@ -1,4 +1,4 @@ -//TEST:SIMPLE:-target cpp -stage compute -entry computeMain -obfuscate -source-map -line-directive-mode none +//TEST:SIMPLE:-target cpp -stage compute -entry computeMain -obfuscate -line-directive-mode none //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; diff --git a/tests/serialization/obfuscated-module-check-loc.slang b/tests/serialization/obfuscated-module-check-loc.slang index f603d5403..2570c8843 100644 --- a/tests/serialization/obfuscated-module-check-loc.slang +++ b/tests/serialization/obfuscated-module-check-loc.slang @@ -1,4 +1,4 @@ -//TEST:COMPILE: tests/serialization/obfuscated-loc-module.slang -o tests/serialization/obfuscated-loc-module.zip -g -obfuscate -source-map +//TEST:COMPILE: tests/serialization/obfuscated-loc-module.slang -o tests/serialization/obfuscated-loc-module.zip -g -obfuscate //TEST:SIMPLE:-target hlsl -stage compute -entry computeMain -obfuscate -r tests/serialization/obfuscated-loc-module.zip //TEST:COMPILE: tests/serialization/obfuscated-loc-module.slang -o tests/serialization/obfuscated-loc-module.zip -g -obfuscate // Disable for now as it breaks on gcc/release as different hash seems to be produced diff --git a/tests/serialization/obfuscated-serialized-module-test.slang b/tests/serialization/obfuscated-serialized-module-test.slang index b007b7516..927ee06bc 100644 --- a/tests/serialization/obfuscated-serialized-module-test.slang +++ b/tests/serialization/obfuscated-serialized-module-test.slang @@ -3,8 +3,8 @@ // 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 -source-map -//TEST:COMPARE_COMPUTE_EX:-slang -compute -Xslang... -r tests/serialization/obfuscated-serialized-module.slang-module -obfuscate -source-map -X. -shaderobj +//TEST:COMPILE: tests/serialization/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; |
