Skip to content

Commit 72d3f2a

Browse files
Merge pull request #7314 from felipepiovezan/felipe/missing_rebranch_patches
[Rebranch] Missing debug info fixes
2 parents 6a0af20 + 90ef12f commit 72d3f2a

File tree

9 files changed

+162
-35
lines changed

9 files changed

+162
-35
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,6 +2900,13 @@ class DIExpression : public MDNode {
29002900
/// DW_OP_LLVM_arg op as its first operand, or if it contains none.
29012901
bool isSingleLocationExpression() const;
29022902

2903+
/// Returns a reference to the elements contained in this expression, skipping
2904+
/// past the leading `DW_OP_LLVM_arg, 0` if one is present.
2905+
/// Similar to `convertToNonVariadicExpression`, but faster and cheaper - it
2906+
/// does not check whether the expression is a single-location expression, and
2907+
/// it returns elements rather than creating a new DIExpression.
2908+
ArrayRef<uint64_t> getSingleLocationExpressionElements() const;
2909+
29032910
/// Removes all elements from \p Expr that do not apply to an undef debug
29042911
/// value, which includes every operator that computes the value/location on
29052912
/// the DWARF stack, including any DW_OP_LLVM_arg elements (making the result
@@ -2918,6 +2925,9 @@ class DIExpression : public MDNode {
29182925
/// single debug operand at the start of the expression, then return that
29192926
/// expression in a non-variadic form by removing DW_OP_LLVM_arg from the
29202927
/// expression if it is present; otherwise returns std::nullopt.
2928+
/// See also `getSingleLocationExpressionElements` above, which skips
2929+
/// checking `isSingleLocationExpression` and returns a list of elements
2930+
/// rather than a DIExpression.
29212931
static std::optional<const DIExpression *>
29222932
convertToNonVariadicExpression(const DIExpression *Expr);
29232933

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
795795
if (Entry->isLocation()) {
796796
addVariableAddress(DV, *VariableDie, Entry->getLoc());
797797
} else if (Entry->isInt()) {
798-
auto *Expr = DV.getSingleExpression();
798+
auto *Expr = DVal->getExpression();
799799
if (Expr && Expr->getNumElements()) {
800800
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
801801
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
@@ -829,7 +829,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
829829
return Entry.isLocation() && !Entry.getLoc().getReg();
830830
}))
831831
return VariableDie;
832-
const DIExpression *Expr = DV.getSingleExpression();
832+
const DIExpression *Expr = DVal->getExpression();
833833
assert(Expr && "Variadic Debug Value must have an Expression.");
834834
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
835835
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,15 @@ const DIType *DbgVariable::getType() const {
240240
/// Get .debug_loc entry for the instruction range starting at MI.
241241
static DbgValueLoc getDebugLocValue(const MachineInstr *MI) {
242242
const DIExpression *Expr = MI->getDebugExpression();
243-
const bool IsVariadic = MI->isDebugValueList();
243+
const bool IsVariadic = !Expr->isSingleLocationExpression();
244+
// If we have a variadic debug value instruction that is equivalent to a
245+
// non-variadic instruction, then convert it to non-variadic form here.
246+
if (!IsVariadic && !MI->isNonListDebugValue()) {
247+
assert(MI->getNumDebugOperands() == 1 &&
248+
"Mismatched DIExpression and debug operands for debug instruction.");
249+
Expr = DIExpression::get(Expr->getContext(),
250+
Expr->getSingleLocationExpressionElements());
251+
}
244252
assert(MI->getNumOperands() >= 3);
245253
SmallVector<DbgValueLocEntry, 4> DbgValueLocEntries;
246254
for (const MachineOperand &Op : MI->debug_operands()) {
@@ -272,9 +280,12 @@ void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) {
272280
"Wrong inlined-at");
273281

274282
ValueLoc = std::make_unique<DbgValueLoc>(getDebugLocValue(DbgValue));
275-
if (auto *E = DbgValue->getDebugExpression())
276-
if (E->getNumElements())
277-
FrameIndexExprs.push_back({0, E});
283+
// Use the debug value's expression as a FrameIndexExpr iff it is suitable,
284+
// which requires it to be non-variadic.
285+
if (auto E = DIExpression::convertToNonVariadicExpression(
286+
DbgValue->getDebugExpression()))
287+
if ((*E)->getNumElements())
288+
FrameIndexExprs.push_back({0, *E});
278289
}
279290

280291
ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,12 @@ class DbgVariable : public DbgEntity {
209209
assert(!Value.getExpression()->isFragment() && "Fragments not supported.");
210210

211211
ValueLoc = std::make_unique<DbgValueLoc>(Value);
212-
if (auto *E = ValueLoc->getExpression())
213-
if (E->getNumElements())
214-
FrameIndexExprs.push_back({0, E});
212+
// Use the DbgValueLoc's expression as a FrameIndexExpr iff it is suitable,
213+
// which requires it to be non-variadic.
214+
if (auto E = DIExpression::convertToNonVariadicExpression(
215+
ValueLoc->getExpression()))
216+
if ((*E)->getNumElements())
217+
FrameIndexExprs.push_back({0, *E});
215218
}
216219

217220
void initializeEntryValue(MCRegister Reg, const DIExpression &Expr) {

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,8 @@ InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD,
779779
// If this variable location does not depend on any instructions or contains
780780
// any stack locations, produce it as a standard debug value instead.
781781
if (any_of(SD->getLocationOps(), IsInvalidOp) ||
782-
all_of(SD->getLocationOps(), IsNonInstrRefOp)) {
782+
all_of(SD->getLocationOps(), IsNonInstrRefOp) ||
783+
Expr->isEntryValue()) {
783784
if (SD->isVariadic())
784785
return EmitDbgValueList(SD, VRBaseMap);
785786
return EmitDbgValueFromSingleOp(SD, VRBaseMap);

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,13 +1343,17 @@ DIExpression *DIExpression::getImpl(LLVMContext &Context,
13431343
DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));
13441344
}
13451345
bool DIExpression::isEntryValue() const {
1346-
return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_LLVM_entry_value;
1346+
auto singleLocElts = getSingleLocationExpressionElements();
1347+
return singleLocElts.size() > 0 &&
1348+
singleLocElts[0] == dwarf::DW_OP_LLVM_entry_value;
13471349
}
13481350
bool DIExpression::startsWithDeref() const {
1349-
return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref;
1351+
auto singleLocElts = getSingleLocationExpressionElements();
1352+
return singleLocElts.size() > 0 && singleLocElts[0] == dwarf::DW_OP_deref;
13501353
}
13511354
bool DIExpression::isDeref() const {
1352-
return getNumElements() == 1 && startsWithDeref();
1355+
auto singleLocElts = getSingleLocationExpressionElements();
1356+
return singleLocElts.size() == 1 && singleLocElts[0] == dwarf::DW_OP_deref;
13531357
}
13541358

13551359
DIAssignID *DIAssignID::getImpl(LLVMContext &Context, StorageType Storage,
@@ -1526,14 +1530,24 @@ bool DIExpression::isSingleLocationExpression() const {
15261530

15271531
auto ExprOpBegin = expr_ops().begin();
15281532
auto ExprOpEnd = expr_ops().end();
1529-
if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg)
1533+
if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg) {
1534+
if (ExprOpBegin->getArg(0) != 0)
1535+
return false;
15301536
++ExprOpBegin;
1537+
}
15311538

15321539
return !std::any_of(ExprOpBegin, ExprOpEnd, [](auto Op) {
15331540
return Op.getOp() == dwarf::DW_OP_LLVM_arg;
15341541
});
15351542
}
15361543

1544+
ArrayRef<uint64_t> DIExpression::getSingleLocationExpressionElements() const {
1545+
if (getNumElements() < 2 || Elements[0] != dwarf::DW_OP_LLVM_arg ||
1546+
Elements[1] != 0)
1547+
return Elements;
1548+
return getElements().drop_front(2);
1549+
}
1550+
15371551
const DIExpression *
15381552
DIExpression::convertToUndefExpression(const DIExpression *Expr) {
15391553
SmallVector<uint64_t, 3> UndefOps;
@@ -1559,6 +1573,9 @@ DIExpression::convertToVariadicExpression(const DIExpression *Expr) {
15591573

15601574
std::optional<const DIExpression *>
15611575
DIExpression::convertToNonVariadicExpression(const DIExpression *Expr) {
1576+
if (!Expr)
1577+
return std::nullopt;
1578+
15621579
// Check for `isValid` covered by `isSingleLocationExpression`.
15631580
if (!Expr->isSingleLocationExpression())
15641581
return std::nullopt;
@@ -1573,9 +1590,8 @@ DIExpression::convertToNonVariadicExpression(const DIExpression *Expr) {
15731590
if (*ElementsBegin != dwarf::DW_OP_LLVM_arg)
15741591
return Expr;
15751592

1576-
SmallVector<uint64_t> NonVariadicOps(
1577-
make_range(ElementsBegin + 2, Expr->elements_end()));
1578-
return DIExpression::get(Expr->getContext(), NonVariadicOps);
1593+
return DIExpression::get(Expr->getContext(),
1594+
Expr->getElements().drop_front(2));
15791595
}
15801596

15811597
void DIExpression::canonicalizeExpressionOps(SmallVectorImpl<uint64_t> &Ops,
@@ -1646,23 +1662,25 @@ void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,
16461662
}
16471663

16481664
bool DIExpression::extractIfOffset(int64_t &Offset) const {
1649-
if (getNumElements() == 0) {
1665+
auto SingleLocElts = getSingleLocationExpressionElements();
1666+
if (SingleLocElts.size() == 0) {
16501667
Offset = 0;
16511668
return true;
16521669
}
16531670

1654-
if (getNumElements() == 2 && Elements[0] == dwarf::DW_OP_plus_uconst) {
1655-
Offset = Elements[1];
1671+
if (SingleLocElts.size() == 2 &&
1672+
SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {
1673+
Offset = SingleLocElts[1];
16561674
return true;
16571675
}
16581676

1659-
if (getNumElements() == 3 && Elements[0] == dwarf::DW_OP_constu) {
1660-
if (Elements[2] == dwarf::DW_OP_plus) {
1661-
Offset = Elements[1];
1677+
if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {
1678+
if (SingleLocElts[2] == dwarf::DW_OP_plus) {
1679+
Offset = SingleLocElts[1];
16621680
return true;
16631681
}
1664-
if (Elements[2] == dwarf::DW_OP_minus) {
1665-
Offset = -Elements[1];
1682+
if (SingleLocElts[2] == dwarf::DW_OP_minus) {
1683+
Offset = -SingleLocElts[1];
16661684
return true;
16671685
}
16681686
}
@@ -1685,18 +1703,19 @@ const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,
16851703
unsigned &AddrClass) {
16861704
// FIXME: This seems fragile. Nothing that verifies that these elements
16871705
// actually map to ops and not operands.
1706+
auto SingleLocElts = Expr->getSingleLocationExpressionElements();
16881707
const unsigned PatternSize = 4;
1689-
if (Expr->Elements.size() >= PatternSize &&
1690-
Expr->Elements[PatternSize - 4] == dwarf::DW_OP_constu &&
1691-
Expr->Elements[PatternSize - 2] == dwarf::DW_OP_swap &&
1692-
Expr->Elements[PatternSize - 1] == dwarf::DW_OP_xderef) {
1693-
AddrClass = Expr->Elements[PatternSize - 3];
1708+
if (SingleLocElts.size() >= PatternSize &&
1709+
SingleLocElts[PatternSize - 4] == dwarf::DW_OP_constu &&
1710+
SingleLocElts[PatternSize - 2] == dwarf::DW_OP_swap &&
1711+
SingleLocElts[PatternSize - 1] == dwarf::DW_OP_xderef) {
1712+
AddrClass = SingleLocElts[PatternSize - 3];
16941713

1695-
if (Expr->Elements.size() == PatternSize)
1714+
if (SingleLocElts.size() == PatternSize)
16961715
return nullptr;
1697-
return DIExpression::get(Expr->getContext(),
1698-
ArrayRef(&*Expr->Elements.begin(),
1699-
Expr->Elements.size() - PatternSize));
1716+
return DIExpression::get(
1717+
Expr->getContext(),
1718+
ArrayRef(&*SingleLocElts.begin(), SingleLocElts.size() - PatternSize));
17001719
}
17011720
return Expr;
17021721
}

llvm/test/CodeGen/AArch64/dbg-value-swift-async.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; RUN: llc --mtriple="aarch64-" -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=AARCH
22
; RUN: llc --mtriple="aarch64-" -O0 -fast-isel=false -global-isel=false -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=AARCH
33
; RUN: llc --mtriple="aarch64-" -O0 -fast-isel -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=AARCH
4+
; RUN: llc --mtriple="aarch64-" -experimental-debug-variable-locations -fast-isel=false -global-isel=false -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=AARCH
45

56
; AARCH-NOT: DBG_VALUE
67
; AARCH: DBG_VALUE $x22, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# RUN: llc %s --start-after=livedebugvalues --filetype=obj -o - \
2+
# RUN: | llvm-dwarfdump - --name=test-var -o - | FileCheck %s
3+
4+
# Test that when an entry value expression appears in a DBG_VALUE_LIST, we are
5+
# able to produce a valid entry value location in DWARF.
6+
7+
# CHECK: DW_OP_entry_value(DW_OP_reg14 R14), DW_OP_plus_uconst 0x10, DW_OP_plus_uconst 0x10, DW_OP_deref
8+
9+
--- |
10+
source_filename = "test.ll"
11+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
12+
target triple = "x86_64-apple-macosx12.1.0"
13+
14+
declare void @llvm.dbg.value(metadata, metadata, metadata)
15+
16+
define swifttailcc void @blah(ptr swiftasync %0) !dbg !15 {
17+
%use = getelementptr i8, ptr %0, i64 9
18+
call void @llvm.dbg.value(metadata ptr %0, metadata !18, metadata !DIExpression(DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 16, DW_OP_deref, DW_OP_deref)), !dbg !22
19+
%use1 = load i32, ptr null, align 4, !dbg !27
20+
%use2 = sext i32 %use1 to i64
21+
%use3 = getelementptr i8, ptr null, i64 %use2
22+
store ptr %use3, ptr %0, align 8
23+
ret void
24+
}
25+
26+
!llvm.module.flags = !{!0}
27+
!llvm.dbg.cu = !{!1}
28+
29+
!0 = !{i32 2, !"Debug Info Version", i32 3}
30+
!1 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !2, producer: "blah", isOptimized: true, flags: "blah", runtimeVersion: 5, emissionKind: FullDebug, globals: !3, imports: !9, sysroot: "blah", sdk: "blah")
31+
!2 = !DIFile(filename: "blah", directory: "blah")
32+
!3 = !{!4, !10}
33+
!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
34+
!5 = distinct !DIGlobalVariable(name: "blah", linkageName: "blah", scope: !6, file: !2, line: 49, type: !7, isLocal: true, isDefinition: true)
35+
!6 = !DIModule(scope: null, name: "blah", includePath: "blah")
36+
!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8)
37+
!8 = !DICompositeType(tag: DW_TAG_structure_type, name: "blah", scope: !6, file: !2, size: 64, elements: !9, runtimeLang: DW_LANG_Swift, identifier: "blah")
38+
!9 = !{}
39+
!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
40+
!11 = distinct !DIGlobalVariable(name: "blah", linkageName: "blah", scope: !6, file: !2, line: 44, type: !12, isLocal: false, isDefinition: true)
41+
!12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13)
42+
!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "blah", scope: !14, file: !2, size: 64, elements: !9, runtimeLang: DW_LANG_Swift, identifier: "blah")
43+
!14 = !DIModule(scope: null, name: "blah", configMacros: "blah", includePath: "blah")
44+
!15 = distinct !DISubprogram(name: "blah", linkageName: "blah", scope: !16, file: !2, line: 115, type: !17, scopeLine: 117, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !9, thrownTypes: !9)
45+
!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "blah", scope: !6, file: !2, elements: !9, runtimeLang: DW_LANG_Swift, identifier: "blah")
46+
!17 = !DISubroutineType(types: !9)
47+
!18 = !DILocalVariable(name: "test-var", arg: 1, scope: !19, file: !2, line: 95, type: !21, flags: DIFlagArtificial)
48+
!19 = distinct !DISubprogram(name: "blah", linkageName: "blah", scope: !16, file: !2, line: 95, type: !20, scopeLine: 95, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !9)
49+
!20 = distinct !DISubroutineType(types: !9)
50+
!21 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !16)
51+
!22 = !DILocation(line: 95, column: 9, scope: !19, inlinedAt: !23)
52+
!23 = distinct !DILocation(line: 0, scope: !24, inlinedAt: !25)
53+
!24 = distinct !DISubprogram(name: "blah", linkageName: "blah", scope: !16, file: !2, type: !20, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1)
54+
!25 = distinct !DILocation(line: 121, column: 36, scope: !26)
55+
!26 = distinct !DILexicalBlock(scope: !15, file: !2, line: 116, column: 7)
56+
!27 = !DILocation(line: 0, scope: !28, inlinedAt: !23)
57+
!28 = !DILexicalBlockFile(scope: !19, file: !2, discriminator: 0)
58+
59+
...
60+
---
61+
name: blah
62+
alignment: 16
63+
tracksRegLiveness: true
64+
debugInstrRef: true
65+
tracksDebugUserValues: true
66+
registers: []
67+
liveins:
68+
- { reg: '$r14', virtual-reg: '' }
69+
frameInfo:
70+
maxAlignment: 1
71+
body: |
72+
bb.0 (%ir-block.1):
73+
liveins: $r14
74+
75+
DBG_PHI $r14, 1
76+
DBG_INSTR_REF !18, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 16, DW_OP_deref, DW_OP_deref), dbg-instr-ref(1, 0), debug-location !22
77+
DBG_VALUE_LIST !18, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 16, DW_OP_deref, DW_OP_deref), $r14, debug-location !DILocation(line: 0, scope: !19, inlinedAt: !23)
78+
renamable $rax = MOVSX64rm32 $noreg, 1, $noreg, 0, $noreg, debug-location !27 :: (load (s32) from `ptr null`)
79+
MOV64mr killed renamable $r14, 1, $noreg, 0, $noreg, killed renamable $rax :: (store (s64) into %ir.0)
80+
RETI64 8
81+
82+
...

llvm/test/DebugInfo/X86/pr52584.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
; CHECK: DW_TAG
1010
define dso_local void @test() !dbg !4 {
1111
entry:
12-
call void @llvm.dbg.value(metadata !DIArgList(i128 0), metadata !7, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 127)), !dbg !12
12+
call void @llvm.dbg.value(metadata !DIArgList(i128 0), metadata !7, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 0, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 127)), !dbg !12
1313
ret void, !dbg !12
1414
}
1515

0 commit comments

Comments
 (0)