Skip to content

Commit 624e52b

Browse files
authored
[DebugInfo] Handle trailing empty blocks when seeking prologue_end spot (llvm#117320)
The optimiser will produce empty blocks that are unconditionally executed according to the CFG -- while it may not be meaningful code, and won't get a prologue_end position, we need to not crash on this input. The fault comes from assuming that there's always a next block with some instructions in it, that will eventually produce some meaningful control flow to stop at -- in the given reproducer in issue llvm#117206 this isn't true, because the function terminates with `unreachable`. Thus, I've refactored the "get next instruction logic" into a helper that'll step through all blocks and terminate if there aren't any more. Reproducer from aeubanks
1 parent 9efdebc commit 624e52b

File tree

2 files changed

+87
-24
lines changed

2 files changed

+87
-24
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,14 +2192,45 @@ findPrologueEndLoc(const MachineFunction *MF) {
21922192
// better off synthesising an early prologue_end.
21932193
auto CurBlock = MF->begin();
21942194
auto CurInst = CurBlock->begin();
2195-
while (true) {
2196-
// Skip empty blocks, in rare cases the entry can be empty.
2197-
if (CurInst == CurBlock->end()) {
2198-
++CurBlock;
2199-
CurInst = CurBlock->begin();
2200-
continue;
2195+
2196+
// Find the initial instruction, we're guaranteed one by the caller, but not
2197+
// which block it's in.
2198+
while (CurBlock->empty())
2199+
CurInst = (++CurBlock)->begin();
2200+
assert(CurInst != CurBlock->end());
2201+
2202+
// Helper function for stepping through the initial sequence of
2203+
// unconditionally executed instructions.
2204+
auto getNextInst = [&CurBlock, &CurInst, MF]() -> bool {
2205+
// We've reached the end of the block. Did we just look at a terminator?
2206+
if (CurInst->isTerminator()) {
2207+
// Some kind of "real" control flow is occurring. At the very least
2208+
// we would have to start exploring the CFG, a good signal that the
2209+
// prologue is over.
2210+
return false;
22012211
}
22022212

2213+
// If we've already fallen through into a loop, don't fall through
2214+
// further, use a backup-location.
2215+
if (CurBlock->pred_size() > 1)
2216+
return false;
2217+
2218+
// Fall-through from entry to the next block. This is common at -O0 when
2219+
// there's no initialisation in the function. Bail if we're also at the
2220+
// end of the function, or the remaining blocks have no instructions.
2221+
// Skip empty blocks, in rare cases the entry can be empty, and
2222+
// other optimisations may add empty blocks that the control flow falls
2223+
// through.
2224+
do {
2225+
++CurBlock;
2226+
if (CurBlock == MF->end())
2227+
return false;
2228+
} while (CurBlock->empty());
2229+
CurInst = CurBlock->begin();
2230+
return true;
2231+
};
2232+
2233+
while (true) {
22032234
// Check whether this non-meta instruction a good position for prologue_end.
22042235
if (!CurInst->isMetaInstruction()) {
22052236
auto FoundInst = ExamineInst(*CurInst);
@@ -2216,25 +2247,8 @@ findPrologueEndLoc(const MachineFunction *MF) {
22162247
continue;
22172248
}
22182249

2219-
// We've reached the end of the block. Did we just look at a terminator?
2220-
if (CurInst->isTerminator()) {
2221-
// Some kind of "real" control flow is occurring. At the very least
2222-
// we would have to start exploring the CFG, a good signal that the
2223-
// prologue is over.
2224-
break;
2225-
}
2226-
2227-
// If we've already fallen through into a loop, don't fall through
2228-
// further, use a backup-location.
2229-
if (CurBlock->pred_size() > 1)
2230-
break;
2231-
2232-
// Fall-through from entry to the next block. This is common at -O0 when
2233-
// there's no initialisation in the function. Bail if we're also at the
2234-
// end of the function.
2235-
if (++CurBlock == MF->end())
2250+
if (!getNextInst())
22362251
break;
2237-
CurInst = CurBlock->begin();
22382252
}
22392253

22402254
// We couldn't find any source-location, suggesting all meaningful information

llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131
# CHECK-NEXT: .LBB0_1:
3232
# CHECK-LABEL: addl %esi, %edx
3333

34+
## Second function in this file: test that we don't crash when having trailing
35+
## empty blocks and no location for a prologue. Test that a .loc is produced,
36+
## with an implicit-not check for there being no prologue_end.
37+
#
38+
# CHECK-LABEL: f:
39+
# CHECK: .loc 0 1234 0
40+
3441

3542
--- |
3643
; ModuleID = 'out2.ll'
@@ -66,6 +73,17 @@
6673
ret i32 0, !dbg !17
6774
}
6875

76+
define void @f() !dbg !18 {
77+
entry:
78+
%0 = call ptr @llvm.returnaddress(i32 0)
79+
br label %do.body
80+
81+
do.body:
82+
unreachable
83+
}
84+
85+
declare ptr @llvm.returnaddress(i32 immarg)
86+
6987
!llvm.dbg.cu = !{!2}
7088
!llvm.module.flags = !{!6, !7}
7189
!llvm.ident = !{!8}
@@ -88,6 +106,7 @@
88106
!15 = distinct !DILexicalBlock(scope: !9, file: !3, line: 4, column: 15)
89107
!16 = !DILocation(line: 6, column: 9, scope: !15)
90108
!17 = !DILocation(line: 8, column: 3, scope: !9)
109+
!18 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 37, type: !10, scopeLine: 1234, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
91110

92111
...
93112
---
@@ -132,3 +151,33 @@ body: |
132151
RET64 $eax, debug-location !17
133152
134153
...
154+
---
155+
name: f
156+
alignment: 16
157+
tracksRegLiveness: true
158+
noPhis: true
159+
isSSA: false
160+
noVRegs: true
161+
hasFakeUses: false
162+
tracksDebugUserValues: true
163+
frameInfo:
164+
stackSize: 8
165+
offsetAdjustment: -8
166+
maxAlignment: 1
167+
maxCallFrameSize: 0
168+
isCalleeSavedInfoValid: true
169+
fixedStack:
170+
- { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 }
171+
machineFunctionInfo:
172+
amxProgModel: None
173+
body: |
174+
bb.0.entry:
175+
frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
176+
frame-setup CFI_INSTRUCTION def_cfa_offset 16
177+
frame-setup CFI_INSTRUCTION offset $rbp, -16
178+
$rbp = frame-setup MOV64rr $rsp
179+
frame-setup CFI_INSTRUCTION def_cfa_register $rbp
180+
181+
bb.1.do.body:
182+
183+
...

0 commit comments

Comments
 (0)