Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix function definition in debug info, and related cleanups #2807

Merged
merged 4 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions llpc/test/shaderdb/debug_info/FunctionCall.pipe
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
; RUN: amdllpc -trim-debug-info=false -filetype=asm -o - -gfxip 11.0 %s | FileCheck -check-prefixes=NOTRIM %s
; RUN: amdllpc -trim-debug-info=true -filetype=asm -o - -gfxip 11.0 %s | FileCheck -check-prefixes=TRIM %s

; Just a simple sanity check that the compiler ran through and produced *some* debug info
; NOTRIM: .loc 1 11 0 prologue_end

; TRIM-NOT: .loc
; TRIM: s_endpgm

[CsSpirv]
; Compiled with glslangValidator --target-env vulkan1.3 -gVS
; SPIR-V
; Version: 1.6
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 88
; Schema: 0
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%2 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
%3 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %dst %gl_GlobalInvocationID
OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1
%1 = OpString "simplified.comp"
%9 = OpString "uint"
%15 = OpString "main"
%18 = OpString "#version 460

layout(set = 0, binding = 0, r32ui) uniform uimage2D dst;

uint BugFunction(uint val0) {
return val0;
}

void main() {
uvec4 data = uvec4(BugFunction(0));
imageStore(dst, ivec2(gl_GlobalInvocationID.xy), data);
}
"
%29 = OpString "BugFunction"
%35 = OpString "val0"
%53 = OpString "data"
%62 = OpString "type.2d.image"
%63 = OpString "@type.2d.image"
%68 = OpString "dst"
%76 = OpString "gl_GlobalInvocationID"
%82 = OpString "int"
OpName %main "main"
OpName %BugFunction_u1_ "BugFunction(u1;"
OpName %val0 "val0"
OpName %data "data"
OpName %param "param"
OpName %dst "dst"
OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
OpModuleProcessed "client vulkan100"
OpModuleProcessed "target-env spirv1.6"
OpModuleProcessed "target-env vulkan1.3"
OpModuleProcessed "entry-point main"
OpDecorate %dst DescriptorSet 0
OpDecorate %dst Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%8 = OpExtInst %void %2 DebugTypeBasic %9 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %2 DebugTypeFunction %uint_3 %void
%17 = OpExtInst %void %2 DebugSource %1 %18
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%19 = OpExtInst %void %2 DebugCompilationUnit %uint_1 %uint_4 %17 %uint_2
%16 = OpExtInst %void %2 DebugFunction %15 %6 %17 %uint_0 %uint_0 %19 %15 %uint_3 %uint_0
%_ptr_Function_uint = OpTypePointer Function %uint
%25 = OpTypeFunction %uint %_ptr_Function_uint
%26 = OpExtInst %void %2 DebugTypeFunction %uint_3 %8 %8
%30 = OpExtInst %void %2 DebugFunction %29 %26 %17 %uint_0 %uint_0 %19 %29 %uint_3 %uint_0
%34 = OpExtInst %void %2 DebugLocalVariable %35 %8 %17 %uint_0 %uint_0 %30 %uint_4 %uint_1
%37 = OpExtInst %void %2 DebugExpression
%uint_10 = OpConstant %uint 10
%v4uint = OpTypeVector %uint 4
%49 = OpExtInst %void %2 DebugTypeVector %8 %uint_4
%_ptr_Function_v4uint = OpTypePointer Function %v4uint
%52 = OpExtInst %void %2 DebugLocalVariable %53 %49 %17 %uint_10 %uint_0 %16 %uint_4
%uint_11 = OpConstant %uint 11
%60 = OpTypeImage %uint 2D 0 0 0 2 R32ui
%64 = OpExtInst %void %2 DebugInfoNone
%61 = OpExtInst %void %2 DebugTypeComposite %62 %uint_0 %17 %uint_11 %uint_0 %19 %63 %64 %uint_3
%_ptr_UniformConstant_60 = OpTypePointer UniformConstant %60
%dst = OpVariable %_ptr_UniformConstant_60 UniformConstant
%uint_8 = OpConstant %uint 8
%67 = OpExtInst %void %2 DebugGlobalVariable %68 %61 %17 %uint_11 %uint_0 %19 %68 %dst %uint_8
%v3uint = OpTypeVector %uint 3
%72 = OpExtInst %void %2 DebugTypeVector %8 %uint_3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%75 = OpExtInst %void %2 DebugGlobalVariable %76 %72 %17 %uint_11 %uint_0 %19 %76 %gl_GlobalInvocationID %uint_8
%v2uint = OpTypeVector %uint 2
%78 = OpExtInst %void %2 DebugTypeVector %8 %uint_2
%int = OpTypeInt 32 1
%83 = OpExtInst %void %2 DebugTypeBasic %82 %uint_32 %uint_4 %uint_0
%v2int = OpTypeVector %int 2
%85 = OpExtInst %void %2 DebugTypeVector %83 %uint_2
OpLine %1 9 11
%main = OpFunction %void None %5
%23 = OpLabel
%data = OpVariable %_ptr_Function_v4uint Function
%param = OpVariable %_ptr_Function_uint Function
%44 = OpExtInst %void %2 DebugFunctionDefinition %16 %main
%45 = OpExtInst %void %2 DebugScope %16
%46 = OpExtInst %void %2 DebugLine %17 %uint_10 %uint_10 %uint_0 %uint_0
%54 = OpExtInst %void %2 DebugDeclare %52 %data %37
OpStore %param %uint_0
%56 = OpFunctionCall %uint %BugFunction_u1_ %param
%57 = OpCompositeConstruct %v4uint %56 %56 %56 %56
OpStore %data %57
%58 = OpExtInst %void %2 DebugLine %17 %uint_11 %uint_11 %uint_0 %uint_0
%70 = OpLoad %60 %dst
%79 = OpLoad %v3uint %gl_GlobalInvocationID
%80 = OpVectorShuffle %v2uint %79 %79 0 1
%86 = OpBitcast %v2int %80
%87 = OpLoad %v4uint %data
OpImageWrite %70 %86 %87 ZeroExtend
OpReturn
OpFunctionEnd
OpLine %1 5 27
%BugFunction_u1_ = OpFunction %uint None %25
%val0 = OpFunctionParameter %_ptr_Function_uint
%31 = OpLabel
%32 = OpExtInst %void %2 DebugScope %30
%33 = OpExtInst %void %2 DebugLine %17 %uint_0 %uint_0 %uint_0 %uint_0
%36 = OpExtInst %void %2 DebugDeclare %34 %val0 %37
%38 = OpExtInst %void %2 DebugFunctionDefinition %30 %BugFunction_u1_
%39 = OpExtInst %void %2 DebugScope %30
%40 = OpExtInst %void %2 DebugLine %17 %uint_6 %uint_6 %uint_0 %uint_0
%41 = OpLoad %uint %val0
OpReturnValue %41
OpFunctionEnd

[CsInfo]
entryPoint = main
userDataNode[0].visibility = 0xffffffff
userDataNode[0].type = DescriptorTableVaPtr
userDataNode[0].offsetInDwords = 0
userDataNode[0].sizeInDwords = 1
userDataNode[0].next[0].type = DescriptorImage
userDataNode[0].next[0].offsetInDwords = 0
userDataNode[0].next[0].sizeInDwords = 8
userDataNode[0].next[0].set = 0x00000000
userDataNode[0].next[0].binding = 0
44 changes: 13 additions & 31 deletions llpc/translator/lib/SPIRV/SPIRVToLLVMDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,15 +477,11 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) {

SPIRVWord SPIRVDebugFlags = getConstant(Ops[FlagsIdx]);
DINode::DIFlags Flags = mapToDIFlags(SPIRVDebugFlags);
// TODO: IsDefinition is always true for DebugFunction, but should be false
// for DebugFunctionDeclaration.
const bool IsDefinition = true;

bool IsOptimized = SPIRVDebugFlags & SPIRVDebug::FlagIsOptimized;
bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal;
bool IsMainSubprogram = BM->getEntryPoint(Ops[FunctionIdIdx]) != nullptr;
DISubprogram::DISPFlags SPFlags =
DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized, DISubprogram::SPFlagNonvirtual, IsMainSubprogram);
DISubprogram::toSPFlags(IsLocal, /*IsDefinition*/ true, IsOptimized, DISubprogram::SPFlagNonvirtual,
/*IsMainSubprogram*/ false);

unsigned ScopeLine = getConstant(Ops[ScopeLineIdx]);

Expand All @@ -504,26 +500,9 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) {
DINodeArray TParams = Builder.getOrCreateArray(Elts);
llvm::DITemplateParameterArray TParamsArray = TParams.get();

DISubprogram *DIS = nullptr;
if ((isa<DICompositeType>(Scope) || isa<DINamespace>(Scope)) && !IsDefinition)
DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, nullptr, Flags, SPFlags, TParamsArray);
else
DIS =
Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty, ScopeLine, Flags, SPFlags, TParamsArray, FD);
DISubprogram *DIS =
Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty, ScopeLine, Flags, SPFlags, TParamsArray, FD);
DebugInstCache[DebugInst] = DIS;
SPIRVId RealFuncId = Ops[FunctionIdIdx];
FuncMap[RealFuncId] = DIS;

// Function.
SPIRVEntry *E = BM->getEntry(Ops[FunctionIdIdx]);
if (E->getOpCode() == OpFunction) {
SPIRVFunction *BF = static_cast<SPIRVFunction *>(E);
llvm::Function *F = SPIRVReader->transFunction(BF);
assert(F && "Translation of function failed!");
if (!F->hasMetadata())
F->setMetadata("dbg", DIS);
F->setSubprogram(DIS);
}
return DIS;
}

Expand Down Expand Up @@ -887,12 +866,15 @@ Instruction *SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugIn
case SPIRVDebug::NoScope:
return nullptr;
case SPIRVDebug::FunctionDefinition: {
using namespace SPIRVDebug::Operand::Function;
SPIRVExtInst *funcExt = BM->get<SPIRVExtInst>(Ops[0]);
std::vector<SPIRVWord> &args = funcExt->getArguments();
assert(args.size() > FunctionIdIdx);
args[FunctionIdIdx] = Ops[1];
transDebugInst<DISubprogram>(funcExt);
SPIRVExtInst *dbgDef = BM->get<SPIRVExtInst>(Ops[0]);
SPIRVFunction *opDef = BM->get<SPIRVFunction>(Ops[1]);
DISubprogram *DIS = transDebugInst<DISubprogram>(dbgDef);

FuncMap[opDef->getId()] = DIS;

llvm::Function *F = SPIRVReader->transFunction(opDef);
assert(F && "Translation of function failed!");
F->setSubprogram(DIS);
return nullptr;
}

Expand Down
5 changes: 2 additions & 3 deletions llpc/translator/lib/SPIRV/libSPIRV/SPIRV.debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,8 @@ enum {
LinkageNameIdx = 6,
FlagsIdx = 7,
ScopeLineIdx = 8,
FunctionIdIdx = 9,
DeclarationIdx = 10,
MinOperandCount = 10
DeclarationIdx = 9,
MinOperandCount = 9
};
}

Expand Down
5 changes: 0 additions & 5 deletions llpc/translator/lib/SPIRV/libSPIRV/SPIRVInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1560,11 +1560,6 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
SPIRVLine *line = Module->add(new SPIRVLine(Module, Args[0], dbgLn, dbgCol));
Module->setCurrentLine(line);
}
// NonSemanticShaderDebugInfo100DebugFunction has one less argument than
// OpenCL.DebugInfo.100 DebugFunction
else if (ExtOpDebug == NonSemanticShaderDebugInfo100DebugFunction) {
Args.push_back(0);
}
}
}
void validate() const override {
Expand Down
30 changes: 24 additions & 6 deletions llpc/util/llpcShaderModuleHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,13 @@ unsigned ShaderModuleHelper::trimSpirvDebugInfo(const BinaryData *spvBin, llvm::
codeBuffer = codeBuffer.drop_front(sizeof(Vkgc::SpirvHeader) / wordSize);
}

unsigned nonSemanticShaderDebug = ~0;

// Copy SPIR-V instructions
while (codePos < end) {
unsigned opCode = (codePos[0] & OpCodeMask);
unsigned wordCount = (codePos[0] >> WordCountShift);
bool skip = false;
switch (opCode) {
case OpSource:
case OpSourceContinued:
Expand All @@ -266,21 +269,36 @@ unsigned ShaderModuleHelper::trimSpirvDebugInfo(const BinaryData *spvBin, llvm::
case OpLine:
case OpNop:
case OpNoLine:
case OpModuleProcessed: {
// Skip debug instructions
case OpModuleProcessed:
skip = true;
break;
case OpExtInstImport: {
unsigned id = codePos[1];
const char *name = reinterpret_cast<const char *>(&codePos[2]);
if (!strcmp(name, "NonSemantic.Shader.DebugInfo.100")) {
nonSemanticShaderDebug = id;
skip = true;
}
break;
}
default: {
// Copy other instructions
case OpExtInst: {
unsigned set = codePos[3];
if (set == nonSemanticShaderDebug)
skip = true;
break;
}
default:
break;
}

if (!skip) {
if (writeCode) {
assert(codePos + wordCount <= end);
assert(wordCount <= codeBuffer.size());
memcpy(codeBuffer.data(), codePos, wordCount * wordSize);
codeBuffer = codeBuffer.drop_front(wordCount);
}
totalSizeInWords += wordCount;
break;
}
}

codePos += wordCount;
Expand Down
Loading