diff options
| author | jarcherNV <jarcher@nvidia.com> | 2025-06-06 14:30:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-06 14:30:06 -0700 |
| commit | 0d16228ae22fa2e1a00e62dc099eea08da7717fe (patch) | |
| tree | 067573914132892dc1336dcdea2c8b595f24f871 /source/slang/slang-compiler.cpp | |
| parent | 649d533727b31b28397ffb3a530e655ac3861547 (diff) | |
Add command line option for separate debug info (#7178)
* Add command line option for separate debug info
Add command line arg -separate-debug-info which, if provided, produces
both a .spv and a .dbg.spv file. The .dbg.spv file contains full debug
info and the .spv file has all debug info stripped out.
Also add a DebugBuildIdentifier instruction to store a unique hash in
both the output files, so they can be more easily matched together.
A matching API is provided to allow using the Slang API to retrieve a
base and debug SPIRV as well as the debug build identifier string.
Diffstat (limited to 'source/slang/slang-compiler.cpp')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 86dcf5d7f..4e114eb78 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1860,6 +1860,23 @@ static CodeGenTarget _getIntermediateTarget(CodeGenTarget target) } } +static IArtifact* _getSeparateDbgArtifact(IArtifact* artifact) +{ + if (!artifact) + return nullptr; + + // The first associated artifact of kind ObjectCode and SPIRV payload should be the debug + // artifact. + for (auto* associated : artifact->getAssociated()) + { + auto desc = associated->getDesc(); + if (desc.kind == ArtifactKind::ObjectCode && desc.payload == ArtifactPayload::SPIRV) + return associated; + } + + return nullptr; +} + /// Function to simplify the logic around emitting, and dissassembling SlangResult CodeGenContext::_emitEntryPoints(ComPtr<IArtifact>& outArtifact) { @@ -1890,6 +1907,32 @@ SlangResult CodeGenContext::_emitEntryPoints(ComPtr<IArtifact>& outArtifact) getSink(), disassemblyArtifact.writeRef())); + // Also disassemble the debug artifact if one exists. + auto debugArtifact = _getSeparateDbgArtifact(intermediateArtifact); + ComPtr<IArtifact> disassemblyDebugArtifact; + if (debugArtifact) + { + SLANG_RETURN_ON_FAIL(ArtifactOutputUtil::dissassembleWithDownstream( + getSession(), + debugArtifact, + getSink(), + disassemblyDebugArtifact.writeRef())); + disassemblyDebugArtifact->setName(debugArtifact->getName()); + + // The disassembly needs both the metadata for the debug build identifier + // and the debug spirv to be associated with is. + for (auto associated : intermediateArtifact->getAssociated()) + { + if (associated->getDesc().payload == ArtifactPayload::Metadata || + associated->getDesc().payload == ArtifactPayload::PostEmitMetadata) + { + disassemblyArtifact->addAssociated(associated); + break; + } + } + disassemblyArtifact->addAssociated(disassemblyDebugArtifact); + } + outArtifact.swap(disassemblyArtifact); return SLANG_OK; } @@ -2113,6 +2156,46 @@ SlangResult EndToEndCompileRequest::_maybeWriteArtifact(const String& path, IArt return SLANG_OK; } +// These helper functions are used by the -separate-debug-info command line +// arg to extract the associated artifact containing the debug SPIRV data +// and save it to a file with a .dbg.spv extension. +static String _getDebugSpvPath(const String& basePath) +{ + // Find the last occurrence of ".spv" at the end of the string. + static const char ext[] = ".spv"; + static const char dbgExt[] = ".dbg.spv"; + Index extLen = 4; + if (basePath.getLength() >= extLen && basePath.endsWith(ext)) + { + // Replace the ".spv" extension with ".dbg.spv" + String prefix = String(basePath.subString(0, basePath.getLength() - extLen)); + return prefix + dbgExt; + } + // If it doesn't end with .spv, just append .dbg.spv + return basePath + dbgExt; +} + +SlangResult EndToEndCompileRequest::_maybeWriteDebugArtifact( + TargetProgram* targetProgram, + const String& path, + IArtifact* artifact) +{ + if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EmitSeparateDebug)) + { + const auto dbgArtifact = _getSeparateDbgArtifact(artifact); + // The artifact's name may have been set to the debug build id hash, use + // it as the filename if it exists. + String dbgPath = dbgArtifact->getName(); + if (dbgPath.getLength() == 0) + dbgPath = _getDebugSpvPath(path); + else + dbgPath.append(".dbg.spv"); + return _maybeWriteArtifact(dbgPath, dbgArtifact); + } + + return SLANG_OK; +} + IArtifact* TargetProgram::_createWholeProgramResult( DiagnosticSink* sink, EndToEndCompileRequest* endToEndReq) @@ -2612,6 +2695,10 @@ void EndToEndCompileRequest::generateOutput() const auto path = _getWholeProgramPath(targetReq); _maybeWriteArtifact(path, artifact); + + // If we are compiling separate debug info, check for the additional + // SPIRV artifact and write that if needed. + _maybeWriteDebugArtifact(targetProgram, path, artifact); } } else @@ -2624,6 +2711,10 @@ void EndToEndCompileRequest::generateOutput() const auto path = _getEntryPointPath(targetReq, ee); _maybeWriteArtifact(path, artifact); + + // If we are compiling separate debug info, check for the additional + // SPIRV artifact and write that if needed. + _maybeWriteDebugArtifact(targetProgram, path, artifact); } } } |
