Skip to content

Commit 9edf714

Browse files
authored
[DebugInfo] Preserve DIExpression in DIGlobalVariableExpression (#2285)
Preserve DIExpression in DIGlobalVariableExpression. Preserving DIExpressions is necessary because of this change in LLVM: commit 638a8393615e911b729d5662096f60ef49f1c65e Author: Michael Buch [email protected] Date: Mon Nov 13 06:04:27 2023 +0000 Reland "[clang][DebugInfo] Emit global variable definitions for static data members with constant initializers" (#71780)
1 parent 346b4cd commit 9edf714

File tree

4 files changed

+135
-10
lines changed

4 files changed

+135
-10
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,23 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) {
11851185
if (DIDerivedType *StaticMember = GV->getStaticDataMemberDeclaration())
11861186
Ops.push_back(transDbgEntry(StaticMember)->getId());
11871187

1188+
// Check if Ops[VariableIdx] has no information
1189+
if (Ops[VariableIdx] == getDebugInfoNoneId()) {
1190+
// Check if GV has an associated GVE with a non-empty DIExpression.
1191+
// The non-empty DIExpression gives the initial value of the GV.
1192+
for (const DIGlobalVariableExpression *GVE : DIF.global_variables()) {
1193+
if ( // GVE matches GV
1194+
GVE->getVariable() == GV &&
1195+
// DIExpression is non-empty
1196+
GVE->getExpression()->getNumElements()) {
1197+
// Repurpose VariableIdx operand to hold the initial value held in the
1198+
// GVE's DIExpression
1199+
Ops[VariableIdx] = transDbgExpression(GVE->getExpression())->getId();
1200+
break;
1201+
}
1202+
}
1203+
}
1204+
11881205
if (isNonSemanticDebugInfo())
11891206
transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx});
11901207
return BM->addDebugInfo(SPIRVDebug::GlobalVariable, getVoidTy(), Ops);

lib/SPIRV/SPIRVToLLVMDbgTran.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,15 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11281128
StaticMemberDecl = transDebugInst<DIDerivedType>(
11291129
BM->get<SPIRVExtInst>(Ops[StaticMemberDeclarationIdx]));
11301130
}
1131+
1132+
DIExpression *DIExpr = nullptr;
1133+
// Check if Ops[VariableIdx] is not being used to hold a variable operand.
1134+
// Instead it is being used to hold an Expression that holds the initial
1135+
// value of the GlobalVariable.
1136+
if (getDbgInst<SPIRVDebug::Expression>(Ops[VariableIdx]))
1137+
DIExpr =
1138+
transDebugInst<DIExpression>(BM->get<SPIRVExtInst>(Ops[VariableIdx]));
1139+
11311140
SPIRVWord Flags =
11321141
getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
11331142
bool IsLocal = Flags & SPIRVDebug::FlagIsLocal;
@@ -1136,7 +1145,7 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11361145
if (IsDefinition) {
11371146
VarDecl = getDIBuilder(DebugInst).createGlobalVariableExpression(
11381147
Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition,
1139-
nullptr, StaticMemberDecl);
1148+
DIExpr, StaticMemberDecl);
11401149
} else {
11411150
VarDecl = getDIBuilder(DebugInst).createTempGlobalVariableFwdDecl(
11421151
Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, StaticMemberDecl);
@@ -1145,15 +1154,20 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11451154
llvm::TempMDNode TMP(VarDecl);
11461155
VarDecl = getDIBuilder(DebugInst).replaceTemporary(std::move(TMP), VarDecl);
11471156
}
1148-
// If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone.
1149-
// Otherwise Ops[VariableIdx] may be a global variable or a constant(C++
1150-
// static const).
1151-
if (VarDecl && !getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[VariableIdx])) {
1152-
SPIRVValue *V = BM->get<SPIRVValue>(Ops[VariableIdx]);
1153-
Value *Var = SPIRVReader->transValue(V, nullptr, nullptr);
1154-
llvm::GlobalVariable *GV = dyn_cast_or_null<llvm::GlobalVariable>(Var);
1155-
if (GV && !GV->hasMetadata("dbg"))
1156-
GV->addMetadata("dbg", *VarDecl);
1157+
1158+
// Ops[VariableIdx] was not used to hold an Expression with the initial value
1159+
// for the GlobalVariable
1160+
if (!DIExpr) {
1161+
// If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone.
1162+
// Otherwise Ops[VariableIdx] may be a global variable or a constant(C++
1163+
// static const).
1164+
if (VarDecl && !getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[VariableIdx])) {
1165+
SPIRVValue *V = BM->get<SPIRVValue>(Ops[VariableIdx]);
1166+
Value *Var = SPIRVReader->transValue(V, nullptr, nullptr);
1167+
llvm::GlobalVariable *GV = dyn_cast_or_null<llvm::GlobalVariable>(Var);
1168+
if (GV && !GV->hasMetadata("dbg"))
1169+
GV->addMetadata("dbg", *VarDecl);
1170+
}
11571171
}
11581172
return VarDecl;
11591173
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
;; Ensure that DIExpressions are preserved in DIGlobalVariableExpressions
2+
;; This utilizes SPIRV DebugGlobalVariable's Variable field to hold the
3+
;; DIExpression.
4+
5+
; RUN: llvm-as %s -o %t.bc
6+
7+
; RUN: llvm-spirv -o %t.100.spt %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text
8+
; RUN: FileCheck %s --input-file %t.100.spt --check-prefix CHECK-SPIRV
9+
; RUN: llvm-spirv -o %t.100.spv %t.bc --spirv-debug-info-version=nonsemantic-shader-100
10+
; RUN: llvm-spirv -r -o %t.100.rev.bc %t.100.spv
11+
; RUN: llvm-dis %t.100.rev.bc -o %t.100.rev.ll
12+
; RUN: FileCheck %s --input-file %t.100.rev.ll --check-prefix CHECK-LLVM
13+
14+
; RUN: llvm-spirv -o %t.200.spt %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text
15+
; RUN: FileCheck %s --input-file %t.200.spt --check-prefix CHECK-SPIRV
16+
; RUN: llvm-spirv -o %t.200.spv %t.bc --spirv-debug-info-version=nonsemantic-shader-200
17+
; RUN: llvm-spirv -r -o %t.200.rev.bc %t.200.spv
18+
; RUN: llvm-dis %t.200.rev.bc -o %t.200.rev.ll
19+
; RUN: FileCheck %s --input-file %t.200.rev.ll --check-prefix CHECK-LLVM
20+
21+
; CHECK-SPIRV: [[EXPRESSION:[0-9]+]] [[#]] DebugExpression [[#]] [[#]]
22+
; CHECK-SPIRV: [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[EXPRESSION]] [[#]] {{$}}
23+
24+
; CHECK-LLVM: ![[#]] = !DIGlobalVariableExpression(var: ![[#GV:]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
25+
; CHECK-LLVM: ![[#GV]] = distinct !DIGlobalVariable(name: "true", scope: ![[#]], file: ![[#]], line: 3777, type: ![[#]], isLocal: true, isDefinition: true)
26+
27+
!llvm.module.flags = !{!0, !1}
28+
!llvm.dbg.cu = !{!2}
29+
30+
!0 = !{i32 7, !"Dwarf Version", i32 4}
31+
!1 = !{i32 2, !"Debug Info Version", i32 3}
32+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang", emissionKind: FullDebug, globals: !4)
33+
!3 = !DIFile(filename: "test.cpp", directory: "/path/to")
34+
!4 = !{!5}
35+
!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
36+
!6 = distinct !DIGlobalVariable(name: "true", scope: !2, file: !3, line: 3777, type: !7, isLocal: true, isDefinition: true)
37+
!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8)
38+
!8 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
;; Ensure that DIExpressions are preserved in DIGlobalVariableExpressions
2+
;; when a Static Member Declaration is also needed.
3+
;; This utilizes SPIRV DebugGlobalVariable's Variable field to hold the
4+
;; DIExpression.
5+
6+
;; Declaration generated from:
7+
;;
8+
;; struct A {
9+
;; static int fully_specified;
10+
;; };
11+
;;
12+
;; int A::fully_specified;
13+
14+
; RUN: llvm-as %s -o %t.bc
15+
16+
; RUN: llvm-spirv -o %t.100.spt %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text
17+
; RUN: FileCheck %s --input-file %t.100.spt --check-prefix CHECK-SPIRV
18+
; RUN: llvm-spirv -o %t.100.spv %t.bc --spirv-debug-info-version=nonsemantic-shader-100
19+
; RUN: llvm-spirv -r -o %t.100.rev.bc %t.100.spv
20+
; RUN: llvm-dis %t.100.rev.bc -o %t.100.rev.ll
21+
; RUN: FileCheck %s --input-file %t.100.rev.ll --check-prefix CHECK-LLVM
22+
23+
; RUN: llvm-spirv -o %t.200.spt %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text
24+
; RUN: FileCheck %s --input-file %t.200.spt --check-prefix CHECK-SPIRV
25+
; RUN: llvm-spirv -o %t.200.spv %t.bc --spirv-debug-info-version=nonsemantic-shader-200
26+
; RUN: llvm-spirv -r -o %t.200.rev.bc %t.200.spv
27+
; RUN: llvm-dis %t.200.rev.bc -o %t.200.rev.ll
28+
; RUN: FileCheck %s --input-file %t.200.rev.ll --check-prefix CHECK-LLVM
29+
30+
; CHECK-SPIRV-DAG: [[TYPE_MEMBER:[0-9]+]] [[#]] DebugTypeMember [[#]] [[#]] [[#]] [[#]]
31+
; CHECK-SPIRV-DAG: [[EXPRESSION:[0-9]+]] [[#]] DebugExpression [[#]] [[#]]
32+
; CHECK-SPIRV: [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[EXPRESSION]] [[#]] [[TYPE_MEMBER]] {{$}}
33+
34+
; CHECK-LLVM: ![[#]] = !DIGlobalVariableExpression(var: ![[#GV:]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
35+
; CHECK-LLVM: ![[#GV]] = distinct !DIGlobalVariable(name: "true", scope: ![[#]], file: ![[#]], line: 3777, type: ![[#]], isLocal: true, isDefinition: true, declaration: ![[#DECLARATION:]])
36+
; CHECK-LLVM: ![[#DECLARATION]] = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: ![[#SCOPE:]], file: ![[#]], line: 2, baseType: ![[#BASETYPE:]], flags: DIFlagPublic | DIFlagStaticMember)
37+
; CHECK-LLVM: ![[#SCOPE]] = {{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "A", file: ![[#]], line: 1, size: 8, flags: DIFlagTypePassByValue, elements: ![[#ELEMENTS:]], identifier: "_ZTS1A")
38+
; CHECK-LLVM: ![[#ELEMENTS]] = !{![[#DECLARATION]]}
39+
; CHECK-LLVM: ![[#BASETYPE]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
40+
41+
!llvm.module.flags = !{!0, !1}
42+
!llvm.dbg.cu = !{!2}
43+
44+
!0 = !{i32 7, !"Dwarf Version", i32 4}
45+
!1 = !{i32 2, !"Debug Info Version", i32 3}
46+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang", emissionKind: FullDebug, globals: !4)
47+
!3 = !DIFile(filename: "test.cpp", directory: "/path/to")
48+
!4 = !{!5}
49+
!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
50+
!6 = distinct !DIGlobalVariable(name: "true", scope: !2, file: !3, line: 3777, type: !7, isLocal: true, isDefinition: true, declaration: !10)
51+
!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8)
52+
!8 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
53+
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
54+
!10 = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: !11, file: !3, line: 2, baseType: !9, flags: DIFlagStaticMember)
55+
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !12, identifier: "_ZTS1A")
56+
!12 = !{!10}

0 commit comments

Comments
 (0)