From 565af6567022a9121e21f0e72983e2f4eea19d0c Mon Sep 17 00:00:00 2001 From: Steve Urquhart Date: Mon, 7 Oct 2024 10:52:12 -0400 Subject: [PATCH] [SPIRV] Emit DebugFunction and Definition for both wrapper and real functions --- tools/clang/lib/SPIRV/SpirvEmitter.cpp | 76 +++++++++++++------ tools/clang/lib/SPIRV/SpirvEmitter.h | 8 ++ .../rich.debug.function.param.hlsl | 2 +- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 94952b3c34..8197f8296a 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -1453,25 +1453,7 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) { 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; @@ -1481,14 +1463,18 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) { if (entryInfo->isEntryFunction) { isEntry = true; funcName = "src." + funcName; + SpirvDebugFunction *wrapperDebugFunction = nullptr; + if (spirvOptions.debugInfoRich && decl->hasBody()) { + wrapperDebugFunction = emitDebugFunction(decl, func, &info, funcName); + } // Create wrapper for the entry function - if (!emitEntryFunctionWrapper(decl, func)) + if (!emitEntryFunctionWrapper(decl, wrapperDebugFunction, func)) return; // Generate DebugEntryPoint if function definition - if (spirvOptions.debugInfoVulkan && debugFunction) { + if (spirvOptions.debugInfoVulkan && wrapperDebugFunction) { auto *cu = dyn_cast(outer_scope); assert(cu && "expected DebugCompilationUnit"); - spvBuilder.createDebugEntryPoint(debugFunction, cu, + spvBuilder.createDebugEntryPoint(wrapperDebugFunction, cu, clang::getGitCommitHash(), spirvOptions.clOptions); } @@ -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 = @@ -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; @@ -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()) { @@ -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 diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.h b/tools/clang/lib/SPIRV/SpirvEmitter.h index 242550c295..64d9c60baf 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.h +++ b/tools/clang/lib/SPIRV/SpirvEmitter.h @@ -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. /// @@ -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 @@ -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: diff --git a/tools/clang/test/CodeGenSPIRV/rich.debug.function.param.hlsl b/tools/clang/test/CodeGenSPIRV/rich.debug.function.param.hlsl index c30dc8c262..231750cd64 100644 --- a/tools/clang/test/CodeGenSPIRV/rich.debug.function.param.hlsl +++ b/tools/clang/test/CodeGenSPIRV/rich.debug.function.param.hlsl @@ -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