Skip to content

Commit

Permalink
[SPIRV] Emit DebugFunction and Definition for both wrapper and real f…
Browse files Browse the repository at this point in the history
…unctions
  • Loading branch information
SteveUrquhart committed Oct 17, 2024
1 parent dfa1c81 commit 7cc8280
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 32 deletions.
76 changes: 52 additions & 24 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1450,28 +1450,11 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
auto range = decl->getSourceRange();
RichDebugInfo *info = nullptr;
SpirvDebugFunction *debugFunction = nullptr;
SpirvDebugFunction *wrappedDebugFunction = nullptr;
SpirvDebugInstruction *outer_scope = spvContext.getCurrentLexicalScope();
const auto &sm = astContext.getSourceManager();
if (spirvOptions.debugInfoRich && decl->hasBody()) {
const uint32_t line = sm.getPresumedLineNumber(loc);
const uint32_t column = sm.getPresumedColumnNumber(loc);
info = getOrCreateRichDebugInfo(loc);

auto *source = info->source;
// Note that info->scopeStack.back() is a lexical scope of the function
// caller.
auto *parentScope = info->compilationUnit;
// TODO: figure out the proper flag based on the function decl.
// using FlagIsPublic for now.
uint32_t flags = 3u;
// The line number in the source program at which the function scope begins.
auto scopeLine = sm.getPresumedLineNumber(decl->getBody()->getLocStart());
debugFunction = spvBuilder.createDebugFunction(decl, debugFuncName, source,
line, column, parentScope,
"", flags, scopeLine, func);
func->setDebugScope(new (spvContext) SpirvDebugScope(debugFunction));

spvContext.pushDebugLexicalScope(info, debugFunction);
debugFunction = emitDebugFunction(decl, func, &info, funcName);
}

bool isEntry = false;
Expand All @@ -1481,8 +1464,11 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
if (entryInfo->isEntryFunction) {
isEntry = true;
funcName = "src." + funcName;
if (spirvOptions.debugInfoRich && decl->hasBody()) {
wrappedDebugFunction = emitDebugFunction(decl, func, &info, funcName);
}
// Create wrapper for the entry function
if (!emitEntryFunctionWrapper(decl, func))
if (!emitEntryFunctionWrapper(decl, debugFunction, func))
return;
// Generate DebugEntryPoint if function definition
if (spirvOptions.debugInfoVulkan && debugFunction) {
Expand Down Expand Up @@ -1551,8 +1537,8 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {

// Add DebugFunctionDefinition if we are emitting
// NonSemantic.Shader.DebugInfo.100 debug info
if (spirvOptions.debugInfoVulkan && debugFunction)
spvBuilder.createDebugFunctionDef(debugFunction, func);
if (spirvOptions.debugInfoVulkan && wrappedDebugFunction)
spvBuilder.createDebugFunctionDef(wrappedDebugFunction, func);

// Process all statments in the body.
parentMap = std::make_unique<ParentMap>(decl->getBody());
Expand Down Expand Up @@ -13197,11 +13183,17 @@ bool SpirvEmitter::processTessellationShaderAttributes(
}

bool SpirvEmitter::emitEntryFunctionWrapperForRayTracing(
const FunctionDecl *decl, SpirvFunction *entryFuncInstr) {
const FunctionDecl *decl, SpirvDebugFunction *debugFunction,
SpirvFunction *entryFuncInstr) {
// The entry basic block.
auto *entryLabel = spvBuilder.createBasicBlock();
spvBuilder.setInsertPoint(entryLabel);

// Add DebugFunctionDefinition if we are emitting
// NonSemantic.Shader.DebugInfo.100 debug info.
if (spirvOptions.debugInfoVulkan && debugFunction)
spvBuilder.createDebugFunctionDef(debugFunction, entryFunction);

// Initialize all global variables at the beginning of the wrapper
for (const VarDecl *varDecl : toInitGloalVars) {
const auto varInfo =
Expand Down Expand Up @@ -13464,7 +13456,37 @@ bool SpirvEmitter::processMeshOrAmplificationShaderAttributes(
return true;
}

SpirvDebugFunction *SpirvEmitter::emitDebugFunction(const FunctionDecl *decl,
SpirvFunction *func,
RichDebugInfo **info,
std::string name) {
auto loc = decl->getLocStart();
auto range = decl->getSourceRange();
const auto &sm = astContext.getSourceManager();
const uint32_t line = sm.getPresumedLineNumber(loc);
const uint32_t column = sm.getPresumedColumnNumber(loc);
*info = getOrCreateRichDebugInfo(loc);

SpirvDebugSource *source = (*info)->source;
// Note that info->scopeStack.back() is a lexical scope of the function
// caller.
SpirvDebugInstruction *parentScope = (*info)->compilationUnit;
// TODO: figure out the proper flag based on the function decl.
// using FlagIsPublic for now.
uint32_t flags = 3u;
// The line number in the source program at which the function scope begins.
auto scopeLine = sm.getPresumedLineNumber(decl->getBody()->getLocStart());
SpirvDebugFunction *debugFunction =
spvBuilder.createDebugFunction(decl, name, source, line, column,
parentScope, "", flags, scopeLine, func);
func->setDebugScope(new (spvContext) SpirvDebugScope(debugFunction));

spvContext.pushDebugLexicalScope(*info, debugFunction);
return debugFunction;
}

bool SpirvEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
SpirvDebugFunction *debugFunction,
SpirvFunction *entryFuncInstr) {
// HS specific attributes
uint32_t numOutputControlPoints = 0;
Expand Down Expand Up @@ -13500,7 +13522,8 @@ bool SpirvEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
entryInfo->entryFunction = entryFunction;

if (spvContext.isRay()) {
return emitEntryFunctionWrapperForRayTracing(decl, entryFuncInstr);
return emitEntryFunctionWrapperForRayTracing(decl, debugFunction,
entryFuncInstr);
}
// Handle attributes specific to each shader stage
if (spvContext.isPS()) {
Expand Down Expand Up @@ -13581,6 +13604,11 @@ bool SpirvEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
// after the basic block is created and insert point is set.
processInlineSpirvAttributes(decl);

// Add DebugFunctionDefinition if we are emitting
// NonSemantic.Shader.DebugInfo.100 debug info.
if (spirvOptions.debugInfoVulkan && debugFunction)
spvBuilder.createDebugFunctionDef(debugFunction, entryFunction);

// Initialize all global variables at the beginning of the wrapper
for (const VarDecl *varDecl : toInitGloalVars) {
// SPIR-V does not have string variables
Expand Down
8 changes: 8 additions & 0 deletions tools/clang/lib/SPIRV/SpirvEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,12 @@ class SpirvEmitter : public ASTConsumer {
processMeshOrAmplificationShaderAttributes(const FunctionDecl *decl,
uint32_t *outVerticesArraySize);

/// \brief Emits a SpirvDebugFunction to match given SpirvFunction, and
/// returns a pointer to it.
SpirvDebugFunction *emitDebugFunction(const FunctionDecl *decl,
SpirvFunction *func,
RichDebugInfo **info, std::string name);

/// \brief Emits a wrapper function for the entry function and returns true
/// on success.
///
Expand All @@ -854,6 +860,7 @@ class SpirvEmitter : public ASTConsumer {
/// The wrapper function is also responsible for initializing global static
/// variables for some cases.
bool emitEntryFunctionWrapper(const FunctionDecl *entryFunction,
SpirvDebugFunction *debugFunction,
SpirvFunction *entryFuncId);

/// \brief Emits a wrapper function for the entry functions for raytracing
Expand All @@ -864,6 +871,7 @@ class SpirvEmitter : public ASTConsumer {
/// The wrapper function is also responsible for initializing global static
/// variables for some cases.
bool emitEntryFunctionWrapperForRayTracing(const FunctionDecl *entryFunction,
SpirvDebugFunction *debugFunction,
SpirvFunction *entryFuncId);

/// \brief Performs the following operations for the Hull shader:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// CHECK: [[emptyStr:%[0-9]+]] = OpString ""
// CHECK: [[y:%[0-9]+]] = OpString "y"
// CHECK: [[x:%[0-9]+]] = OpString "x"
// CHECK: [[mainName:%[0-9]+]] = OpString "main"
// CHECK: [[mainName:%[0-9]+]] = OpString "src.main"
// CHECK: [[color:%[0-9]+]] = OpString "color"

// CHECK: [[int:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic {{%[0-9]+}} %uint_32 Signed
Expand Down
19 changes: 12 additions & 7 deletions tools/clang/test/CodeGenSPIRV/shader.debug.function.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
// CHECK: [[set:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
// CHECK: [[fooName:%[0-9]+]] = OpString "foo"
// CHECK: [[emptyStr:%[0-9]+]] = OpString ""
// CHECK: [[srcMainName:%[0-9]+]] = OpString "src.main"
// CHECK: [[mainName:%[0-9]+]] = OpString "main"
// CHECK: [[clOpts:%[0-9]+]] = OpString " -E main -T ps_6_0 -spirv -fcgl -fspv-debug=vulkan
// CHECK: [[clOpts:%[0-9]+]] = OpString " -E main -T ps_6_0 -spirv -fcgl -fspv-debug=vulkan

// CHECK: [[int:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic {{%[0-9]+}} %uint_32 %uint_4 %uint_0
// CHECK: [[float:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic {{%[0-9]+}} %uint_32 %uint_3 %uint_0
Expand All @@ -17,18 +18,22 @@

// Check DebugFunction instructions
//
// CHECK: {{%[0-9]+}} = OpExtInst %void [[set]] DebugFunction [[fooName]] [[fooFnType]] [[source]] %uint_34 %uint_1 [[compilationUnit]] [[emptyStr]] %uint_3 %uint_35

// CHECK: [[float4:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeVector [[float]] %uint_4
// CHECK: [[mainFnType:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeFunction %uint_3 [[float4]] [[float4]]
// CHECK: [[mainDbgFn:%[0-9]+]] = OpExtInst %void [[set]] DebugFunction [[mainName]] [[mainFnType]] [[source]] %uint_39 %uint_1 [[compilationUnit]] [[emptyStr]] %uint_3 %uint_40
// CHECK: [[srcMainDbgFn:%[0-9]+]] = OpExtInst %void [[set]] DebugFunction [[srcMainName]] [[mainFnType]] [[source]] %uint_44 %uint_1 [[compilationUnit]] [[emptyStr]] %uint_3 %uint_45
// CHECK: [[mainDbgFn:%[0-9]+]] = OpExtInst %void [[set]] DebugFunction [[mainName]] [[mainFnType]] [[source]] %uint_44 %uint_1 [[compilationUnit]] [[emptyStr]] %uint_3 %uint_45
// CHECK: [[mainDbgEp:%[0-9]+]] = OpExtInst %void [[set]] DebugEntryPoint [[mainDbgFn]] [[compilationUnit]] {{%[0-9]+}} [[clOpts]]

// Check DebugFunctionDefintion is in src_main
// Check DebugFunctionDefinition is in main
//
// CHECK: %src_main = OpFunction %v4float None {{%[0-9]+}}
// CHECK: {{%[0-9]+}} = OpExtInst %void [[set]] DebugFunctionDefinition [[mainDbgFn]] %src_main
// CHECK: %main = OpFunction %void None {{%[0-9]+}}
// CHECK: {{%[0-9]+}} = OpExtInst %void [[set]] DebugFunctionDefinition [[mainDbgFn]] %main
// CHECK: OpFunctionEnd

// Check DebugFunctionDefinition is in src.main
//
// CHECK: %src_main = OpFunction %v4float None {{%[0-9]+}}
// CHECK: {{%[0-9]+}} = OpExtInst %void [[set]] DebugFunctionDefinition [[srcMainDbgFn]] %src_main
// CHECK: OpFunctionEnd

void foo(int x, float y)
Expand Down

0 comments on commit 7cc8280

Please sign in to comment.