From: Reid Kleckner Date: Fri, 13 Nov 2015 19:06:01 +0000 (+0000) Subject: [WinEH] Make UnwindHelp a fixed stack object allocated after XMM CSRs X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=04538c959e391123e095e7b58699f14004627717;p=oota-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253059 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index da48a871930..302fc936744 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -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); +} diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h index 753d155657d..68dc8edfd43 100644 --- a/lib/Target/X86/X86FrameLowering.h +++ b/lib/Target/X86/X86FrameLowering.h @@ -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 diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index fdb716ebca4..93a4dc291f5 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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 diff --git a/test/CodeGen/X86/catchpad-realign-savexmm.ll b/test/CodeGen/X86/catchpad-realign-savexmm.ll new file mode 100644 index 00000000000..a1578d4843a --- /dev/null +++ b/test/CodeGen/X86/catchpad-realign-savexmm.ll @@ -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 diff --git a/test/CodeGen/X86/cleanuppad-realign.ll b/test/CodeGen/X86/cleanuppad-realign.ll index c80077e80c6..a19cf261307 100644 --- a/test/CodeGen/X86/cleanuppad-realign.ll +++ b/test/CodeGen/X86/cleanuppad-realign.ll @@ -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 diff --git a/test/CodeGen/X86/win-catchpad-csrs.ll b/test/CodeGen/X86/win-catchpad-csrs.ll index 114cc8be622..f759a4ef0d9 100644 --- a/test/CodeGen/X86/win-catchpad-csrs.ll +++ b/test/CodeGen/X86/win-catchpad-csrs.ll @@ -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 diff --git a/test/CodeGen/X86/win-catchpad-varargs.ll b/test/CodeGen/X86/win-catchpad-varargs.ll index f25bacfd630..03c6c70dc69 100644 --- a/test/CodeGen/X86/win-catchpad-varargs.ll +++ b/test/CodeGen/X86/win-catchpad-varargs.ll @@ -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 diff --git a/test/CodeGen/X86/win-catchpad.ll b/test/CodeGen/X86/win-catchpad.ll index a9fd47a5dcf..826fae522a3 100644 --- a/test/CodeGen/X86/win-catchpad.ll +++ b/test/CodeGen/X86/win-catchpad.ll @@ -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 diff --git a/test/CodeGen/X86/win-cleanuppad.ll b/test/CodeGen/X86/win-cleanuppad.ll index 927a6e604c1..aed410f79b1 100644 --- a/test/CodeGen/X86/win-cleanuppad.ll +++ b/test/CodeGen/X86/win-cleanuppad.ll @@ -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