Skip to content

Commit 3a22cf9

Browse files
authored
[CFIFixup] Fixup CFI for split functions with synchronous uwtables (#125299)
- **Precommit tests for synchronous uwtable CFI fixup** - **[CFIFixup] Fixup CFI for split functions with synchronous uwtables** Commit 6e54fcc disables CFI fixup for functions with synchronous tables, breaking CFI for split functions. Instead, we can disable *block-level* CFI fixup for functions with synchronous tables. Unwind tables can be: - N/A (not present) - Asynchronous - Synchronous Functions without unwind tables don't need CFI fixup (since they don't care about CFI). Functions with asynchronous unwind tables must be accurate for each basic block, so full CFI fixup is necessary. Functions with synchronous unwind tables only need to be accurate for each function (specifically, the portion of a function in a given section). Disabling CFI fixup entirely for functions with synchronous uwtables may break CFI for a function split between two sections. The portion in the first section may have valid CFI, while the portion in the second section is missing a call frame. Ex: ``` (.text.hot) Foo (BB1): <Call frame information> ... BB2: ... (.text.split) BB3: ... BB4: <epilogue> ``` Even if `Foo` has a synchronous unwind table, we still need to insert call frame information into `BB3` so that unwinding the call stack from `BB3` or `BB4` works properly.
1 parent 376f65d commit 3a22cf9

File tree

6 files changed

+212
-5
lines changed

6 files changed

+212
-5
lines changed

llvm/include/llvm/CodeGen/TargetFrameLowering.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,17 @@ class TargetFrameLowering {
229229

230230
/// Returns true if we may need to fix the unwind information for the
231231
/// function.
232-
virtual bool enableCFIFixup(MachineFunction &MF) const;
232+
virtual bool enableCFIFixup(const MachineFunction &MF) const;
233+
234+
/// enableFullCFIFixup - Returns true if we may need to fix the unwind
235+
/// information such that it is accurate for *every* instruction in the
236+
/// function (e.g. if the function has an async unwind table).
237+
virtual bool enableFullCFIFixup(const MachineFunction &MF) const {
238+
return enableCFIFixup(MF);
239+
};
233240

234241
/// Emit CFI instructions that recreate the state of the unwind information
235-
/// upon fucntion entry.
242+
/// upon function entry.
236243
virtual void resetCFIToInitialState(MachineBasicBlock &MBB) const {}
237244

238245
/// Replace a StackProbe stub (if any) with the actual probe code inline

llvm/lib/CodeGen/CFIFixup.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#include "llvm/CodeGen/TargetSubtargetInfo.h"
8181
#include "llvm/MC/MCAsmInfo.h"
8282
#include "llvm/MC/MCDwarf.h"
83+
#include "llvm/Support/CodeGen.h"
8384
#include "llvm/Target/TargetMachine.h"
8485

8586
#include <iterator>
@@ -252,6 +253,11 @@ fixupBlock(MachineBasicBlock &CurrBB, const BlockFlagsVector &BlockInfo,
252253
if (!Info.Reachable)
253254
return false;
254255

256+
// If we don't need to perform full CFI fix up, we only need to fix up the
257+
// first basic block in the section.
258+
if (!TFL.enableFullCFIFixup(MF) && !CurrBB.isBeginSection())
259+
return false;
260+
255261
// If the previous block and the current block are in the same section,
256262
// the frame info will propagate from the previous block to the current one.
257263
const BlockFlags &PrevInfo =

llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const
3535
return false;
3636
}
3737

38-
bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const {
38+
bool TargetFrameLowering::enableCFIFixup(const MachineFunction &MF) const {
3939
return MF.needsFrameMoves() &&
4040
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
4141
}

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2612,8 +2612,13 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
26122612
}
26132613
}
26142614

2615-
bool AArch64FrameLowering::enableCFIFixup(MachineFunction &MF) const {
2615+
bool AArch64FrameLowering::enableCFIFixup(const MachineFunction &MF) const {
26162616
return TargetFrameLowering::enableCFIFixup(MF) &&
2617+
MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
2618+
}
2619+
2620+
bool AArch64FrameLowering::enableFullCFIFixup(const MachineFunction &MF) const {
2621+
return enableCFIFixup(MF) &&
26172622
MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF);
26182623
}
26192624

llvm/lib/Target/AArch64/AArch64FrameLowering.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ class AArch64FrameLowering : public TargetFrameLowering {
3636
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
3737
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
3838

39-
bool enableCFIFixup(MachineFunction &MF) const override;
39+
bool enableCFIFixup(const MachineFunction &MF) const override;
40+
41+
bool enableFullCFIFixup(const MachineFunction &MF) const override;
4042

4143
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
4244

llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,19 @@
1010
ret i32 0
1111
}
1212

13+
define i32 @f1(i32 %x) #1 {
14+
entry: br label %return
15+
if.end: br label %return
16+
if.then2: br label %return
17+
if.else: br label %return
18+
return:
19+
ret i32 0
20+
}
21+
1322
declare i32 @g(i32)
1423

1524
attributes #0 = { nounwind shadowcallstack uwtable "sign-return-address"="non-leaf" "target-features"="+reserve-x18" }
25+
attributes #1 = { nounwind shadowcallstack uwtable(sync) "sign-return-address"="non-leaf" "target-features"="+reserve-x18" }
1626

1727
...
1828
---
@@ -197,4 +207,181 @@ body: |
197207
B %bb.7
198208
199209
210+
...
211+
---
212+
name: f1
213+
alignment: 4
214+
exposesReturnsTwice: false
215+
legalized: false
216+
regBankSelected: false
217+
selected: false
218+
failedISel: false
219+
tracksRegLiveness: true
220+
hasWinCFI: false
221+
failsVerification: false
222+
registers: []
223+
liveins:
224+
- { reg: '$w0', virtual-reg: '' }
225+
frameInfo:
226+
isFrameAddressTaken: false
227+
isReturnAddressTaken: false
228+
hasStackMap: false
229+
hasPatchPoint: false
230+
stackSize: 16
231+
offsetAdjustment: 0
232+
maxAlignment: 16
233+
adjustsStack: true
234+
hasCalls: true
235+
stackProtector: ''
236+
maxCallFrameSize: 0
237+
cvBytesOfCalleeSavedRegisters: 0
238+
hasOpaqueSPAdjustment: false
239+
hasVAStart: false
240+
hasMustTailInVarArgFunc: false
241+
hasTailCall: false
242+
localFrameSize: 0
243+
savePoint: ''
244+
restorePoint: ''
245+
fixedStack: []
246+
stack:
247+
- { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16,
248+
stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true,
249+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
250+
callSites: []
251+
debugValueSubstitutions: []
252+
constants: []
253+
body: |
254+
; CHECK-LABEL: name: f1
255+
; CHECK: bb.0.entry:
256+
; CHECK-NEXT: successors: %bb.4(0x30000000), %bb.1(0x50000000)
257+
; CHECK-NEXT: liveins: $w0, $lr, $x18
258+
; CHECK-NEXT: {{ $}}
259+
; CHECK-NEXT: CBZW renamable $w0, %bb.4
260+
; CHECK-NEXT: {{ $}}
261+
; CHECK-NEXT: bb.1.if.end:
262+
; CHECK-NEXT: successors: %bb.3(0x30000000), %bb.2(0x50000000)
263+
; CHECK-NEXT: liveins: $w0, $lr, $x18
264+
; CHECK-NEXT: {{ $}}
265+
; CHECK-NEXT: early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8
266+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
267+
; CHECK-NEXT: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
268+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
269+
; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
270+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
271+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16
272+
; CHECK-NEXT: TBNZW renamable $w0, 31, %bb.3
273+
; CHECK-NEXT: {{ $}}
274+
; CHECK-NEXT: bb.2.if.else:
275+
; CHECK-NEXT: successors: %bb.5(0x80000000)
276+
; CHECK-NEXT: liveins: $w0
277+
; CHECK-NEXT: {{ $}}
278+
; CHECK-NEXT: renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0
279+
; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
280+
; CHECK-NEXT: renamable $w8 = MOVZWi 1, 0
281+
; CHECK-NEXT: $w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0
282+
; CHECK-NEXT: B %bb.5
283+
; CHECK-NEXT: {{ $}}
284+
; CHECK-NEXT: bb.3.if.then2 (bbsections 1):
285+
; CHECK-NEXT: successors: %bb.5(0x80000000)
286+
; CHECK-NEXT: liveins: $w0
287+
; CHECK-NEXT: {{ $}}
288+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
289+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
290+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
291+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16
292+
; CHECK-NEXT: renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0
293+
; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
294+
; CHECK-NEXT: renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0
295+
; CHECK-NEXT: B %bb.5
296+
; CHECK-NEXT: {{ $}}
297+
; CHECK-NEXT: bb.4.return:
298+
; CHECK-NEXT: liveins: $w0
299+
; CHECK-NEXT: {{ $}}
300+
; CHECK-NEXT: RET undef $lr, implicit killed $w0
301+
; CHECK-NEXT: {{ $}}
302+
; CHECK-NEXT: bb.5.return:
303+
; CHECK-NEXT: successors: %bb.7(0x80000000)
304+
; CHECK-NEXT: liveins: $w0
305+
; CHECK-NEXT: {{ $}}
306+
; CHECK-NEXT: B %bb.7
307+
; CHECK-NEXT: {{ $}}
308+
; CHECK-NEXT: bb.6.return:
309+
; CHECK-NEXT: liveins: $w0
310+
; CHECK-NEXT: {{ $}}
311+
; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
312+
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
313+
; CHECK-NEXT: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
314+
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION negate_ra_sign_state
315+
; CHECK-NEXT: early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8
316+
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w18
317+
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
318+
; CHECK-NEXT: RET undef $lr, implicit killed $w0
319+
; CHECK-NEXT: {{ $}}
320+
; CHECK-NEXT: bb.7.return:
321+
; CHECK-NEXT: successors: %bb.6(0x80000000)
322+
; CHECK-NEXT: liveins: $w0
323+
; CHECK-NEXT: {{ $}}
324+
; CHECK-NEXT: B %bb.6
325+
bb.0.entry:
326+
successors: %bb.4(0x30000000), %bb.1(0x50000000)
327+
liveins: $w0, $lr, $x18
328+
329+
CBZW renamable $w0, %bb.4
330+
331+
bb.1.if.end:
332+
successors: %bb.3(0x30000000), %bb.2(0x50000000)
333+
liveins: $w0, $lr, $x18
334+
335+
early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8
336+
frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
337+
frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
338+
frame-setup CFI_INSTRUCTION negate_ra_sign_state
339+
early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
340+
frame-setup CFI_INSTRUCTION def_cfa_offset 16
341+
frame-setup CFI_INSTRUCTION offset $w30, -16
342+
TBNZW renamable $w0, 31, %bb.3
343+
344+
bb.2.if.else:
345+
successors: %bb.5(0x80000000)
346+
liveins: $w0
347+
348+
renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0
349+
BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
350+
renamable $w8 = MOVZWi 1, 0
351+
$w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0
352+
B %bb.5
353+
354+
bb.3.if.then2 (bbsections 1):
355+
successors: %bb.5(0x80000000)
356+
liveins: $w0
357+
358+
renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0
359+
BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
360+
renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0
361+
B %bb.5
362+
363+
bb.4.return:
364+
liveins: $w0
365+
RET undef $lr, implicit killed $w0
366+
367+
bb.5.return:
368+
liveins: $w0
369+
B %bb.6
370+
371+
bb.7.return:
372+
liveins: $w0
373+
early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
374+
frame-destroy CFI_INSTRUCTION def_cfa_offset 0
375+
frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
376+
frame-destroy CFI_INSTRUCTION negate_ra_sign_state
377+
early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8
378+
frame-destroy CFI_INSTRUCTION restore $w18
379+
frame-destroy CFI_INSTRUCTION restore $w30
380+
RET undef $lr, implicit killed $w0
381+
382+
bb.6.return:
383+
liveins: $w0
384+
B %bb.7
385+
386+
200387
...

0 commit comments

Comments
 (0)