forked from OSchip/llvm-project
[WinEH] Make UnwindHelp a fixed stack object allocated after XMM CSRs
Now the offset of UnwindHelp in our EH tables and the offset that we store to in the prologue agree. llvm-svn: 253059
This commit is contained in:
parent
1d37e60dc5
commit
94b57065c6
|
@ -1696,10 +1696,11 @@ int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
|
|||
// RETADDR
|
||||
// PUSH RBP <-- RBP points here
|
||||
// PUSH CSRs
|
||||
// ~~~~~~~ <-- optional stack realignment dynamic adjustment
|
||||
// ~~~~~~~ <-- possible stack realignment (non-win64)
|
||||
// ...
|
||||
// STACK OBJECTS
|
||||
// ... <-- RSP after prologue points here
|
||||
// ~~~~~~~ <-- possible stack realignment (win64)
|
||||
//
|
||||
// if (hasVarSizedObjects()):
|
||||
// ... <-- "base pointer" (ESI/RBX) points here
|
||||
|
@ -1721,7 +1722,8 @@ int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
|
|||
// answer we give is relative to the SP after the prologue, and not the
|
||||
// SP in the middle of the function.
|
||||
|
||||
assert((!TRI->needsStackRealignment(MF) || !MFI->isFixedObjectIndex(FI)) &&
|
||||
assert((!MFI->isFixedObjectIndex(FI) || !TRI->needsStackRealignment(MF) ||
|
||||
STI.isTargetWin64()) &&
|
||||
"offset from fixed object to SP is not static");
|
||||
|
||||
// We don't handle tail calls, and shouldn't be seeing them either.
|
||||
|
@ -2642,3 +2644,40 @@ unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF)
|
|||
Offset += getWinEHFuncletFrameSize(MF);
|
||||
return Offset;
|
||||
}
|
||||
|
||||
void X86FrameLowering::processFunctionBeforeFrameFinalized(
|
||||
MachineFunction &MF, RegScavenger *RS) const {
|
||||
// If this function isn't doing Win64-style C++ EH, we don't need to do
|
||||
// anything.
|
||||
const Function *Fn = MF.getFunction();
|
||||
if (!STI.is64Bit() || !Fn->hasPersonalityFn() ||
|
||||
classifyEHPersonality(MF.getFunction()->getPersonalityFn()) !=
|
||||
EHPersonality::MSVC_CXX)
|
||||
return;
|
||||
|
||||
// Win64 C++ EH needs to allocate the UnwindHelp object at some fixed offset
|
||||
// relative to RSP after the prologue. Find the offset of the last fixed
|
||||
// object, so that we can allocate a slot immediately following it. Fixed
|
||||
// objects have negative frame indices.
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
int64_t MinFixedObjOffset = 0;
|
||||
for (int I = MFI->getObjectIndexBegin(); I < 0; ++I)
|
||||
MinFixedObjOffset = std::min(MinFixedObjOffset, MFI->getObjectOffset(I));
|
||||
|
||||
int64_t UnwindHelpOffset = MinFixedObjOffset - SlotSize;
|
||||
int UnwindHelpFI =
|
||||
MFI->CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false);
|
||||
MF.getMMI().getWinEHFuncInfo(Fn).UnwindHelpFrameIdx = UnwindHelpFI;
|
||||
|
||||
// Store -2 into UnwindHelp on function entry. We have to scan forwards past
|
||||
// other frame setup instructions.
|
||||
MachineBasicBlock &MBB = MF.front();
|
||||
auto MBBI = MBB.begin();
|
||||
while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))
|
||||
++MBBI;
|
||||
|
||||
DebugLoc DL = MBB.findDebugLoc(MBBI);
|
||||
addFrameReference(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64mi32)),
|
||||
UnwindHelpFI)
|
||||
.addImm(-2);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,9 @@ public:
|
|||
|
||||
unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS) const override;
|
||||
|
||||
/// Check the instruction before/after the passed instruction. If
|
||||
/// it is an ADD/SUB/LEA instruction it is deleted argument and the
|
||||
/// stack adjustment is returned as a positive value for ADD/LEA and
|
||||
|
|
|
@ -2880,20 +2880,7 @@ SDValue X86TargetLowering::LowerFormalArguments(
|
|||
|
||||
if (MMI.hasWinEHFuncInfo(Fn)) {
|
||||
EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn());
|
||||
if (Personality == EHPersonality::MSVC_CXX) {
|
||||
if (Is64Bit) {
|
||||
int UnwindHelpFI = MFI->CreateStackObject(8, 8, /*isSS=*/false);
|
||||
SDValue StackSlot = DAG.getFrameIndex(UnwindHelpFI, MVT::i64);
|
||||
MMI.getWinEHFuncInfo(MF.getFunction()).UnwindHelpFrameIdx =
|
||||
UnwindHelpFI;
|
||||
SDValue Neg2 = DAG.getConstant(-2, dl, MVT::i64);
|
||||
Chain = DAG.getStore(Chain, dl, Neg2, StackSlot,
|
||||
MachinePointerInfo::getFixedStack(
|
||||
DAG.getMachineFunction(), UnwindHelpFI),
|
||||
/*isVolatile=*/true,
|
||||
/*isNonTemporal=*/false, /*Alignment=*/0);
|
||||
}
|
||||
} else if (Personality == EHPersonality::CoreCLR) {
|
||||
if (Personality == EHPersonality::CoreCLR) {
|
||||
assert(Is64Bit);
|
||||
// TODO: Add a mechanism to frame lowering that will allow us to indicate
|
||||
// that we'd prefer this slot be allocated towards the bottom of the frame
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
|
||||
|
||||
; We should store -2 into UnwindHelp in a slot immediately after the last XMM
|
||||
; CSR save.
|
||||
|
||||
declare void @g()
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
|
||||
@fp_global = global double 0.0
|
||||
|
||||
define void @f() personality i32 (...)* @__CxxFrameHandler3 {
|
||||
%v = load double, double* @fp_global
|
||||
call void @g()
|
||||
%v1 = fadd double %v, 1.0
|
||||
store double %v1, double* @fp_global
|
||||
invoke void @g()
|
||||
to label %return unwind label %catch
|
||||
|
||||
return:
|
||||
ret void
|
||||
|
||||
catch:
|
||||
%p = catchpad [i8* null, i32 64, i8* null]
|
||||
to label %catchit unwind label %endpad
|
||||
|
||||
catchit:
|
||||
catchret %p to label %return
|
||||
endpad:
|
||||
catchendpad unwind to caller
|
||||
}
|
||||
|
||||
; CHECK: f: # @f
|
||||
; CHECK: pushq %rbp
|
||||
; CHECK: .seh_pushreg 5
|
||||
; CHECK: subq $64, %rsp
|
||||
; CHECK: .seh_stackalloc 64
|
||||
; CHECK: leaq 64(%rsp), %rbp
|
||||
; CHECK: .seh_setframe 5, 64
|
||||
; CHECK: movaps %xmm6, -16(%rbp) # 16-byte Spill
|
||||
; CHECK: .seh_savexmm 6, 48
|
||||
; CHECK: .seh_endprologue
|
||||
; CHECK: movq $-2, -24(%rbp)
|
||||
; CHECK: movsd fp_global(%rip), %xmm6 # xmm6 = mem[0],zero
|
||||
; CHECK: callq g
|
||||
; CHECK: addsd __real@3ff0000000000000(%rip), %xmm6
|
||||
; CHECK: movsd %xmm6, fp_global(%rip)
|
||||
; CHECK: .Ltmp{{.*}}
|
||||
; CHECK: callq g
|
||||
; CHECK: .Ltmp{{.*}}
|
||||
; CHECK: .LBB{{.*}} # Block address taken
|
||||
; CHECK: movaps -16(%rbp), %xmm6
|
||||
; CHECK: addq $64, %rsp
|
||||
; CHECK: popq %rbp
|
||||
; CHECK: retq
|
||||
; CHECK: .seh_handlerdata
|
|
@ -50,15 +50,16 @@ ehcleanup: ; preds = %entry
|
|||
; X64: .seh_pushreg 5
|
||||
; X64: pushq %rbx
|
||||
; X64: .seh_pushreg 3
|
||||
; X64: subq $72, %rsp
|
||||
; X64: .seh_stackalloc 72
|
||||
; X64: leaq 64(%rsp), %rbp
|
||||
; X64: .seh_setframe 5, 64
|
||||
; X64: subq $104, %rsp
|
||||
; X64: .seh_stackalloc 104
|
||||
; X64: leaq 96(%rsp), %rbp
|
||||
; X64: .seh_setframe 5, 96
|
||||
; X64: .seh_endprologue
|
||||
; X64: andq $-32, %rsp
|
||||
; X64: movq %rsp, %rbx
|
||||
; RBP will reload from this offset.
|
||||
; X64: movq %rbp, 48(%rbx)
|
||||
; X64: movq %rbp, 56(%rbx)
|
||||
; X64: movq $-2, (%rbp)
|
||||
|
||||
; X64-LABEL: "?dtor$2@?0?realigned_cleanup@4HA":
|
||||
; X64: movq %rdx, 16(%rsp)
|
||||
|
@ -68,7 +69,7 @@ ehcleanup: ; preds = %entry
|
|||
; X64: .seh_pushreg 3
|
||||
; X64: subq $40, %rsp
|
||||
; X64: .seh_stackalloc 40
|
||||
; X64: leaq 64(%rdx), %rbp
|
||||
; X64: leaq 96(%rdx), %rbp
|
||||
; X64: .seh_endprologue
|
||||
; X64: andq $-32, %rdx
|
||||
; X64: movq %rdx, %rbx
|
||||
|
|
|
@ -106,6 +106,7 @@ catchendblock: ; preds = %catch,
|
|||
; X64: leaq 32(%rsp), %rbp
|
||||
; X64: .seh_setframe 5, 32
|
||||
; X64: .seh_endprologue
|
||||
; X64: movq $-2, (%rbp)
|
||||
; X64: callq getint
|
||||
; X64: callq getint
|
||||
; X64: callq getint
|
||||
|
|
|
@ -38,13 +38,14 @@ return: ; preds = %entry, %catch
|
|||
; X64: pushq %rsi
|
||||
; X64: subq $56, %rsp
|
||||
; X64: leaq 48(%rsp), %rbp
|
||||
; X64: movq $-2, (%rbp)
|
||||
; X64: callq g
|
||||
; X64: movl %esi, %eax
|
||||
; X64: addq $56, %rsp
|
||||
; X64: popq %rsi
|
||||
; X64: popq %rbp
|
||||
|
||||
; X64: movl 4(%rbp), %esi
|
||||
; X64: movl -4(%rbp), %esi
|
||||
; X64: jmp
|
||||
|
||||
; X64-LABEL: "?catch$1@?0?f@4HA":
|
||||
|
@ -64,7 +65,7 @@ return: ; preds = %entry, %catch
|
|||
; - 48 for setframe
|
||||
; = 40
|
||||
; X64: movl 40(%rbp), %eax
|
||||
; X64: movl %eax, 4(%rbp)
|
||||
; X64: movl %eax, -4(%rbp)
|
||||
; X64: leaq .LBB0_2(%rip), %rax
|
||||
; X64: addq $40, %rsp
|
||||
; X64: popq %rsi
|
||||
|
|
|
@ -138,6 +138,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
|||
; X64: leaq 48(%rsp), %rbp
|
||||
; X64: .seh_setframe 5, 48
|
||||
; X64: .seh_endprologue
|
||||
; X64: movq $-2, -8(%rbp)
|
||||
; X64: .Ltmp0
|
||||
; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx
|
||||
; X64-DAG: movl $1, %ecx
|
||||
|
@ -159,7 +160,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
|||
; X64: .seh_endprologue
|
||||
; X64-DAG: .Ltmp4
|
||||
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
|
||||
; X64-DAG: movl -4(%rbp), %ecx
|
||||
; X64-DAG: movl -12(%rbp), %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64-NEXT: addq $32, %rsp
|
||||
|
@ -192,7 +193,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
|||
; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL
|
||||
; X64-NEXT: .long 4
|
||||
; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL
|
||||
; X64-NEXT: .long 32
|
||||
; X64-NEXT: .long 40
|
||||
; X64-NEXT: .long 0
|
||||
; X64-NEXT: .long 1
|
||||
|
||||
|
@ -206,8 +207,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
|
|||
; X64: $handlerMap$0$try_catch_catch:
|
||||
; X64-NEXT: .long 0
|
||||
; X64-NEXT: .long "??_R0H@8"@IMGREL
|
||||
; FIXME: This should probably be offset from rsp, not rbp.
|
||||
; X64-NEXT: .long 44
|
||||
; X64-NEXT: .long 36
|
||||
; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
|
||||
; X64-NEXT: .long 56
|
||||
; X64-NEXT: .long 64
|
||||
|
|
|
@ -142,7 +142,7 @@ cleanup.outer: ; preds = %invoke.cont.1, %c
|
|||
; X64-NEXT: .long 0
|
||||
; X64-NEXT: .long 5
|
||||
; X64-NEXT: .long ($ip2state$nested_cleanup)@IMGREL
|
||||
; X64-NEXT: .long 40
|
||||
; X64-NEXT: .long 56
|
||||
; X64-NEXT: .long 0
|
||||
; X64-NEXT: .long 1
|
||||
|
||||
|
|
Loading…
Reference in New Issue