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