From: David Majnemer Date: Tue, 29 Sep 2015 22:33:36 +0000 (+0000) Subject: [WinEH] Ensure that funclets obey the x64 ABI X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=28c61f88cc67ea857234e9bcd334a61b7a3ac228;p=oota-llvm.git [WinEH] Ensure that funclets obey the x64 ABI The x64 ABI requires that epilogues do not contain code other than stack adjustments and some limited control flow. However, we'd insert code to initialize the return address after stack adjustments. Instead, insert EAX/RAX with the current value before we create the stack adjustments in the epilogue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248839 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ExpandPseudo.cpp b/lib/Target/X86/X86ExpandPseudo.cpp index c9441bd0c2f..6a5a28e546f 100644 --- a/lib/Target/X86/X86ExpandPseudo.cpp +++ b/lib/Target/X86/X86ExpandPseudo.cpp @@ -141,41 +141,6 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, // The EH_RETURN pseudo is really removed during the MC Lowering. return true; } - - case X86::CLEANUPRET: { - // Replace CATCHRET with the appropriate RET. - unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL; - BuildMI(MBB, MBBI, DL, TII->get(RetOp)); - MBBI->eraseFromParent(); - return true; - } - - case X86::CATCHRET: { - MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB(); - - // Fill EAX/RAX with the address of the target block. - unsigned ReturnReg = STI->is64Bit() ? X86::RAX : X86::EAX; - unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL; - if (STI->is64Bit()) { - // LEA64r TargetMBB(%rip), %rax - BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), ReturnReg) - .addReg(X86::RIP) - .addImm(0) - .addReg(0) - .addMBB(TargetMBB) - .addReg(0); - } else { - // MOV32ri $TargetMBB, %eax - BuildMI(MBB, MBBI, DL, TII->get(X86::MOV32ri)) - .addReg(ReturnReg) - .addMBB(TargetMBB); - } - - // Replace CATCHRET with the appropriate RET. - BuildMI(MBB, MBBI, DL, TII->get(RetOp)).addReg(ReturnReg); - MBBI->eraseFromParent(); - return true; - } } llvm_unreachable("Previous switch has a fallthrough?"); } diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 0e6b5c4b404..b0bd6983654 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -1093,9 +1093,26 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (STI.is32Bit()) { RestoreMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock()); MF.insert(TargetMBB, RestoreMBB); - MBB.transferSuccessors(RestoreMBB); + MBB.removeSuccessor(TargetMBB); MBB.addSuccessor(RestoreMBB); - MBBI->getOperand(0).setMBB(RestoreMBB); + RestoreMBB->addSuccessor(TargetMBB); + } + + // Fill EAX/RAX with the address of the target block. + unsigned ReturnReg = STI.is64Bit() ? X86::RAX : X86::EAX; + if (STI.is64Bit()) { + // LEA64r RestoreMBB(%rip), %rax + BuildMI(MBB, MBBI, DL, TII.get(X86::LEA64r), ReturnReg) + .addReg(X86::RIP) + .addImm(0) + .addReg(0) + .addMBB(RestoreMBB) + .addReg(0); + } else { + // MOV32ri $RestoreMBB, %eax + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri)) + .addReg(ReturnReg) + .addMBB(RestoreMBB); } // Pop EBP. @@ -1111,12 +1128,24 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::JMP_4)) .addMBB(TargetMBB); } - } else if (isFuncletReturnInstr(MBBI)) { + // Replace CATCHRET with the appropriate RET. + unsigned RetOp = STI.is64Bit() ? X86::RETQ : X86::RETL; + MachineBasicBlock::iterator NewExit = + BuildMI(MBB, MBBI, DL, TII.get(RetOp)).addReg(ReturnReg); + MBBI->eraseFromParent(); + MBBI = NewExit; + } else if (MBBI->getOpcode() == X86::CLEANUPRET) { NumBytes = MFI->getMaxCallFrameSize(); assert(hasFP(MF) && "EH funclets without FP not yet implemented"); BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) .setMIFlag(MachineInstr::FrameDestroy); + // Replace CLEANUPRET with the appropriate RET. + unsigned RetOp = STI.is64Bit() ? X86::RETQ : X86::RETL; + MachineBasicBlock::iterator NewExit = + BuildMI(MBB, MBBI, DL, TII.get(RetOp)); + MBBI->eraseFromParent(); + MBBI = NewExit; } else if (hasFP(MF)) { // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; diff --git a/test/CodeGen/X86/win-catchpad-csrs.ll b/test/CodeGen/X86/win-catchpad-csrs.ll index 6603f4e6d92..4a745121cc4 100644 --- a/test/CodeGen/X86/win-catchpad-csrs.ll +++ b/test/CodeGen/X86/win-catchpad-csrs.ll @@ -80,9 +80,9 @@ catchendblock: ; preds = %catch, ; X86: movl $1, -{{[0-9]+}}(%ebp) ; X86: movl $2, (%esp) ; X86: calll _f -; X86: addl $16, %esp +; X86: movl $[[restorebb]], %eax +; X86-NEXT: addl $16, %esp ; X86-NEXT: popl %ebp -; X86-NEXT: movl $[[restorebb]], %eax ; X86-NEXT: retl ; X86: L__ehtable$try_catch_catch: @@ -125,9 +125,9 @@ catchendblock: ; preds = %catch, ; X64: subq $32, %rsp ; X64: movl $2, %ecx ; X64: callq f +; X64: leaq [[contbb]](%rip), %rax ; X64: addq $32, %rsp ; X64: popq %rbp -; X64: leaq [[contbb]](%rip), %rax ; X64: retq ; X64: $handlerMap$0$try_catch_catch: diff --git a/test/CodeGen/X86/win-catchpad.ll b/test/CodeGen/X86/win-catchpad.ll index 7af13e67975..5a700b444f2 100644 --- a/test/CodeGen/X86/win-catchpad.ll +++ b/test/CodeGen/X86/win-catchpad.ll @@ -73,7 +73,13 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont ; X86: retl -; X86: [[restorebb:LBB0_[0-9]+]]: # %invoke.cont.3 +; FIXME: These should be de-duplicated. +; X86: [[restorebb1:LBB0_[0-9]+]]: # %invoke.cont.2 +; X86: movl -16(%ebp), %esp +; X86: addl $12, %ebp +; X86: jmp [[contbb]] + +; X86: [[restorebb2:LBB0_[0-9]+]]: # %invoke.cont.3 ; X86: movl -16(%ebp), %esp ; X86: addl $12, %ebp ; X86: jmp [[contbb]] @@ -89,9 +95,9 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86-DAG: movl %[[addr_reg]], 4(%esp) ; X86-DAG: movl %[[e_reg]], (%esp) ; X86: calll _f +; X86-NEXT: movl $[[restorebb1]], %eax ; X86-NEXT: addl $8, %esp ; X86-NEXT: popl %ebp -; X86-NEXT: movl $[[restorebb]], %eax ; X86-NEXT: retl ; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": @@ -104,9 +110,9 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86-DAG: movl %[[addr_reg]], 4(%esp) ; X86-DAG: movl $3, (%esp) ; X86: calll _f +; X86-NEXT: movl $[[restorebb2]], %eax ; X86-NEXT: addl $8, %esp ; X86-NEXT: popl %ebp -; X86-NEXT: movl $[[restorebb]], %eax ; X86-NEXT: retl ; X86: L__ehtable$try_catch_catch: @@ -147,9 +153,9 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx ; X64-DAG: movl [[e_addr:[-0-9]+]](%rbp), %ecx ; X64: callq f -; X64: addq $32, %rsp +; X64: leaq [[contbb]](%rip), %rax +; X64-NEXT: addq $32, %rsp ; X64-NEXT: popq %rbp -; X64-NEXT: leaq [[contbb]](%rip), %rax ; X64-NEXT: retq ; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": @@ -162,9 +168,9 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X64-DAG: movl $3, %ecx ; X64: callq f ; X64: .Ltmp3 -; X64: addq $32, %rsp +; X64: leaq [[contbb]](%rip), %rax +; X64-NEXT: addq $32, %rsp ; X64-NEXT: popq %rbp -; X64-NEXT: leaq [[contbb]](%rip), %rax ; X64-NEXT: retq ; X64: $cppxdata$try_catch_catch: diff --git a/test/CodeGen/X86/win-funclet-cfi.ll b/test/CodeGen/X86/win-funclet-cfi.ll index 30883791d8e..63a81d81551 100644 --- a/test/CodeGen/X86/win-funclet-cfi.ll +++ b/test/CodeGen/X86/win-funclet-cfi.ll @@ -89,9 +89,9 @@ declare i32 @__CxxFrameHandler3(...) ; Prologue is done, emit the .seh_endprologue directive. ; CHECK: .seh_endprologue -; Make sure there is a nop after a call if the call precedes the epilogue. +; Make sure there is at least one instruction after a call before the epilogue. ; CHECK: callq g -; CHECK-NEXT: nop +; CHECK-NEXT: leaq .LBB0_{{[0-9]+}}(%rip), %rax ; Emit a reference to the LSDA. ; CHECK: .seh_handlerdata