summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp30
-rw-r--r--llvm/lib/CodeGen/MachineModuleInfo.cpp19
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp56
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp20
4 files changed, 117 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp
index 8c90bed2b5a..2737a5323d6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp
@@ -212,9 +212,14 @@ void Win64Exception::emitCSpecificHandlerTable() {
if (isCatchEHSelector(Selector))
++NumEntries;
}
+ NumEntries += CSE.LPad->SEHHandlers.size();
}
Asm->OutStreamer.EmitIntValue(NumEntries, 4);
+ // If there are no actions, we don't need to iterate again.
+ if (NumEntries == 0)
+ return;
+
// Emit the four-label records for each call site entry. The table has to be
// sorted in layout order, and the call sites should already be sorted.
for (const CallSiteEntry &CSE : CallSites) {
@@ -240,6 +245,31 @@ void Win64Exception::emitCSpecificHandlerTable() {
End = createImageRel32(EHFuncEndSym);
}
+ // Emit an entry for each action.
+ for (SEHHandler Handler : LPad->SEHHandlers) {
+ Asm->OutStreamer.EmitValue(Begin, 4);
+ Asm->OutStreamer.EmitValue(End, 4);
+
+ // Emit the filter or finally function pointer, if present. Otherwise,
+ // emit '1' to indicate a catch-all.
+ const Function *F = Handler.FilterOrFinally;
+ if (F)
+ Asm->OutStreamer.EmitValue(createImageRel32(Asm->getSymbol(F)), 4);
+ else
+ Asm->OutStreamer.EmitIntValue(1, 4);
+
+ // Emit the recovery address, if present. Otherwise, this must be a
+ // finally.
+ const BlockAddress *BA = Handler.RecoverBA;
+ if (BA)
+ Asm->OutStreamer.EmitValue(
+ createImageRel32(Asm->GetBlockAddressSymbol(BA)), 4);
+ else
+ Asm->OutStreamer.EmitIntValue(0, 4);
+ }
+ if (!LPad->SEHHandlers.empty())
+ continue;
+
// These aren't really type info globals, they are actually pointers to
// filter functions ordered by selector. The zero selector is used for
// cleanups, so slot zero corresponds to selector 1.
diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp
index e8bd1f8e6d9..e4f2aea287f 100644
--- a/llvm/lib/CodeGen/MachineModuleInfo.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp
@@ -469,6 +469,25 @@ MachineModuleInfo::addClauseForLandingPad(MachineBasicBlock *LandingPad) {
return ClauseLabel;
}
+void MachineModuleInfo::addSEHCatchHandler(MachineBasicBlock *LandingPad,
+ const Function *Filter,
+ const BlockAddress *RecoverBA) {
+ LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
+ SEHHandler Handler;
+ Handler.FilterOrFinally = Filter;
+ Handler.RecoverBA = RecoverBA;
+ LP.SEHHandlers.push_back(Handler);
+}
+
+void MachineModuleInfo::addSEHCleanupHandler(MachineBasicBlock *LandingPad,
+ const Function *Cleanup) {
+ LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
+ SEHHandler Handler;
+ Handler.FilterOrFinally = Cleanup;
+ Handler.RecoverBA = nullptr;
+ LP.SEHHandlers.push_back(Handler);
+}
+
/// TidyLandingPads - Remap landing pad labels and remove any deleted landing
/// pads.
void MachineModuleInfo::TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 4b8ae32e9a5..bb40326ba2d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -270,12 +270,21 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
}
// Mark landing pad blocks.
- for (BB = Fn->begin(); BB != EB; ++BB)
+ const LandingPadInst *LP = nullptr;
+ for (BB = Fn->begin(); BB != EB; ++BB) {
if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator()))
MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
+ if (BB->isLandingPad())
+ LP = BB->getLandingPadInst();
+ }
- // Calculate EH numbers for WinEH.
- if (fn.hasFnAttribute("wineh-parent")) {
+ // Calculate EH numbers for MSVC C++ EH and save SEH handlers if necessary.
+ EHPersonality Personality = EHPersonality::Unknown;
+ if (LP)
+ Personality = classifyEHPersonality(LP->getPersonalityFn());
+ if (Personality == EHPersonality::MSVC_Win64SEH) {
+ addSEHHandlersForLPads();
+ } else if (Personality == EHPersonality::MSVC_CXX) {
const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn);
if (FI.LandingPadStateMap.empty()) {
@@ -287,6 +296,47 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
}
}
+void FunctionLoweringInfo::addSEHHandlersForLPads() {
+ MachineModuleInfo &MMI = MF->getMMI();
+
+ // Iterate over all landing pads with llvm.eh.actions calls.
+ for (const BasicBlock &BB : *Fn) {
+ const LandingPadInst *LP = BB.getLandingPadInst();
+ if (!LP)
+ continue;
+ const IntrinsicInst *ActionsCall =
+ dyn_cast<IntrinsicInst>(LP->getNextNode());
+ if (!ActionsCall ||
+ ActionsCall->getIntrinsicID() != Intrinsic::eh_actions)
+ continue;
+
+ // Parse the llvm.eh.actions call we found.
+ MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
+ SmallVector<ActionHandler *, 4> Actions;
+ parseEHActions(ActionsCall, Actions);
+
+ // Iterate EH actions from most to least precedence, which means
+ // iterating in reverse.
+ for (auto I = Actions.rbegin(), E = Actions.rend(); I != E; ++I) {
+ ActionHandler *Action = *I;
+ if (auto *CH = dyn_cast<CatchHandler>(Action)) {
+ const auto *Filter =
+ dyn_cast<Function>(CH->getSelector()->stripPointerCasts());
+ assert((Filter || CH->getSelector()->isNullValue()) &&
+ "expected function or catch-all");
+ const auto *RecoverBA =
+ cast<BlockAddress>(CH->getHandlerBlockOrFunc());
+ MMI.addSEHCatchHandler(LPadMBB, Filter, RecoverBA);
+ } else {
+ assert(isa<CleanupHandler>(Action));
+ const auto *Fini = cast<Function>(Action->getHandlerBlockOrFunc());
+ MMI.addSEHCleanupHandler(LPadMBB, Fini);
+ }
+ }
+ DeleteContainerPointers(Actions);
+ }
+}
+
void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
WinEHUnwindMapEntry UME;
UME.ToState = ToState;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 1e116dddafa..235cda64776 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -911,7 +911,7 @@ void SelectionDAGISel::DoInstructionSelection() {
/// PrepareEHLandingPad - Emit an EH_LABEL, set up live-in registers, and
/// do other setup for EH landing-pad blocks.
-void SelectionDAGISel::PrepareEHLandingPad() {
+bool SelectionDAGISel::PrepareEHLandingPad() {
MachineBasicBlock *MBB = FuncInfo->MBB;
const TargetRegisterClass *PtrRC = TLI->getRegClassFor(TLI->getPointerTy());
@@ -937,12 +937,12 @@ void SelectionDAGISel::PrepareEHLandingPad() {
if (isMSVCEHPersonality(Personality)) {
SmallVector<MachineBasicBlock *, 4> ClauseBBs;
- const IntrinsicInst *Actions =
+ const IntrinsicInst *ActionsCall =
dyn_cast<IntrinsicInst>(LLVMBB->getFirstInsertionPt());
// Get all invoke BBs that unwind to this landingpad.
SmallVector<MachineBasicBlock *, 4> InvokeBBs(MBB->pred_begin(),
MBB->pred_end());
- if (Actions && Actions->getIntrinsicID() == Intrinsic::eh_actions) {
+ if (ActionsCall && ActionsCall->getIntrinsicID() == Intrinsic::eh_actions) {
// If this is a call to llvm.eh.actions followed by indirectbr, then we've
// run WinEHPrepare, and we should remove this block from the machine CFG.
// Mark the targets of the indirectbr as landingpads instead.
@@ -951,11 +951,15 @@ void SelectionDAGISel::PrepareEHLandingPad() {
// Add the edge from the invoke to the clause.
for (MachineBasicBlock *InvokeBB : InvokeBBs)
InvokeBB->addSuccessor(ClauseBB);
+
+ // Mark the clause as a landing pad or MI passes will delete it.
+ ClauseBB->setIsLandingPad();
}
} else {
// Otherwise, we haven't done the preparation, and we need to invent some
// clause basic blocks that branch into the landingpad.
// FIXME: Remove this code once SEH preparation works.
+ ActionsCall = nullptr;
// Make virtual registers and a series of labels that fill in values for
// the clauses.
@@ -1017,7 +1021,10 @@ void SelectionDAGISel::PrepareEHLandingPad() {
WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction());
MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]);
}
- return;
+
+ // Select instructions for the landingpad if there was no llvm.eh.actions
+ // call.
+ return ActionsCall == nullptr;
}
// Mark exception register as live in.
@@ -1027,6 +1034,8 @@ void SelectionDAGISel::PrepareEHLandingPad() {
// Mark exception selector register as live in.
if (unsigned Reg = TLI->getExceptionSelectorRegister())
FuncInfo->ExceptionSelectorVirtReg = MBB->addLiveIn(Reg, PtrRC);
+
+ return true;
}
/// isFoldedOrDeadInstruction - Return true if the specified instruction is
@@ -1197,7 +1206,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FuncInfo->ExceptionPointerVirtReg = 0;
FuncInfo->ExceptionSelectorVirtReg = 0;
if (LLVMBB->isLandingPad())
- PrepareEHLandingPad();
+ if (!PrepareEHLandingPad())
+ continue;
// Before doing SelectionDAG ISel, see if FastISel has been requested.
if (FastIS) {
OpenPOWER on IntegriCloud