[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:
Reid Kleckner 2015-11-13 19:06:01 +00:00
parent 1d37e60dc5
commit 94b57065c6
9 changed files with 116 additions and 29 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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