From f89ce9a09d44506828e5397bdbe378addbbcf9bd Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 3 Apr 2015 22:32:26 +0000 Subject: [PATCH] [WinEH] Sink UnwindHelp completely out of IR We don't need to represent UnwindHelp in IR. Instead, we can use the knowledge that we are emitting the parent function to decide if we should create the UnwindHelp stack object. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234061 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ExceptionHandling.rst | 12 --------- include/llvm/CodeGen/MachineFrameInfo.h | 4 --- include/llvm/IR/Intrinsics.td | 4 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 11 -------- lib/CodeGen/WinEHPrepare.cpp | 14 ---------- lib/IR/Verifier.cpp | 7 ----- lib/Target/X86/X86ISelLowering.cpp | 27 +++++++++++++------ test/CodeGen/WinEH/cppeh-catch-unwind.ll | 3 --- test/CodeGen/WinEH/cppeh-multi-catch.ll | 4 --- test/CodeGen/WinEH/cppeh-prepared-catch.ll | 21 +++++---------- test/CodeGen/WinEH/cppeh-prepared-cleanups.ll | 9 ++----- 11 files changed, 27 insertions(+), 89 deletions(-) diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst index 6c33e0b363c..72ed78a3c99 100644 --- a/docs/ExceptionHandling.rst +++ b/docs/ExceptionHandling.rst @@ -543,18 +543,6 @@ In order to preserve the structure of the CFG, a call to '``llvm.eh.actions``' must be followed by an ':ref:`indirectbr `' instruction that jumps to the result of the intrinsic call. -``llvm.eh.unwindhelp`` ----------------------- - -.. code-block:: llvm - - void @llvm.eh.unwindhelp(i8*) - -This intrinsic designates the provided static alloca as the unwind help object. -This object is used by Windows native exception handling on non-x86 platforms -where xdata unwind information is used. It is typically an 8 byte chunk of -memory treated as two 32-bit integers. - SJLJ Intrinsics --------------- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 667736021f9..1e7fee666fc 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -516,10 +516,6 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); - /// Allocates memory at a fixed, target-specific offset from the frame - /// pointer. Marks the function as having its frame address taken. - int CreateFrameAllocation(uint64_t Size); - /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e0e8d674e16..4052a312fd0 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -421,10 +421,6 @@ def int_eh_endcatch : Intrinsic<[], []>; // Represents the list of actions to take when an exception is thrown. def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; -// Designates the provided static alloca as the unwind help object. Required -// for WinEH. -def int_eh_unwindhelp : Intrinsic<[], [llvm_ptr_ty], []>; - // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index dde8434e0b9..008d7dc2b25 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5453,17 +5453,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { case Intrinsic::eh_begincatch: case Intrinsic::eh_endcatch: llvm_unreachable("begin/end catch intrinsics not lowered in codegen"); - case Intrinsic::eh_unwindhelp: { - AllocaInst *Slot = - cast(I.getArgOperand(0)->stripPointerCasts()); - assert(FuncInfo.StaticAllocaMap.count(Slot) && - "can only use static allocas with llvm.eh.unwindhelp"); - int FI = FuncInfo.StaticAllocaMap[Slot]; - MachineFunction &MF = DAG.getMachineFunction(); - MachineModuleInfo &MMI = MF.getMMI(); - MMI.getWinEHFuncInfo(MF.getFunction()).UnwindHelpFrameIdx = FI; - return nullptr; - } } } diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index d030a7d44cd..d12a8ed472b 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -607,20 +607,6 @@ bool WinEHPrepare::prepareExceptionHandlers( Builder.SetInsertPoint(&F.getEntryBlock().back()); Builder.CreateCall(FrameEscapeFn, AllocasToEscape); - // Insert an alloca for the EH state in the entry block. On x86, we will also - // insert stores to update the EH state, but on other ISAs, the runtime does - // it for us. - // FIXME: This record is different on x86. - Type *UnwindHelpTy = Type::getInt64Ty(Context); - AllocaInst *UnwindHelp = - new AllocaInst(UnwindHelpTy, "unwindhelp", &F.getEntryBlock().front()); - Builder.CreateStore(llvm::ConstantInt::get(UnwindHelpTy, -2), UnwindHelp, - /*isVolatile=*/true); - Function *UnwindHelpFn = - Intrinsic::getDeclaration(M, Intrinsic::eh_unwindhelp); - Builder.CreateCall(UnwindHelpFn, - Builder.CreateBitCast(UnwindHelp, Int8PtrType)); - // Clean up the handler action maps we created for this function DeleteContainerSeconds(CatchHandlerMap); CatchHandlerMap.clear(); diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 15e354b8dfc..accd5cd8940 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -3230,13 +3230,6 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { break; } - case Intrinsic::eh_unwindhelp: { - auto *AI = dyn_cast(CI.getArgOperand(0)->stripPointerCasts()); - Assert(AI && AI->isStaticAlloca(), - "llvm.eh.unwindhelp requires a static alloca", &CI); - break; - } - case Intrinsic::experimental_gc_statepoint: Assert(!CI.isInlineAsm(), "gc.statepoint support for inline assembly unimplemented", &CI); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index de81949e0cc..3055256605a 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2267,12 +2267,6 @@ static ArrayRef get64BitArgumentXMMs(MachineFunction &MF, return makeArrayRef(std::begin(XMMArgRegs64Bit), std::end(XMMArgRegs64Bit)); } -static bool isOutlinedHandler(const MachineFunction &MF) { - const MachineModuleInfo &MMI = MF.getMMI(); - const Function *F = MF.getFunction(); - return MMI.getWinEHParent(F) != F; -} - SDValue X86TargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -2424,6 +2418,13 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, MFI->CreateFixedObject(1, StackSize, true)); } + MachineModuleInfo &MMI = MF.getMMI(); + const Function *WinEHParent = nullptr; + if (IsWin64 && MMI.hasWinEHFuncInfo(Fn)) + WinEHParent = MMI.getWinEHParent(Fn); + bool IsWinEHOutlined = WinEHParent && WinEHParent != Fn; + bool IsWinEHParent = WinEHParent && WinEHParent == Fn; + // Figure out if XMM registers are in use. assert(!(MF.getTarget().Options.UseSoftFloat && Fn->hasFnAttribute(Attribute::NoImplicitFloat)) && @@ -2512,14 +2513,13 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, if (!MemOps.empty()) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); - } else if (IsWin64 && isOutlinedHandler(MF)) { + } else if (IsWinEHOutlined) { // Get to the caller-allocated home save location. Add 8 to account // for the return address. int HomeOffset = TFI.getOffsetOfLocalArea() + 8; FuncInfo->setRegSaveFrameIndex(MFI->CreateFixedObject( /*Size=*/1, /*SPOffset=*/HomeOffset + 8, /*Immutable=*/false)); - MachineModuleInfo &MMI = MF.getMMI(); MMI.getWinEHFuncInfo(Fn) .CatchHandlerParentFrameObjIdx[const_cast(Fn)] = FuncInfo->getRegSaveFrameIndex(); @@ -2600,6 +2600,17 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, FuncInfo->setArgumentStackSize(StackSize); + if (IsWinEHParent) { + 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, MVT::i64); + Chain = DAG.getStore(Chain, dl, Neg2, StackSlot, + MachinePointerInfo::getFixedStack(UnwindHelpFI), + /*isVolatile=*/true, + /*isNonTemporal=*/false, /*Alignment=*/0); + } + return Chain; } diff --git a/test/CodeGen/WinEH/cppeh-catch-unwind.ll b/test/CodeGen/WinEH/cppeh-catch-unwind.ll index 055a3ad0dca..92f67479f93 100644 --- a/test/CodeGen/WinEH/cppeh-catch-unwind.ll +++ b/test/CodeGen/WinEH/cppeh-catch-unwind.ll @@ -33,13 +33,10 @@ $"\01??_R0H@8" = comdat any ; CHECK-LABEL: define void @"\01?test@@YAXXZ"() #0 { ; CHECK: entry: -; CHECK: [[UNWIND_HELP:\%.+]] = alloca i64 ; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass ; CHECK: [[TMP0:\%.+]] = alloca i32, align 4 ; CHECK: [[TMP1:\%.+]] = alloca i32, align 4 ; CHECK: call void (...)* @llvm.frameescape(i32* [[TMP1]], %class.SomeClass* [[OBJ_PTR]], i32* [[TMP0]]) -; CHECK: [[UNWIND_HELP_i8:\%.+]] = bitcast i64* [[UNWIND_HELP]] to i8* -; CHECK: call void @llvm.eh.unwindhelp(i8* [[UNWIND_HELP_i8]]) ; CHECK: %call = invoke %class.SomeClass* @"\01??0SomeClass@@QEAA@XZ"(%class.SomeClass* %obj) ; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]+]] diff --git a/test/CodeGen/WinEH/cppeh-multi-catch.ll b/test/CodeGen/WinEH/cppeh-multi-catch.ll index 29b342a824e..a7bd0b86f09 100644 --- a/test/CodeGen/WinEH/cppeh-multi-catch.ll +++ b/test/CodeGen/WinEH/cppeh-multi-catch.ll @@ -47,14 +47,10 @@ $"\01??_R0?AVSomeClass@@@8" = comdat any ; CHECK: define void @"\01?test@@YAXXZ"() #0 { ; CHECK: entry: -; CHECK: [[UNWINDHELP:\%.+]] = alloca i64 ; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass*, align 8 ; CHECK: [[LL_PTR:\%.+]] = alloca i64, align 8 ; CHECK: [[I_PTR:\%.+]] = alloca i32, align 4 ; CHECK: call void (...)* @llvm.frameescape(i32* [[I_PTR]], i64* [[LL_PTR]], %class.SomeClass** [[OBJ_PTR]]) -; CHECK: store volatile i64 -2, i64* [[UNWINDHELP]] -; CHECK: [[TMP:\%.+]] = bitcast i64* [[UNWINDHELP]] to i8* -; CHECK: call void @llvm.eh.unwindhelp(i8* [[TMP]]) ; CHECK: invoke void @"\01?may_throw@@YAXXZ"() ; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]+]] diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch.ll b/test/CodeGen/WinEH/cppeh-prepared-catch.ll index c05a202c3a8..3bc864833e1 100644 --- a/test/CodeGen/WinEH/cppeh-prepared-catch.ll +++ b/test/CodeGen/WinEH/cppeh-prepared-catch.ll @@ -33,8 +33,8 @@ $"\01??_R0H@8" = comdat any define internal i8* @"\01?f@@YAXXZ.catch"(i8*, i8*) #4 { entry: %.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?f@@YAXXZ" to i8*), i8* %1, i32 0) - %2 = bitcast i8* %.i8 to i32** - %3 = bitcast i32** %2 to i8* + %bc2 = bitcast i8* %.i8 to i32** + %bc3 = bitcast i32** %bc2 to i8* invoke void @"\01?may_throw@@YAXXZ"() to label %invoke.cont2 unwind label %lpad1 @@ -42,7 +42,7 @@ invoke.cont2: ; preds = %entry ret i8* blockaddress(@"\01?f@@YAXXZ", %try.cont) lpad1: ; preds = %entry - %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) + %lp4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) cleanup catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 %recover = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") @@ -50,8 +50,6 @@ lpad1: ; preds = %entry } ; CHECK-LABEL: "?f@@YAXXZ.catch": -; CHECK: ".L?f@@YAXXZ.catch$parent_frame_offset" = 56 -; CHECK: movq %rdx, 56(%rsp) ; CHECK: .seh_handlerdata ; CHECK: .long ("$cppxdata$?f@@YAXXZ")@IMGREL @@ -81,15 +79,11 @@ lpad: ; preds = %entry define void @"\01?f@@YAXXZ"() #0 { entry: - %unwindhelp = alloca i64 %exn.slot = alloca i8* %ehselector.slot = alloca i32 %0 = alloca i32*, align 8 %1 = alloca double, align 8 call void (...)* @llvm.frameescape(i32** %0, double* %1) - store volatile i64 -2, i64* %unwindhelp - %2 = bitcast i64* %unwindhelp to i8* - call void @llvm.eh.unwindhelp(i8* %2) invoke void @"\01?may_throw@@YAXXZ"() to label %invoke.cont unwind label %lpad2 @@ -97,7 +91,7 @@ invoke.cont: ; preds = %entry br label %try.cont lpad2: ; preds = %entry - %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) + %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.8 catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 %recover = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.8 to i8*), i32 0, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") @@ -108,7 +102,7 @@ try.cont: ; preds = %lpad2, %invoke.cont to label %try.cont8 unwind label %lpad1 lpad1: - %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) + %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 %recover2 = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") indirectbr i8* %recover2, [label %try.cont8] @@ -128,7 +122,7 @@ try.cont8: ; preds = %lpad2, %try.cont ; CHECK-NEXT: .long ("$tryMap$?f@@YAXXZ")@IMGREL ; CHECK-NEXT: .long 3 ; CHECK-NEXT: .long ("$ip2state$?f@@YAXXZ")@IMGREL -; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 32 ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 1 ; CHECK-NEXT:"$stateUnwindMap$?f@@YAXXZ": @@ -194,9 +188,6 @@ declare void @llvm.frameescape(...) #3 ; Function Attrs: nounwind readnone declare i8* @llvm.framerecover(i8*, i8*, i32) #2 -; Function Attrs: nounwind -declare void @llvm.eh.unwindhelp(i8*) #3 - declare void @llvm.donothing(...) attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" "wineh-parent"="?f@@YAXXZ" } diff --git a/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll b/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll index 0a76a22208c..df6b5f3be23 100644 --- a/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll +++ b/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll @@ -38,7 +38,7 @@ $_TI1H = comdat any ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 1 ; CHECK-NEXT: .long ("$ip2state$?test1@@YAXXZ")@IMGREL -; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 32 ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 1 ; CHECK-NEXT:"$stateUnwindMap$?test1@@YAXXZ": @@ -98,7 +98,7 @@ entry: ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long ("$ip2state$?test2@@YAX_N@Z")@IMGREL -; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 40 ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 1 ; CHECK-NEXT:"$stateUnwindMap$?test2@@YAX_N@Z": @@ -117,8 +117,6 @@ entry: ; CHECK-NEXT: .long 0 define void @"\01?test2@@YAX_N@Z"(i1 zeroext %b) #2 { -entry: - %unwindhelp = alloca i64 %b.addr = alloca i8, align 1 %s = alloca %struct.S, align 1 %exn.slot = alloca i8* @@ -126,10 +124,7 @@ entry: %s1 = alloca %struct.S, align 1 %frombool = zext i1 %b to i8 store i8 %frombool, i8* %b.addr, align 1 - %0 = bitcast i64* %unwindhelp to i8* - store volatile i64 -2, i64* %unwindhelp call void (...)* @llvm.frameescape(%struct.S* %s, %struct.S* %s1) - call void @llvm.eh.unwindhelp(i8* %0) call void @"\01?may_throw@@YAXXZ"() invoke void @"\01?may_throw@@YAXXZ"() to label %invoke.cont unwind label %lpad1 -- 2.34.1