Skip to content

[CFIFixup] Fixup CFI for split functions with synchronous uwtables #125299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions llvm/include/llvm/CodeGen/TargetFrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,17 @@ class TargetFrameLowering {

/// Returns true if we may need to fix the unwind information for the
/// function.
virtual bool enableCFIFixup(MachineFunction &MF) const;
virtual bool enableCFIFixup(const MachineFunction &MF) const;

/// enableFullCFIFixup - Returns true if we may need to fix the unwind
/// information such that it is accurate for *every* instruction in the
/// function (e.g. if the function has an async unwind table).
virtual bool enableFullCFIFixup(const MachineFunction &MF) const {
return enableCFIFixup(MF);
};

/// Emit CFI instructions that recreate the state of the unwind information
/// upon fucntion entry.
/// upon function entry.
virtual void resetCFIToInitialState(MachineBasicBlock &MBB) const {}

/// Replace a StackProbe stub (if any) with the actual probe code inline
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/CodeGen/CFIFixup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetMachine.h"

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

// If we don't need to perform full CFI fix up, we only need to fix up the
// first basic block in the section.
if (!TFL.enableFullCFIFixup(MF) && !CurrBB.isBeginSection())
return false;

// If the previous block and the current block are in the same section,
// the frame info will propagate from the previous block to the current one.
const BlockFlags &PrevInfo =
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const
return false;
}

bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const {
bool TargetFrameLowering::enableCFIFixup(const MachineFunction &MF) const {
return MF.needsFrameMoves() &&
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
}
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2612,8 +2612,13 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
}
}

bool AArch64FrameLowering::enableCFIFixup(MachineFunction &MF) const {
bool AArch64FrameLowering::enableCFIFixup(const MachineFunction &MF) const {
return TargetFrameLowering::enableCFIFixup(MF) &&
MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
}

bool AArch64FrameLowering::enableFullCFIFixup(const MachineFunction &MF) const {
return enableCFIFixup(MF) &&
MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF);
}

Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/AArch64/AArch64FrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class AArch64FrameLowering : public TargetFrameLowering {
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;

bool enableCFIFixup(MachineFunction &MF) const override;
bool enableCFIFixup(const MachineFunction &MF) const override;

bool enableFullCFIFixup(const MachineFunction &MF) const override;

bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;

Expand Down
187 changes: 187 additions & 0 deletions llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@
ret i32 0
}

define i32 @f1(i32 %x) #1 {
entry: br label %return
if.end: br label %return
if.then2: br label %return
if.else: br label %return
return:
ret i32 0
}

declare i32 @g(i32)

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

...
---
Expand Down Expand Up @@ -197,4 +207,181 @@ body: |
B %bb.7


...
---
name: f1
alignment: 4
exposesReturnsTwice: false
legalized: false
regBankSelected: false
selected: false
failedISel: false
tracksRegLiveness: true
hasWinCFI: false
failsVerification: false
registers: []
liveins:
- { reg: '$w0', virtual-reg: '' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 16
offsetAdjustment: 0
maxAlignment: 16
adjustsStack: true
hasCalls: true
stackProtector: ''
maxCallFrameSize: 0
cvBytesOfCalleeSavedRegisters: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
hasTailCall: false
localFrameSize: 0
savePoint: ''
restorePoint: ''
fixedStack: []
stack:
- { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16,
stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true,
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
callSites: []
debugValueSubstitutions: []
constants: []
body: |
; CHECK-LABEL: name: f1
; CHECK: bb.0.entry:
; CHECK-NEXT: successors: %bb.4(0x30000000), %bb.1(0x50000000)
; CHECK-NEXT: liveins: $w0, $lr, $x18
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: CBZW renamable $w0, %bb.4
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1.if.end:
; CHECK-NEXT: successors: %bb.3(0x30000000), %bb.2(0x50000000)
; CHECK-NEXT: liveins: $w0, $lr, $x18
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8
; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
; CHECK-NEXT: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16
; CHECK-NEXT: TBNZW renamable $w0, 31, %bb.3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2.if.else:
; CHECK-NEXT: successors: %bb.5(0x80000000)
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0
; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
; CHECK-NEXT: renamable $w8 = MOVZWi 1, 0
; CHECK-NEXT: $w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0
; CHECK-NEXT: B %bb.5
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.3.if.then2 (bbsections 1):
; CHECK-NEXT: successors: %bb.5(0x80000000)
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16
; CHECK-NEXT: renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0
; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
; CHECK-NEXT: renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0
; CHECK-NEXT: B %bb.5
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.4.return:
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: RET undef $lr, implicit killed $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.5.return:
; CHECK-NEXT: successors: %bb.7(0x80000000)
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: B %bb.7
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.6.return:
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
; CHECK-NEXT: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION negate_ra_sign_state
; CHECK-NEXT: early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w18
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
; CHECK-NEXT: RET undef $lr, implicit killed $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.7.return:
; CHECK-NEXT: successors: %bb.6(0x80000000)
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: B %bb.6
bb.0.entry:
successors: %bb.4(0x30000000), %bb.1(0x50000000)
liveins: $w0, $lr, $x18

CBZW renamable $w0, %bb.4

bb.1.if.end:
successors: %bb.3(0x30000000), %bb.2(0x50000000)
liveins: $w0, $lr, $x18

early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8
frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78
frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
frame-setup CFI_INSTRUCTION negate_ra_sign_state
early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
frame-setup CFI_INSTRUCTION def_cfa_offset 16
frame-setup CFI_INSTRUCTION offset $w30, -16
TBNZW renamable $w0, 31, %bb.3

bb.2.if.else:
successors: %bb.5(0x80000000)
liveins: $w0

renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0
BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
renamable $w8 = MOVZWi 1, 0
$w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0
B %bb.5

bb.3.if.then2 (bbsections 1):
successors: %bb.5(0x80000000)
liveins: $w0

renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0
BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0
renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0
B %bb.5

bb.4.return:
liveins: $w0
RET undef $lr, implicit killed $w0

bb.5.return:
liveins: $w0
B %bb.6

bb.7.return:
liveins: $w0
early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
frame-destroy CFI_INSTRUCTION def_cfa_offset 0
frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
frame-destroy CFI_INSTRUCTION negate_ra_sign_state
early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8
frame-destroy CFI_INSTRUCTION restore $w18
frame-destroy CFI_INSTRUCTION restore $w30
RET undef $lr, implicit killed $w0

bb.6.return:
liveins: $w0
B %bb.7


...