forked from OSchip/llvm-project
WinEH: Create an unwind help alloca for __CxxFrameHandler3 xdata tables
We don't have any logic to emit those tables yet, so the sdag lowering of this intrinsic is just a stub. We can see the intrinsic in the prepared IR, though. llvm-svn: 233209
This commit is contained in:
parent
4f7b9eb217
commit
7e9546b378
|
@ -539,6 +539,18 @@ In order to preserve the structure of the CFG, a call to '``llvm.eh.actions``'
|
||||||
must be followed by an ':ref:`indirectbr <i_indirectbr>`' instruction that jumps
|
must be followed by an ':ref:`indirectbr <i_indirectbr>`' instruction that jumps
|
||||||
to the result of the intrinsic call.
|
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
|
SJLJ Intrinsics
|
||||||
---------------
|
---------------
|
||||||
|
|
|
@ -421,6 +421,10 @@ def int_eh_endcatch : Intrinsic<[], []>;
|
||||||
// Represents the list of actions to take when an exception is thrown.
|
// Represents the list of actions to take when an exception is thrown.
|
||||||
def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
|
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
|
// __builtin_unwind_init is an undocumented GCC intrinsic that causes all
|
||||||
// callee-saved registers to be saved and restored (regardless of whether they
|
// callee-saved registers to be saved and restored (regardless of whether they
|
||||||
// are used) in the calling function. It is used by libgcc_eh.
|
// are used) in the calling function. It is used by libgcc_eh.
|
||||||
|
|
|
@ -5446,6 +5446,16 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||||
case Intrinsic::eh_begincatch:
|
case Intrinsic::eh_begincatch:
|
||||||
case Intrinsic::eh_endcatch:
|
case Intrinsic::eh_endcatch:
|
||||||
llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
|
llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
|
||||||
|
case Intrinsic::eh_unwindhelp: {
|
||||||
|
AllocaInst *Slot =
|
||||||
|
cast<AllocaInst>(I.getArgOperand(0)->stripPointerCasts());
|
||||||
|
assert(FuncInfo.StaticAllocaMap.count(Slot) &&
|
||||||
|
"can only use static allocas with llvm.eh.unwindhelp");
|
||||||
|
int FI = FuncInfo.StaticAllocaMap[Slot];
|
||||||
|
// TODO: Save this in the not-yet-existant WinEHFuncInfo struct.
|
||||||
|
(void)FI;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -601,6 +601,19 @@ bool WinEHPrepare::prepareExceptionHandlers(
|
||||||
Builder.SetInsertPoint(&F.getEntryBlock().back());
|
Builder.SetInsertPoint(&F.getEntryBlock().back());
|
||||||
Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
|
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);
|
||||||
|
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
|
// Clean up the handler action maps we created for this function
|
||||||
DeleteContainerSeconds(CatchHandlerMap);
|
DeleteContainerSeconds(CatchHandlerMap);
|
||||||
CatchHandlerMap.clear();
|
CatchHandlerMap.clear();
|
||||||
|
|
|
@ -2908,6 +2908,13 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Intrinsic::eh_unwindhelp: {
|
||||||
|
auto *AI = dyn_cast<AllocaInst>(CI.getArgOperand(0)->stripPointerCasts());
|
||||||
|
Assert(AI && AI->isStaticAlloca(),
|
||||||
|
"llvm.eh.unwindhelp requires a static alloca", &CI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Intrinsic::experimental_gc_statepoint:
|
case Intrinsic::experimental_gc_statepoint:
|
||||||
Assert(!CI.isInlineAsm(),
|
Assert(!CI.isInlineAsm(),
|
||||||
"gc.statepoint support for inline assembly unimplemented", &CI);
|
"gc.statepoint support for inline assembly unimplemented", &CI);
|
||||||
|
|
|
@ -33,10 +33,13 @@ $"\01??_R0H@8" = comdat any
|
||||||
|
|
||||||
; CHECK-LABEL: define void @"\01?test@@YAXXZ"() #0 {
|
; CHECK-LABEL: define void @"\01?test@@YAXXZ"() #0 {
|
||||||
; CHECK: entry:
|
; CHECK: entry:
|
||||||
|
; CHECK: [[UNWIND_HELP:\%.+]] = alloca i64
|
||||||
; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass
|
; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass
|
||||||
; CHECK: [[TMP0:\%.+]] = alloca i32, align 4
|
; CHECK: [[TMP0:\%.+]] = alloca i32, align 4
|
||||||
; CHECK: [[TMP1:\%.+]] = alloca i32, align 4
|
; CHECK: [[TMP1:\%.+]] = alloca i32, align 4
|
||||||
; CHECK: call void (...)* @llvm.frameescape(i32* [[TMP1]], %class.SomeClass* [[OBJ_PTR]], i32* [[TMP0]])
|
; 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: %call = invoke %class.SomeClass* @"\01??0SomeClass@@QEAA@XZ"(%class.SomeClass* %obj)
|
||||||
; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]+]]
|
; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]+]]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue