WinEHPrepare(const TargetMachine *TM = nullptr)
: FunctionPass(ID) {
if (TM)
- TheTriple = Triple(TM->getTargetTriple());
+ TheTriple = TM->getTargetTriple();
}
bool runOnFunction(Function &Fn) override;
LandingPadInst *OutlinedLPad,
const LandingPadInst *OriginalLPad,
FrameVarInfoMap &VarInfo);
- Function *createHandlerFunc(Type *RetTy, const Twine &Name, Module *M,
- Value *&ParentFP);
+ Function *createHandlerFunc(Function *ParentFn, Type *RetTy,
+ const Twine &Name, Module *M, Value *&ParentFP);
bool outlineHandler(ActionHandler *Action, Function *SrcFn,
LandingPadInst *LPad, BasicBlock *StartBB,
FrameVarInfoMap &VarInfo);
// FIXME: Consider sinking this into lib/Target/X86 somehow. TargetLowering
// usually doesn't build LLVM IR, so that's probably the wrong place.
-Function *WinEHPrepare::createHandlerFunc(Type *RetTy, const Twine &Name,
- Module *M, Value *&ParentFP) {
+Function *WinEHPrepare::createHandlerFunc(Function *ParentFn, Type *RetTy,
+ const Twine &Name, Module *M,
+ Value *&ParentFP) {
// x64 uses a two-argument prototype where the parent FP is the second
// argument. x86 uses no arguments, just the incoming EBP value.
LLVMContext &Context = M->getContext();
+ Type *Int8PtrType = Type::getInt8PtrTy(Context);
FunctionType *FnType;
if (TheTriple.getArch() == Triple::x86_64) {
- Type *Int8PtrType = Type::getInt8PtrTy(Context);
Type *ArgTys[2] = {Int8PtrType, Int8PtrType};
FnType = FunctionType::get(RetTy, ArgTys, false);
} else {
assert(M);
Function *FrameAddressFn =
Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
- Value *Args[1] = {ConstantInt::get(Type::getInt32Ty(Context), 1)};
- ParentFP = CallInst::Create(FrameAddressFn, Args, "parent_fp",
- &Handler->getEntryBlock());
+ Function *RecoverFPFn =
+ Intrinsic::getDeclaration(M, Intrinsic::x86_seh_recoverfp);
+ IRBuilder<> Builder(&Handler->getEntryBlock());
+ Value *EBP =
+ Builder.CreateCall(FrameAddressFn, {Builder.getInt32(1)}, "ebp");
+ Value *ParentI8Fn = Builder.CreateBitCast(ParentFn, Int8PtrType);
+ ParentFP = Builder.CreateCall(RecoverFPFn, {ParentI8Fn, EBP});
}
return Handler;
}
Value *ParentFP;
Function *Handler;
if (Action->getType() == Catch) {
- Handler = createHandlerFunc(Int8PtrType, SrcFn->getName() + ".catch", M,
+ Handler = createHandlerFunc(SrcFn, Int8PtrType, SrcFn->getName() + ".catch", M,
ParentFP);
} else {
- Handler = createHandlerFunc(Type::getVoidTy(Context),
+ Handler = createHandlerFunc(SrcFn, Type::getVoidTy(Context),
SrcFn->getName() + ".cleanup", M, ParentFP);
}
Handler->setPersonalityFn(SrcFn->getPersonalityFn());
// value for this block but the value is a nullptr. This means that
// we have previously analyzed the block and determined that it did
// not contain any cleanup code. Based on the earlier analysis, we
- // know the the block must end in either an unconditional branch, a
+ // know the block must end in either an unconditional branch, a
// resume or a conditional branch that is predicated on a comparison
// with a selector. Either the resume or the selector dispatch
// would terminate the search for cleanup code, so the unconditional
MaybeCall = MaybeCall->getNextNode();
}
- // Look for outlined finally calls.
- if (CallSite FinallyCall = matchOutlinedFinallyCall(BB, MaybeCall)) {
- Function *Fin = FinallyCall.getCalledFunction();
- assert(Fin && "outlined finally call should be direct");
- auto *Action = new CleanupHandler(BB);
- Action->setHandlerBlockOrFunc(Fin);
- Actions.insertCleanupHandler(Action);
- CleanupHandlerMap[BB] = Action;
- DEBUG(dbgs() << " Found frontend-outlined finally call to "
- << Fin->getName() << " in block "
- << Action->getStartBlock()->getName() << "\n");
-
- // Split the block if there were more interesting instructions and look
- // for finally calls in the normal successor block.
- BasicBlock *SuccBB = BB;
- if (FinallyCall.getInstruction() != BB->getTerminator() &&
- FinallyCall.getInstruction()->getNextNode() !=
- BB->getTerminator()) {
- SuccBB =
- SplitBlock(BB, FinallyCall.getInstruction()->getNextNode(), DT);
- } else {
- if (FinallyCall.isInvoke()) {
+ // Look for outlined finally calls on x64, since those happen to match the
+ // prototype provided by the runtime.
+ if (TheTriple.getArch() == Triple::x86_64) {
+ if (CallSite FinallyCall = matchOutlinedFinallyCall(BB, MaybeCall)) {
+ Function *Fin = FinallyCall.getCalledFunction();
+ assert(Fin && "outlined finally call should be direct");
+ auto *Action = new CleanupHandler(BB);
+ Action->setHandlerBlockOrFunc(Fin);
+ Actions.insertCleanupHandler(Action);
+ CleanupHandlerMap[BB] = Action;
+ DEBUG(dbgs() << " Found frontend-outlined finally call to "
+ << Fin->getName() << " in block "
+ << Action->getStartBlock()->getName() << "\n");
+
+ // Split the block if there were more interesting instructions and
+ // look for finally calls in the normal successor block.
+ BasicBlock *SuccBB = BB;
+ if (FinallyCall.getInstruction() != BB->getTerminator() &&
+ FinallyCall.getInstruction()->getNextNode() !=
+ BB->getTerminator()) {
SuccBB =
- cast<InvokeInst>(FinallyCall.getInstruction())->getNormalDest();
+ SplitBlock(BB, FinallyCall.getInstruction()->getNextNode(), DT);
} else {
- SuccBB = BB->getUniqueSuccessor();
- assert(SuccBB &&
- "splitOutlinedFinallyCalls didn't insert a branch");
+ if (FinallyCall.isInvoke()) {
+ SuccBB = cast<InvokeInst>(FinallyCall.getInstruction())
+ ->getNormalDest();
+ } else {
+ SuccBB = BB->getUniqueSuccessor();
+ assert(SuccBB &&
+ "splitOutlinedFinallyCalls didn't insert a branch");
+ }
}
+ BB = SuccBB;
+ if (BB == EndBB)
+ return;
+ continue;
}
- BB = SuccBB;
- if (BB == EndBB)
- return;
- continue;
}
}