Skip to content

Commit

Permalink
[DebugInfo] Fix SPIR-V consumption of DebugInfoNone for debug types (K…
Browse files Browse the repository at this point in the history
…hronosGroup#2341)

OpenCL and NonSemantic DebugInfo specifications are flexible in terms of allowing any debug information be replaced with DebugInfoNone, so various of SPIR-V producers follow that and generate it for base types of several debug instructions, leaving SPIR-V consumers to handle this. By default the translator replaces missing debug info with tag: null, which is in most cases correct. Yet, there are situations, where it's not allowed by both LLVM and DWARF, for example for DW_TAG_array_type DWARF spec sets, that DW_AT_type attribute is mandatory. For such cases new transNonNullDebugType wrapper function was added to the translator, generating "DIBasicType(tag: DW_TAG_unspecified_type, name: "SPIRV unknown type")" where DebugInfoNone was used as the type. This function doesn't replace all calls to transDebugInst<DIType> as there are cases, where we can generate null type, for example DWARF doesn't require it for DW_TAG_typedef, hence I'm not changing translation flow in this case. Additionally to this, while DWARF requires type attribute for DW_TAG_pointer_type, LLVM does not, hence I'm not changing translation flow in this case as well.

Signed-off-by: Sidorov, Dmitry <dmitry.sidorov@intel.com>
  • Loading branch information
MrSidims committed Feb 19, 2024
1 parent c3dc6b8 commit d0f3a4f
Show file tree
Hide file tree
Showing 8 changed files with 472 additions and 12 deletions.
29 changes: 17 additions & 12 deletions lib/SPIRV/SPIRVToLLVMDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) {
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
DIType *BaseTy =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
size_t TotalCount = 1;
SmallVector<llvm::Metadata *, 8> Subscripts;
// Ops looks like: { BaseType, count1|upperBound1, count2|upperBound2, ...,
Expand Down Expand Up @@ -418,7 +418,7 @@ SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) {
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
DIType *BaseTy =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
size_t TotalCount = 1;
SmallVector<llvm::Metadata *, 8> Subscripts;
if (DebugInst->getExtOp() == SPIRVDebug::TypeArray) {
Expand All @@ -442,7 +442,7 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) {
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
DIType *BaseTy =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
size_t TotalCount = 1;
SmallVector<llvm::Metadata *, 8> Subscripts;
for (size_t I = SubrangesIdx; I < Ops.size(); ++I) {
Expand Down Expand Up @@ -485,7 +485,7 @@ SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) {
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
DIType *BaseTy =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
SPIRVWord Count = getConstantValueOrLiteral(Ops, ComponentCountIdx,
DebugInst->getExtSetKind());
// FIXME: The current design of SPIR-V Debug Info doesn't provide a field
Expand Down Expand Up @@ -692,8 +692,7 @@ SPIRVToLLVMDbgTran::transTypeMemberOpenCL(const SPIRVExtInst *DebugInst) {
getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
StringRef Name = getString(Ops[NameIdx]);
DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx]));
DIType *BaseType =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DIType *BaseType = transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
uint64_t OffsetInBits =
BM->get<SPIRVConstant>(Ops[OffsetIdx])->getZExtIntValue();
SPIRVWord SPIRVFlags =
Expand Down Expand Up @@ -739,8 +738,7 @@ SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst,
SPIRVWord LineNo =
getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
StringRef Name = getString(Ops[NameIdx]);
DIType *BaseType =
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DIType *BaseType = transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
uint64_t OffsetInBits =
BM->get<SPIRVConstant>(Ops[OffsetIdx])->getZExtIntValue();
SPIRVWord SPIRVFlags =
Expand Down Expand Up @@ -847,9 +845,9 @@ SPIRVToLLVMDbgTran::transTypePtrToMember(const SPIRVExtInst *DebugInst) {
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() >= OperandCount && "Invalid number of operands");
SPIRVExtInst *Member = BM->get<SPIRVExtInst>(Ops[MemberTypeIdx]);
DIType *PointeeTy = transDebugInst<DIType>(Member);
DIType *PointeeTy = transNonNullDebugType(Member);
SPIRVExtInst *ContainingTy = BM->get<SPIRVExtInst>(Ops[ParentIdx]);
DIType *BaseTy = transDebugInst<DIType>(ContainingTy);
DIType *BaseTy = transNonNullDebugType(ContainingTy);
return getDIBuilder(DebugInst).createMemberPointerType(PointeeTy, BaseTy, 0);
}

Expand Down Expand Up @@ -1110,7 +1108,7 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
assert(Ops.size() >= MinOperandCount && "Invalid number of operands");

StringRef Name = getString(Ops[NameIdx]);
DIType *Ty = transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DIType *Ty = transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DIFile *File = getFile(Ops[SourceIdx]);
SPIRVWord LineNo =
getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
Expand Down Expand Up @@ -1176,7 +1174,7 @@ DINode *SPIRVToLLVMDbgTran::transLocalVariable(const SPIRVExtInst *DebugInst) {
DIFile *File = getFile(Ops[SourceIdx]);
SPIRVWord LineNo =
getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
DIType *Ty = transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DIType *Ty = transNonNullDebugType(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
DINode::DIFlags Flags = DINode::FlagZero;
SPIRVWord SPIRVFlags =
getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
Expand Down Expand Up @@ -1406,6 +1404,13 @@ MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) {
return getDIBuilder(DebugInst).createExpression(Addr);
}

DIType *
SPIRVToLLVMDbgTran::transNonNullDebugType(const SPIRVExtInst *DebugInst) {
if (DebugInst->getExtOp() != SPIRVDebug::DebugInfoNone)
return transDebugInst<DIType>(DebugInst);
return getDIBuilder(DebugInst).createUnspecifiedType("SPIRV unknown type");
}

MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) {
switch (DebugInst->getExtOp()) {
case SPIRVDebug::DebugInfoNone:
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/SPIRVToLLVMDbgTran.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class SPIRVToLLVMDbgTran {
DebugInstCache[DebugInst] = Res;
return static_cast<T *>(Res);
}

Instruction *transDebugIntrinsic(const SPIRVExtInst *DebugInst,
BasicBlock *BB);
void finalize();
Expand All @@ -98,6 +99,8 @@ class SPIRVToLLVMDbgTran {

MDNode *transDebugInstImpl(const SPIRVExtInst *DebugInst);

DIType *transNonNullDebugType(const SPIRVExtInst *DebugInst);

llvm::DebugLoc transDebugLocation(const SPIRVExtInst *DebugInst);

llvm::DebugLoc transDebugScope(const SPIRVInstruction *Inst);
Expand Down
54 changes: 54 additions & 0 deletions test/DebugInfo/DebugInfoGlobalVariableNone.spvasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
; Tests translation of GlobalVariable with DebugInfoNone type

; REQUIRES: spirv-as

; RUN: spirv-as %s --target-env spv1.1 -o %t.spv
; RUN: llvm-spirv -r -o %t.rev.bc %t.spv
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM

; CHECK-LLVM: distinct !DIGlobalVariable(name: "i", linkageName: "_ZL1i", scope: ![[#]], file: ![[#]], line: 1, type: ![[#Type:]], isLocal: true, isDefinition: true)
; CHECK-LLVM: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "SPIRV unknown type")

; SPIR-V
; Version: 1.1
; Generator: Khronos LLVM/SPIR-V Translator; 14
; Bound: 24
; Schema: 0
OpCapability Addresses
OpCapability Linkage
OpCapability Kernel
%1 = OpExtInstImport "OpenCL.std"
%2 = OpExtInstImport "OpenCL.DebugInfo.100"
OpMemoryModel Physical64 OpenCL
%8 = OpString "/tmp/global.cpp"
%13 = OpString "int"
%17 = OpString "main"
%18 = OpString ""
%21 = OpString "i"
%22 = OpString "_ZL1i"
OpSource Unknown 0
OpName %main "main"
OpName %entry "entry"
OpModuleProcessed "Debuginfoproducer:clangversion3.4"
OpDecorate %main LinkageAttributes "main" Export
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%uint_32 = OpConstant %uint 32
%4 = OpTypeFunction %uint
%void = OpTypeVoid
%10 = OpExtInst %void %2 DebugInfoNone
%11 = OpExtInst %void %2 DebugSource %8
%12 = OpExtInst %void %2 DebugCompilationUnit 65536 3 %11 CPP_for_OpenCL
%15 = OpExtInst %void %2 DebugTypeBasic %13 %uint_32 Signed
%16 = OpExtInst %void %2 DebugTypeFunction None %15
%19 = OpExtInst %void %2 DebugInfoNone
%20 = OpExtInst %void %2 DebugFunction %17 %16 %11 2 0 %12 %18 FlagIsDefinition|FlagPrototyped|FlagIsOptimized 2 %main %19
%23 = OpExtInst %void %2 DebugGlobalVariable %21 %10 %11 1 0 %12 %22 %19 FlagIsLocal|FlagIsDefinition
%main = OpFunction %uint None %4
%entry = OpLabel
%24 = OpExtInst %void %2 DebugScope %20
OpLine %8 4 0
OpReturnValue %uint_0
OpFunctionEnd

90 changes: 90 additions & 0 deletions test/DebugInfo/DebugInfoTypeInheritance.spvasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
; Tests translation of DebugTypeInheritance and DebugLocalVariable with
; DebugInfoNone type

; REQUIRES: spirv-as

; RUN: spirv-as %s --target-env spv1.1 -o %t.spv
; RUN: llvm-spirv -r -o %t.rev.bc %t.spv
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM

; CHECK-LLVM: DILocalVariable(name: "c", scope: !9, file: !3, line: 7, type: ![[#Type:]])
; CHECK-LLVM: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "SPIRV unknown type")
; CHECK-LLVM-NOT: DW_TAG_inheritance

; SPIR-V
; Version: 1.0
; Generator: Khronos LLVM/SPIR-V Translator; 14
; Bound: 62
; Schema: 0
OpCapability Addresses
OpCapability Linkage
OpCapability Kernel
OpCapability Int8
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "OpenCL.std"
%2 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Physical64 OpenCL
%15 = OpString "/app/example.cpp"
%17 = OpString "0"
%20 = OpString ""
%26 = OpString "int"
%31 = OpString "_ZTS1C"
%32 = OpString "C"
%35 = OpString "_ZTS1B"
%36 = OpString "B"
%38 = OpString "_ZTS1A"
%39 = OpString "A"
%48 = OpString "foo"
%49 = OpString "_Z3foov"
%53 = OpString "c"
OpSource Unknown 0
OpName %_Z3foov "_Z3foov"
OpName %class_C "class.C"
OpDecorate %_Z3foov LinkageAttributes "_Z3foov" Export
OpDecorate %10 Alignment 1
%uint = OpTypeInt 32 0
%uchar = OpTypeInt 8 0
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%uint_65536 = OpConstant %uint 65536
%uint_4 = OpConstant %uint 4
%uint_6 = OpConstant %uint 6
%uint_32 = OpConstant %uint 32
%uint_8 = OpConstant %uint 8
%uint_32768 = OpConstant %uint 32768
%uint_3 = OpConstant %uint 3
%uint_2 = OpConstant %uint 2
%uint_136 = OpConstant %uint 136
%uint_7 = OpConstant %uint 7
%uint_11 = OpConstant %uint 11
%uint_12 = OpConstant %uint 12
%4 = OpTypeFunction %uint
%class_C = OpTypeStruct %uchar
%_ptr_Function_class_C = OpTypePointer Function %class_C
%void = OpTypeVoid
%12 = OpExtInst %void %2 DebugInfoNone
%16 = OpExtInst %void %2 DebugSource %15
%19 = OpExtInst %void %2 DebugBuildIdentifier %17 %uint_1
%21 = OpExtInst %void %2 DebugStoragePath %20
%25 = OpExtInst %void %2 DebugCompilationUnit %uint_65536 %uint_4 %16 %uint_6
%28 = OpExtInst %void %2 DebugTypeBasic %26 %uint_32 %uint_4 %12
%29 = OpExtInst %void %2 DebugTypeFunction %uint_0 %28
%37 = OpExtInst %void %2 DebugTypeComposite %39 %uint_0 %16 %uint_1 %uint_0 %25 %38 %uint_8 %uint_32768
%43 = OpExtInst %void %2 DebugTypeInheritance %37 %uint_0 %uint_0 %uint_3
%34 = OpExtInst %void %2 DebugTypeComposite %36 %uint_0 %16 %uint_2 %uint_0 %25 %35 %uint_8 %uint_32768 %43
%46 = OpExtInst %void %2 DebugTypeInheritance %34 %uint_0 %uint_0 %uint_3
%30 = OpExtInst %void %2 DebugTypeComposite %32 %uint_0 %16 %uint_3 %uint_0 %25 %31 %uint_8 %uint_32768 %46
%51 = OpExtInst %void %2 DebugFunction %48 %29 %16 %uint_4 %uint_0 %25 %49 %uint_136 %uint_4 %12
%55 = OpExtInst %void %2 DebugLocalVariable %53 %12 %16 %uint_7 %uint_0 %51 %uint_0
%56 = OpExtInst %void %2 DebugExpression
%_Z3foov = OpFunction %uint DontInline %4
%6 = OpLabel
%52 = OpExtInst %void %2 DebugFunctionDefinition %51 %_Z3foov
%10 = OpVariable %_ptr_Function_class_C Function
%57 = OpExtInst %void %2 DebugScope %51
%60 = OpExtInst %void %2 DebugLine %15 %uint_7 %uint_7 %uint_11 %uint_12
%13 = OpExtInst %void %2 DebugDeclare %55 %10 %56
%61 = OpExtInst %void %2 DebugLine %15 %uint_8 %uint_8 %uint_3 %uint_4
OpReturnValue %uint_0
OpFunctionEnd
60 changes: 60 additions & 0 deletions test/DebugInfo/DebugInfoTypePtrToMember.spvasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
; Tests translation of DebugTypePtrToMember DebugInfoNone type

; REQUIRES: spirv-as

; RUN: spirv-as %s --target-env spv1.1 -o %t.spv
; RUN: llvm-spirv -r -o %t.rev.bc %t.spv
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM

; CHECK-LLVM: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[#Type:]]
; CHECK-LLVM: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "SPIRV unknown type")

; SPIR-V
; Version: 1.0
; Generator: Khronos LLVM/SPIR-V Translator; 14
; Bound: 35
; Schema: 0
OpCapability Addresses
OpCapability Linkage
OpCapability Kernel
OpCapability Int64
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "OpenCL.std"
%2 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Physical64 OpenCL
%7 = OpString "./foo.cpp"
%10 = OpString "0"
%14 = OpString ""
%20 = OpString "int"
%26 = OpString "_ZTS3Foo"
%27 = OpString "Foo"
%32 = OpString "x"
OpSource Unknown 0
OpName %x "x"
OpDecorate %x LinkageAttributes "x" Export
OpDecorate %x Alignment 8
%ulong = OpTypeInt 64 0
%uint = OpTypeInt 32 0
%ulong_18446744073709551615 = OpConstant %ulong 18446744073709551615
%uint_1 = OpConstant %uint 1
%uint_65536 = OpConstant %uint 65536
%uint_2 = OpConstant %uint 2
%uint_6 = OpConstant %uint 6
%uint_32 = OpConstant %uint 32
%uint_4 = OpConstant %uint 4
%uint_0 = OpConstant %uint 0
%uint_16 = OpConstant %uint 16
%uint_8 = OpConstant %uint 8
%_ptr_CrossWorkgroup_ulong = OpTypePointer CrossWorkgroup %ulong
%void = OpTypeVoid
%x = OpVariable %_ptr_CrossWorkgroup_ulong CrossWorkgroup %ulong_18446744073709551615
%9 = OpExtInst %void %2 DebugSource %7
%13 = OpExtInst %void %2 DebugBuildIdentifier %10 %uint_1
%15 = OpExtInst %void %2 DebugStoragePath %14
%19 = OpExtInst %void %2 DebugCompilationUnit %uint_65536 %uint_2 %9 %uint_6
%23 = OpExtInst %void %2 DebugInfoNone
%24 = OpExtInst %void %2 DebugTypeBasic %20 %uint_32 %uint_4 %23
%25 = OpExtInst %void %2 DebugTypeComposite %27 %uint_1 %9 %uint_1 %uint_0 %19 %26 %uint_0 %uint_16
%31 = OpExtInst %void %2 DebugTypePtrToMember %23 %25
%34 = OpExtInst %void %2 DebugGlobalVariable %32 %31 %9 %uint_4 %uint_0 %19 %14 %x %uint_8
Loading

0 comments on commit d0f3a4f

Please sign in to comment.