#define DEBUG_TYPE "winehstate"
+namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); }
+
namespace {
class WinEHStatePass : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid.
- WinEHStatePass() : FunctionPass(ID) {}
+ WinEHStatePass() : FunctionPass(ID) {
+ initializeWinEHStatePassPass(*PassRegistry::getPassRegistry());
+ }
bool runOnFunction(Function &Fn) override;
void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
void unlinkExceptionRegistration(IRBuilder<> &Builder);
- void addCXXStateStores(Function &F, MachineModuleInfo &MMI);
- void addSEHStateStores(Function &F, MachineModuleInfo &MMI);
+ void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo);
+ void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo);
void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
Function &F, int BaseState);
void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
char WinEHStatePass::ID = 0;
+INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
+ "Insert stores for EH state numbers", false, false)
+
bool WinEHStatePass::doInitialization(Module &M) {
TheModule = &M;
- FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::frameescape);
- FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::framerecover);
+ FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
+ FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
return false;
}
void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
// This pass should only insert a stack allocation, memory accesses, and
- // framerecovers.
+ // localrecovers.
AU.setPreservesCFG();
}
emitExceptionRegistrationRecord(&F);
- auto *MMIPtr = getAnalysisIfAvailable<MachineModuleInfo>();
- assert(MMIPtr && "MachineModuleInfo should always be available");
- MachineModuleInfo &MMI = *MMIPtr;
+ auto *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+ // If MMI is null, create our own WinEHFuncInfo. This only happens in opt
+ // tests.
+ std::unique_ptr<WinEHFuncInfo> FuncInfoPtr;
+ if (!MMI)
+ FuncInfoPtr.reset(new WinEHFuncInfo());
+ WinEHFuncInfo &FuncInfo =
+ *(MMI ? &MMI->getWinEHFuncInfo(&F) : FuncInfoPtr.get());
+
switch (Personality) {
default: llvm_unreachable("unexpected personality function");
- case EHPersonality::MSVC_CXX: addCXXStateStores(F, MMI); break;
- case EHPersonality::MSVC_X86SEH: addSEHStateStores(F, MMI); break;
+ case EHPersonality::MSVC_CXX:
+ addCXXStateStores(F, FuncInfo);
+ break;
+ case EHPersonality::MSVC_X86SEH:
+ addSEHStateStores(F, FuncInfo);
+ break;
}
// Reset per-function state.
FunctionType *TargetFuncTy =
FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
/*isVarArg=*/false);
- Function *Trampoline = Function::Create(
- TrampolineTy, GlobalValue::InternalLinkage,
- Twine("__ehhandler$") + ParentFunc->getName(), TheModule);
+ Function *Trampoline =
+ Function::Create(TrampolineTy, GlobalValue::InternalLinkage,
+ Twine("__ehhandler$") + GlobalValue::getRealLinkageName(
+ ParentFunc->getName()),
+ TheModule);
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
IRBuilder<> Builder(EntryBB);
Value *LSDA = emitEHLSDA(Builder, ParentFunc);
Builder.CreateStore(Next, FSZero);
}
-void WinEHStatePass::addCXXStateStores(Function &F, MachineModuleInfo &MMI) {
- WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
+void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
calculateWinCXXEHStateNumbers(&F, FuncInfo);
// The base state for the parent is -1.
}
/// Escape RegNode so that we can access it from child handlers. Find the call
-/// to frameescape, if any, in the entry block and append RegNode to the list
+/// to localescape, if any, in the entry block and append RegNode to the list
/// of arguments.
int WinEHStatePass::escapeRegNode(Function &F) {
- // Find the call to frameescape and extract its arguments.
+ // Find the call to localescape and extract its arguments.
IntrinsicInst *EscapeCall = nullptr;
for (Instruction &I : F.getEntryBlock()) {
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
- if (II && II->getIntrinsicID() == Intrinsic::frameescape) {
+ if (II && II->getIntrinsicID() == Intrinsic::localescape) {
EscapeCall = II;
break;
}
// Replace the call (if it exists) with new one. Otherwise, insert at the end
// of the entry block.
- IRBuilder<> Builder(&F.getEntryBlock(),
- EscapeCall ? EscapeCall : F.getEntryBlock().end());
+ Instruction *InsertPt = EscapeCall;
+ if (!EscapeCall)
+ InsertPt = F.getEntryBlock().getTerminator();
+ IRBuilder<> Builder(&F.getEntryBlock(), InsertPt);
Builder.CreateCall(FrameEscape, Args);
if (EscapeCall)
EscapeCall->eraseFromParent();
insertStateNumberStore(ParentRegNode, CI, BaseState);
} else if (auto *II = dyn_cast<InvokeInst>(&I)) {
// Look up the state number of the landingpad this unwinds to.
- LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst();
+ Instruction *PadInst = II->getUnwindDest()->getFirstNonPHI();
// FIXME: Why does this assertion fail?
- //assert(FuncInfo.LandingPadStateMap.count(LPI) && "LP has no state!");
- int State = FuncInfo.LandingPadStateMap[LPI];
+ //assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
+ int State = FuncInfo.EHPadStateMap[PadInst];
insertStateNumberStore(ParentRegNode, II, State);
}
}
/// handlers aren't outlined and the runtime doesn't have to figure out which
/// catch handler frame to unwind to.
/// FIXME: __finally blocks are outlined, so this approach may break down there.
-void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
- WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
-
+void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
// Remember and return the index that we used. We save it in WinEHFuncInfo so
// that we can lower llvm.x86.seh.recoverfp later in filter functions without
// too much trouble.
// Look up the state number of the landingpad this unwinds to.
LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst();
auto InsertionPair =
- FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, CurState));
+ FuncInfo.EHPadStateMap.insert(std::make_pair(LPI, CurState));
auto Iter = InsertionPair.first;
int &State = Iter->second;
bool Inserted = InsertionPair.second;
for (auto &Handler : ActionList) {
if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) {
auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc());
+#ifndef NDEBUG
+ for (BasicBlock *Pred : predecessors(BA->getBasicBlock()))
+ assert(Pred->isLandingPad() &&
+ "WinEHPrepare failed to split block");
+#endif
ExceptBlocks.insert(BA->getBasicBlock());
}
}