diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 94952b3c34..0497c5af74 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -1450,28 +1450,10 @@ 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; @@ -1481,8 +1463,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) { @@ -1551,8 +1536,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(decl->getBody()); @@ -13197,11 +13182,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 +13455,36 @@ bool SpirvEmitter::processMeshOrAmplificationShaderAttributes( return true; } +SpirvDebugFunction *SpirvEmitter::emitDebugFunction(const FunctionDecl *decl, + SpirvFunction *func, + RichDebugInfo **info, + std::string name) { + auto loc = decl->getLocStart(); + 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 +13520,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 +13602,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 diff --git a/tools/clang/test/CodeGenSPIRV/shader.debug.function.hlsl b/tools/clang/test/CodeGenSPIRV/shader.debug.function.hlsl index e59e9bc807..6d61d9f5c4 100644 --- a/tools/clang/test/CodeGenSPIRV/shader.debug.function.hlsl +++ b/tools/clang/test/CodeGenSPIRV/shader.debug.function.hlsl @@ -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 @@ -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)