Skip to content

Commit 692facd

Browse files
committed
[HeterogeneousDwarf] Support Dwarf register emission of subregs/sequences
This commit adds support for emitting subregisters and register sequences. This is needed for debugging -O1, since DIExpressions can now refer to these registers. Change-Id: Ic7b468a01855d3f8dc675dce4b2280625bf68574
1 parent e33b2b5 commit 692facd

File tree

3 files changed

+161
-10
lines changed

3 files changed

+161
-10
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -736,18 +736,22 @@ void DwarfExpression::addExpression(DIExpression::NewElementsRef Expr,
736736
assert(!IsPoisonedExpr && "poisoned exprs should have old elements");
737737
this->ArgLocEntries = ArgLocEntries;
738738
this->TRI = TRI;
739-
buildAST(Expr);
740-
traverse(ASTRoot.get(), ValueKind::LocationDesc);
741-
ASTRoot.reset();
742-
this->TRI = nullptr;
743-
this->ArgLocEntries = std::nullopt;
744-
739+
std::optional<DIOp::Fragment> FragOp;
745740
for (DIOp::Variant Op : Expr) {
746741
if (auto *Frag = std::get_if<DIOp::Fragment>(&Op)) {
747-
addOpPiece(Frag->getBitSize());
742+
FragOp = *Frag;
743+
IsFragment = true;
748744
break;
749745
}
750746
}
747+
buildAST(Expr);
748+
traverse(ASTRoot.get(), ValueKind::LocationDesc);
749+
if (FragOp)
750+
addOpPiece(FragOp->getBitSize());
751+
IsFragment = false;
752+
ASTRoot.reset();
753+
this->TRI = nullptr;
754+
this->ArgLocEntries = std::nullopt;
751755
}
752756

753757
/// add masking operations to stencil out a subregister.
@@ -946,11 +950,67 @@ std::optional<NewOpResult> DwarfExpression::traverse(DIOp::Arg Arg,
946950
}
947951

948952
if (Entry.isLocation()) {
949-
auto DWARFRegister = TRI->getDwarfRegNum(Entry.getLoc().getReg(), false);
950-
if (DWARFRegister < 0) {
953+
assert(DwarfRegs.empty() && "unconsumed registers?");
954+
if (!addMachineReg(*TRI, Entry.getLoc().getReg())) {
955+
DwarfRegs.clear();
951956
return std::nullopt;
952957
}
953-
addReg(DWARFRegister);
958+
959+
// addMachineReg sets DwarfRegs and SubRegister{Size,Offset}InBits. Collect
960+
// them here and reset the fields to avoid hitting any asserts.
961+
decltype(DwarfRegs) Regs;
962+
std::swap(Regs, DwarfRegs);
963+
unsigned SubRegOffset = SubRegisterOffsetInBits;
964+
unsigned SubRegSize = SubRegisterSizeInBits;
965+
SubRegisterOffsetInBits = SubRegisterSizeInBits = 0;
966+
if (SubRegOffset % 8 || SubRegSize % 8)
967+
return std::nullopt;
968+
SubRegOffset /= 8;
969+
SubRegSize /= 8;
970+
971+
if (Regs.size() == 1) {
972+
addReg(Regs[0].DwarfRegNo, Regs[0].Comment);
973+
974+
if (SubRegOffset) {
975+
emitUserOp(dwarf::DW_OP_LLVM_USER_offset_uconst);
976+
emitUnsigned(SubRegOffset);
977+
}
978+
979+
if (SubRegSize) {
980+
emitOp(dwarf::DW_OP_deref_size);
981+
emitData1(SubRegSize);
982+
return NewOpResult{Arg.getResultType(), ValueKind::Value};
983+
}
984+
985+
return NewOpResult{Arg.getResultType(), ValueKind::LocationDesc};
986+
}
987+
988+
assert(SubRegOffset == 0 && SubRegSize == 0 &&
989+
"register piece cannot apply to multiple registers");
990+
991+
// When emitting fragments, the top element on the stack might be an
992+
// incomplete composite. Push/drop a lit0 so that we don't add the registers
993+
// to the larger composite.
994+
if (IsFragment)
995+
emitOp(dwarf::DW_OP_lit0);
996+
997+
unsigned RegSize = 0;
998+
for (auto &Reg : Regs) {
999+
if (Reg.SubRegSize % 8)
1000+
return std::nullopt;
1001+
RegSize += Reg.SubRegSize;
1002+
if (Reg.DwarfRegNo >= 0)
1003+
addReg(Reg.DwarfRegNo, Reg.Comment);
1004+
emitOp(dwarf::DW_OP_piece);
1005+
emitUnsigned(Reg.SubRegSize / 8);
1006+
}
1007+
emitUserOp(dwarf::DW_OP_LLVM_USER_piece_end);
1008+
1009+
if (IsFragment) {
1010+
emitOp(dwarf::DW_OP_swap);
1011+
emitOp(dwarf::DW_OP_drop);
1012+
}
1013+
9541014
return NewOpResult{Arg.getResultType(), ValueKind::LocationDesc};
9551015
}
9561016

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ class DwarfExpression {
361361
// the expression lowers as expected. If the lowering is not supported, it
362362
// is terminated by a DW_OP_LLVM_undefined operation.
363363
bool IsImplemented = true;
364+
bool IsFragment = false;
364365

365366
/// Set when emitting a fragment/non-fragment expression that contains a
366367
/// DW_OP_LLVM_poison operation. This matters for correctness in the fragment
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# RUN: llc -O0 -x mir -mcpu=gfx900 -start-after=livedebugvalues -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
2+
3+
--- |
4+
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
5+
target triple = "amdgcn-amd-amdhsa"
6+
7+
define void @kern() #0 !dbg !9 {
8+
ret void, !dbg !16
9+
}
10+
attributes #0 = { convergent mustprogress noinline nounwind optnone "amdgpu-stack-objects" "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="gfx900" "target-features"="+16-bit-insts,+ci-insts,+dpp,+flat-address-space,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst" "uniform-work-group-size"="false" }
11+
12+
!llvm.dbg.cu = !{!0}
13+
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
14+
!llvm.ident = !{!8}
15+
16+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 19.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
17+
!1 = !DIFile(filename: "t.cpp", directory: "/")
18+
!2 = !{i32 1, !"amdhsa_code_object_version", i32 500}
19+
!3 = !{i32 7, !"Dwarf Version", i32 5}
20+
!4 = !{i32 2, !"Debug Info Version", i32 3}
21+
!5 = !{i32 1, !"wchar_size", i32 4}
22+
!6 = !{i32 8, !"PIC Level", i32 2}
23+
!7 = !{i32 7, !"frame-pointer", i32 2}
24+
!8 = !{!"clang version 19.0.0"}
25+
!9 = distinct !DISubprogram(name: "kern", linkageName: "kern", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12)
26+
!10 = !DISubroutineType(types: !11)
27+
!11 = !{}
28+
!12 = !{!17, !18, !19}
29+
!13 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
30+
!14 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
31+
!15 = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
32+
!16 = !DILocation(line: 1, column: 1, scope: !9)
33+
!17 = !DILocalVariable(name: "s_lo16", scope: !9, file: !1, line: 1, type: !13)
34+
!18 = !DILocalVariable(name: "s_hi16", scope: !9, file: !1, line: 1, type: !13)
35+
!19 = !DILocalVariable(name: "s_s", scope: !9, file: !1, line: 1, type: !15)
36+
!20 = !DILocalVariable(name: "v_lo16", scope: !9, file: !1, line: 1, type: !13)
37+
!21 = !DILocalVariable(name: "v_hi16", scope: !9, file: !1, line: 1, type: !13)
38+
!22 = !DILocalVariable(name: "v_v", scope: !9, file: !1, line: 1, type: !15)
39+
!23 = !DILocalVariable(name: "with_frags", scope: !9, file: !1, line: 1, type: !15)
40+
!24 = !DILocalVariable(name: "sgpr", scope: !9, file: !1, line: 1, type: !14)
41+
!25 = !DILocalVariable(name: "vgpr", scope: !9, file: !1, line: 1, type: !14)
42+
43+
...
44+
---
45+
name: kern
46+
body: |
47+
bb.0:
48+
49+
; CHECK: DW_AT_location (DW_OP_regx SGPR42, DW_OP_deref_size 0x2, DW_OP_stack_value)
50+
; CHECK-NEXT: DW_AT_name ("s_lo16")
51+
DBG_VALUE renamable $sgpr42_lo16, $noreg, !17, !DIExpression(DIOpArg(0, i16)), debug-location !16
52+
53+
; CHECK: DW_AT_location (DW_OP_regx SGPR42, DW_OP_LLVM_user DW_OP_LLVM_offset_uconst 0x2, DW_OP_deref_size 0x2, DW_OP_stack_value)
54+
; CHECK-NEXT: DW_AT_name ("s_hi16")
55+
DBG_VALUE renamable $sgpr42_hi16, $noreg, !18, !DIExpression(DIOpArg(0, i16)), debug-location !16
56+
57+
; CHECK: DW_AT_location (DW_OP_regx SGPR42, DW_OP_piece 0x4, DW_OP_regx SGPR43, DW_OP_piece 0x4, DW_OP_LLVM_user DW_OP_LLVM_piece_end)
58+
; CHECK-NEXT: DW_AT_name ("s_s")
59+
DBG_VALUE renamable $sgpr42_sgpr43, $noreg, !19, !DIExpression(DIOpArg(0, i64)), debug-location !16
60+
61+
; CHECK: DW_AT_location (DW_OP_regx VGPR42, DW_OP_deref_size 0x2, DW_OP_stack_value)
62+
; CHECK-NEXT: DW_AT_name ("v_lo16")
63+
DBG_VALUE renamable $vgpr42_lo16, $noreg, !20, !DIExpression(DIOpArg(0, i16)), debug-location !16
64+
65+
; CHECK: DW_AT_location (DW_OP_regx VGPR42, DW_OP_LLVM_user DW_OP_LLVM_offset_uconst 0x2, DW_OP_deref_size 0x2, DW_OP_stack_value)
66+
; CHECK-NEXT: DW_AT_name ("v_hi16")
67+
DBG_VALUE renamable $vgpr42_hi16, $noreg, !21, !DIExpression(DIOpArg(0, i16)), debug-location !16
68+
69+
; CHECK: DW_AT_location (DW_OP_regx VGPR42, DW_OP_piece 0x4, DW_OP_regx VGPR43, DW_OP_piece 0x4, DW_OP_LLVM_user DW_OP_LLVM_piece_end)
70+
; CHECK-NEXT: DW_AT_name ("v_v")
71+
DBG_VALUE renamable $vgpr42_vgpr43, $noreg, !22, !DIExpression(DIOpArg(0, i64)), debug-location !16
72+
73+
; CHECK: DW_TAG_variable
74+
; CHECK-NEXT: DW_AT_location (indexed ({{.*}}) loclist = {{.*}}:
75+
; CHECK-NEXT: [{{.*}}): DW_OP_lit0, DW_OP_regx SGPR50, DW_OP_piece 0x4, DW_OP_regx SGPR51, DW_OP_piece 0x4, DW_OP_LLVM_user DW_OP_LLVM_piece_end, DW_OP_swap, DW_OP_drop, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_regx SGPR52, DW_OP_piece 0x4, DW_OP_regx SGPR53, DW_OP_piece 0x4, DW_OP_LLVM_user DW_OP_LLVM_piece_end, DW_OP_swap, DW_OP_drop, DW_OP_piece 0x4)
76+
; CHECK-NEXT: DW_AT_name ("with_frags")
77+
DBG_VALUE renamable $sgpr50_sgpr51, $noreg, !23, !DIExpression(DIOpArg(0, i64), DIOpFragment(0, 32)), debug-location !16
78+
DBG_VALUE renamable $sgpr52_sgpr53, $noreg, !23, !DIExpression(DIOpArg(0, i64), DIOpFragment(32, 32)), debug-location !16
79+
80+
; CHECK: DW_AT_location (DW_OP_regx SGPR100)
81+
; CHECK-NEXT: DW_AT_name ("sgpr")
82+
DBG_VALUE $sgpr100, $noreg, !24, !DIExpression(DIOpArg(0, i32)), debug-location !16
83+
84+
; CHECK: DW_AT_location (DW_OP_regx VGPR100)
85+
; CHECK-NEXT: ("vgpr")
86+
DBG_VALUE $vgpr100, $noreg, !25, !DIExpression(DIOpArg(0, i32)), debug-location !16
87+
88+
S_ENDPGM 0, debug-location !16
89+
90+
...

0 commit comments

Comments
 (0)