[WinEH] Create an llvm.x86.seh.exceptioninfo intrinsic

This intrinsic is like framerecover plus a load. It recovers the EH
registration stack allocation from the parent frame and loads the
exception information field out of it, giving back a pointer to an
EXCEPTION_POINTERS struct. It's designed for clang to use in SEH filter
expressions instead of accessing the EXCEPTION_POINTERS parameter that
is available on x64.

This required a minor change to MC to allow defining a label variable to
another absolute framerecover label variable.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239567 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner
2015-06-11 22:32:23 +00:00
parent 5e9819c5bd
commit 3e16bd3aaf
10 changed files with 176 additions and 105 deletions

View File

@@ -67,8 +67,6 @@ private:
void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
Function &F, int BaseState);
void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
iplist<Instruction>::iterator
rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin);
Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
@@ -487,6 +485,12 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
// Remember and return the index that we used. We save it in WinEHFuncInfo so
// that we can lower llvm.x86.seh.exceptioninfo later in filter functions
// without too much trouble.
int RegNodeEscapeIndex = escapeRegNode(F);
FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex;
// Iterate all the instructions and emit state number stores.
int CurState = 0;
SmallPtrSet<BasicBlock *, 4> ExceptBlocks;
@@ -495,7 +499,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
if (auto *CI = dyn_cast<CallInst>(I)) {
auto *Intrin = dyn_cast<IntrinsicInst>(CI);
if (Intrin) {
I = rewriteExceptionInfoIntrinsics(Intrin);
// Calls that "don't throw" are considered to be able to throw asynch
// exceptions, but intrinsics cannot.
continue;
@@ -542,32 +545,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
}
}
/// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in
/// IR.
iplist<Instruction>::iterator
WinEHStatePass::rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin) {
Intrinsic::ID ID = Intrin->getIntrinsicID();
if (ID != Intrinsic::eh_exceptioncode && ID != Intrinsic::eh_exceptioninfo)
return Intrin;
// RegNode->ExceptionPointers
IRBuilder<> Builder(Intrin);
Value *Ptrs =
Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
Value *Res;
if (ID == Intrinsic::eh_exceptioncode) {
// Ptrs->ExceptionRecord->Code
Ptrs = Builder.CreateBitCast(
Ptrs, Builder.getInt32Ty()->getPointerTo()->getPointerTo());
Value *Rec = Builder.CreateLoad(Ptrs);
Res = Builder.CreateLoad(Rec);
} else {
Res = Ptrs;
}
Intrin->replaceAllUsesWith(Res);
return Intrin->eraseFromParent();
}
void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode,
Instruction *IP, int State) {
IRBuilder<> Builder(IP);