Skip to content

Commit a89ca4a

Browse files
author
Thomas Preud'homme
committed
Fix PR44001: assert failure in getFunctionLocalOffsetAfterInsn
Summary: Assert in getFunctionLocalOffsetAfterInsn() fails when processing a call MachineInstr inside a bundle and compiling with debug info. This is because labels are added by DwarfDebug::beginInstruction() which is called for each top-level MI by EmitFunctionBody()'s for-loop iteration but constructCallSiteEntryDIEs() which calls getFunctionLocalOffsetAfterInsn() iterates over all MIs. This commit modifies constructCallSiteEntryDIEs() to get the associated bundle MI for call MIs inside a bundle and use that to when calling getFunctionLocalOffsetAfterInsn() and getLabelAfterInsn(). It also skips loop iterations for bundle MIs since the loop statements are concerned with debug info for each physical instructions and bundles represent a group of instructions. It also fix the comment about PCAddr since the code is getting the return address and not the call address. Reviewers: dstenb, vsk, aprantl, djtodoro, dblaikie, NikolaPrica Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70293
1 parent 7deb8ce commit a89ca4a

File tree

2 files changed

+100
-6
lines changed

2 files changed

+100
-6
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,12 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
714714
// Emit call site entries for each call or tail call in the function.
715715
for (const MachineBasicBlock &MBB : MF) {
716716
for (const MachineInstr &MI : MBB.instrs()) {
717+
// Bundles with call in them will pass the isCall() test below but do not
718+
// have callee operand information so skip them here. Iterator will
719+
// eventually reach the call MI.
720+
if (MI.isBundle())
721+
continue;
722+
717723
// Skip instructions which aren't calls. Both calls and tail-calling jump
718724
// instructions (e.g TAILJMPd64) are classified correctly here.
719725
if (!MI.isCall())
@@ -748,19 +754,28 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
748754

749755
bool IsTail = TII->isTailCall(MI);
750756

757+
// If MI is in a bundle, the label was created after the bundle since
758+
// EmitFunctionBody iterates over top-level MIs. Get that top-level MI
759+
// to search for that label below.
760+
const MachineInstr *TopLevelCallMI =
761+
MI.isInsideBundle() ? &*getBundleStart(MI.getIterator()) : &MI;
762+
751763
// For tail calls, for non-gdb tuning, no return PC information is needed.
752764
// For regular calls (and tail calls in GDB tuning), the return PC
753765
// is needed to disambiguate paths in the call graph which could lead to
754766
// some target function.
755767
const MCExpr *PCOffset =
756-
(IsTail && !tuneForGDB()) ? nullptr
757-
: getFunctionLocalOffsetAfterInsn(&MI);
768+
(IsTail && !tuneForGDB())
769+
? nullptr
770+
: getFunctionLocalOffsetAfterInsn(TopLevelCallMI);
758771

759-
// Address of a call-like instruction for a normal call or a jump-like
760-
// instruction for a tail call. This is needed for GDB + DWARF 4 tuning.
772+
// Return address of a call-like instruction for a normal call or a
773+
// jump-like instruction for a tail call. This is needed for
774+
// GDB + DWARF 4 tuning.
761775
const MCSymbol *PCAddr =
762-
ApplyGNUExtensions ? const_cast<MCSymbol*>(getLabelAfterInsn(&MI))
763-
: nullptr;
776+
ApplyGNUExtensions
777+
? const_cast<MCSymbol *>(getLabelAfterInsn(TopLevelCallMI))
778+
: nullptr;
764779

765780
assert((IsTail || PCOffset || PCAddr) &&
766781
"Call without return PC information");
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# RUN: llc -filetype=obj -start-after=patchable-function -O3 %s -o - | llvm-dwarfdump -v - | FileCheck %s
2+
3+
# CHECK-LABEL: .debug_info contents:
4+
5+
# CHECK-LABEL: DW_TAG_GNU_call_site
6+
# CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x[[BAR_ADDR:[0-9a-f]+]] => {0x{{0*}}[[BAR_ADDR]]} "bar")
7+
# CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000008 ".text")
8+
9+
--- |
10+
; ModuleID = 'bundled-call-pr44001.ll'
11+
source_filename = "bundled-call-pr44001.c"
12+
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
13+
target triple = "hexagon-unknown-unknown-elf"
14+
15+
define dso_local i32 @foo(i32 %cond) local_unnamed_addr !dbg !12 {
16+
entry:
17+
call void @llvm.dbg.value(metadata i32 %cond, metadata !14, metadata !DIExpression()), !dbg !15
18+
%call = tail call i32 @bar(i32 %cond), !dbg !16
19+
%add = add nsw i32 %call, 1, !dbg !17
20+
ret i32 %add, !dbg !18
21+
}
22+
23+
declare !dbg !4 dso_local i32 @bar(i32) local_unnamed_addr
24+
25+
; Function Attrs: nounwind readnone speculatable willreturn
26+
declare void @llvm.dbg.value(metadata, metadata, metadata)
27+
28+
!llvm.dbg.cu = !{!0}
29+
!llvm.module.flags = !{!8, !9, !10}
30+
!llvm.ident = !{!11}
31+
32+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
33+
!1 = !DIFile(filename: "bundled-call-pr44001.ll", directory: "/")
34+
!2 = !{}
35+
!3 = !{!4}
36+
!4 = !DISubprogram(name: "bar", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
37+
!5 = !DISubroutineType(types: !6)
38+
!6 = !{!7, !7}
39+
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
40+
!8 = !{i32 2, !"Dwarf Version", i32 4}
41+
!9 = !{i32 2, !"Debug Info Version", i32 3}
42+
!10 = !{i32 1, !"wchar_size", i32 4}
43+
!11 = !{!"clang version 10.0.0"}
44+
!12 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, type: !5, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
45+
!13 = !{!14}
46+
!14 = !DILocalVariable(name: "cond", arg: 1, scope: !12, file: !1, line: 4, type: !7)
47+
!15 = !DILocation(line: 0, scope: !12)
48+
!16 = !DILocation(line: 5, column: 10, scope: !12)
49+
!17 = !DILocation(line: 5, column: 20, scope: !12)
50+
!18 = !DILocation(line: 5, column: 3, scope: !12)
51+
52+
...
53+
---
54+
name: foo
55+
alignment: 16
56+
tracksRegLiveness: true
57+
frameInfo:
58+
maxAlignment: 1
59+
adjustsStack: true
60+
hasCalls: true
61+
maxCallFrameSize: 0
62+
machineFunctionInfo: {}
63+
body: |
64+
bb.0.entry:
65+
liveins: $r0
66+
67+
DBG_VALUE $r0, $noreg, !14, !DIExpression(), debug-location !15
68+
DBG_VALUE $r0, $noreg, !14, !DIExpression(), debug-location !15
69+
DBG_VALUE $r0, $noreg, !14, !DIExpression(), debug-location !15
70+
BUNDLE implicit-def $r29, implicit-def $r30, implicit-def dead $pc, implicit-def dead $r31, implicit-def $r0, implicit $r29, implicit killed $framekey, implicit killed $framelimit, implicit killed $r30, implicit killed $r31, implicit $r0, debug-location !16 {
71+
$r29 = S2_allocframe $r29, 0, implicit-def $r30, implicit killed $framekey, implicit killed $framelimit, implicit killed $r30, implicit killed $r31, debug-location !16 :: (store 4 into stack)
72+
J2_call @bar, hexagoncsr, implicit-def dead $pc, implicit-def dead $r31, implicit internal killed $r29, implicit $r0, implicit-def $r29, implicit-def $r0, debug-location !16
73+
}
74+
BUNDLE implicit-def dead $r0, implicit-def $d15, implicit-def $r30, implicit-def $r31, implicit-def $pc, implicit-def $r29, implicit $r0, implicit killed $r30, implicit killed $framekey, debug-location !17 {
75+
renamable $r0 = nsw A2_addi renamable $r0, 1, debug-location !17
76+
$d15 = L4_return killed $r30, implicit-def $pc, implicit-def $r29, implicit killed $framekey, implicit-def dead $pc, implicit internal killed $r0, debug-location !18
77+
}
78+
79+
...

0 commit comments

Comments
 (0)