summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-compiler.cpp
diff options
context:
space:
mode:
authorjarcherNV <jarcher@nvidia.com>2025-06-06 14:30:06 -0700
committerGitHub <noreply@github.com>2025-06-06 14:30:06 -0700
commit0d16228ae22fa2e1a00e62dc099eea08da7717fe (patch)
tree067573914132892dc1336dcdea2c8b595f24f871 /source/slang/slang-compiler.cpp
parent649d533727b31b28397ffb3a530e655ac3861547 (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.cpp91
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);
}
}
}