summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-09-09 21:10:03 +0000
committerReid Kleckner <rnk@google.com>2015-09-09 21:10:03 +0000
commit94b704c4691a8b10eff156277976702475bdfd3e (patch)
treee1a2622631516e9ea1177e4bc60ef8c45dfcaa7f /llvm/lib
parent81f3ccb505f8a594703bfc574442bb5c8bb841e3 (diff)
downloadbcm5719-llvm-94b704c4691a8b10eff156277976702475bdfd3e.tar.gz
bcm5719-llvm-94b704c4691a8b10eff156277976702475bdfd3e.zip
[SEH] Emit 32-bit SEH tables for the new EH IR
The 32-bit tables don't actually contain PC range data, so emitting them is incredibly simple. The 64-bit tables, on the other hand, use the same table for state numbering as well as label ranges. This makes things more difficult, so it will be implemented later. llvm-svn: 247192
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinException.cpp52
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinException.h2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp26
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp23
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp201
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp10
-rw-r--r--llvm/lib/Target/X86/X86WinEHState.cpp63
7 files changed, 279 insertions, 98 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index aedac5467c6..e706d73dee2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -161,7 +161,7 @@ void WinException::endFunction(const MachineFunction *MF) {
// Emit the tables appropriate to the personality function in use. If we
// don't recognize the personality, assume it uses an Itanium-style LSDA.
if (Per == EHPersonality::MSVC_Win64SEH)
- emitCSpecificHandlerTable();
+ emitCSpecificHandlerTable(MF);
else if (Per == EHPersonality::MSVC_X86SEH)
emitExceptHandlerTable(MF);
else if (Per == EHPersonality::MSVC_CXX)
@@ -222,9 +222,13 @@ const MCExpr *WinException::create32bitRef(const Value *V) {
/// imagerel32 LabelLPad; // Zero means __finally.
/// } Entries[NumEntries];
/// };
-void WinException::emitCSpecificHandlerTable() {
+void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
+ WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction());
+ if (!FuncInfo.SEHUnwindMap.empty())
+ report_fatal_error("x64 SEH tables not yet implemented");
+
// Simplifying assumptions for first implementation:
// - Cleanups are not implemented.
// - Filters are not implemented.
@@ -309,6 +313,15 @@ void WinException::emitCSpecificHandlerTable() {
}
}
+/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues
+/// are used in the old WinEH scheme, and they will be removed eventually.
+static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) {
+ if (Handler.is<MachineBasicBlock *>())
+ return Handler.get<MachineBasicBlock *>()->getSymbol();
+ else
+ return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>()));
+}
+
void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
const Function *F = MF->getFunction();
const Function *ParentF = MMI->getWinEHParent(F);
@@ -422,9 +435,9 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
int CatchHigh = TBME.CatchHigh;
if (CatchHigh == -1) {
for (WinEHHandlerType &HT : TBME.HandlerArray)
- CatchHigh = std::max(
- CatchHigh,
- FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]);
+ CatchHigh =
+ std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast<Function>(
+ HT.Handler.get<const Value *>())]);
}
assert(TBME.TryLow <= TBME.TryHigh);
@@ -464,13 +477,12 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
}
- OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
- OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
- OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
- if (HT.HandlerMBB) // Handler
- OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4);
- else
- OS.EmitValue(create32bitRef(HT.Handler), 4);
+ MCSymbol *HandlerSym = getMCSymbolForMBBOrGV(Asm, HT.Handler);
+
+ OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
+ OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
+ OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
+ OS.EmitValue(create32bitRef(HandlerSym), 4); // Handler
if (shouldEmitPersonality) {
if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) {
@@ -482,7 +494,8 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
} else {
MCSymbol *ParentFrameOffset =
Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
- GlobalValue::getRealLinkageName(HT.Handler->getName()));
+ GlobalValue::getRealLinkageName(
+ HT.Handler.get<const Value *>()->getName()));
const MCSymbolRefExpr *ParentFrameOffsetRef =
MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext);
OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
@@ -642,6 +655,19 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
BaseState = -2;
}
+ if (!FuncInfo.SEHUnwindMap.empty()) {
+ for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
+ MCSymbol *ExceptOrFinally =
+ UME.Handler.get<MachineBasicBlock *>()->getSymbol();
+ OS.EmitIntValue(UME.ToState, 4); // ToState
+ OS.EmitValue(create32bitRef(UME.Filter), 4); // Filter
+ OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally
+ }
+ return;
+ }
+ // FIXME: The following code is for the old landingpad-based SEH
+ // implementation. Remove it when possible.
+
// Build a list of pointers to LandingPadInfos and then sort by WinEHState.
const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
SmallVector<const LandingPadInfo *, 4> LPads;
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.h b/llvm/lib/CodeGen/AsmPrinter/WinException.h
index 7a80984c32e..aa159f5cf6e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.h
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.h
@@ -36,7 +36,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
/// True if this is a 64-bit target and we should use image relative offsets.
bool useImageRel32 = false;
- void emitCSpecificHandlerTable();
+ void emitCSpecificHandlerTable(const MachineFunction *MF);
/// Emit the EH table data for 32-bit and 64-bit functions using
/// the __CxxFrameHandler3 personality.
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 7bbb194ac19..15793f666ea 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -287,21 +287,31 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
addSEHHandlersForLPads(LPads);
}
+ // Calculate state numbers if we haven't already.
WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn);
if (Personality == EHPersonality::MSVC_CXX) {
- // Calculate state numbers and then map from funclet BBs to MBBs.
const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
+ } else {
+ const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+ calculateSEHStateNumbers(WinEHParentFn, EHInfo);
+ }
+
+ // Map all BB references in the EH data to MBBs.
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
for (WinEHHandlerType &H : TBME.HandlerArray)
- if (const auto *BB = dyn_cast<BasicBlock>(H.Handler))
- H.HandlerMBB = MBBMap[BB];
- // If there's an explicit EH registration node on the stack, record its
- // frame index.
- if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
- assert(StaticAllocaMap.count(EHInfo.EHRegNode));
- EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
+ if (const auto *BB =
+ dyn_cast<BasicBlock>(H.Handler.get<const Value *>()))
+ H.Handler = MBBMap[BB];
+ for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
+ const BasicBlock *BB = UME.Handler.get<const BasicBlock *>();
+ UME.Handler = MBBMap[BB];
}
+ // If there's an explicit EH registration node on the stack, record its
+ // frame index.
+ if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
+ assert(StaticAllocaMap.count(EHInfo.EHRegNode));
+ EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
}
// Copy the state numbers to LandingPadInfo for the current function, which
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1df4245bf0b..6fba18d60b2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1989,7 +1989,6 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
// and catchendpads for successors.
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
const BasicBlock *EHPadBB = I.getSuccessor(1);
- bool IsLandingPad = EHPadBB->isLandingPad();
const Value *Callee(I.getCalledValue());
const Function *Fn = dyn_cast<Function>(Callee);
@@ -2025,16 +2024,26 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
// Catchpads are conditional branches that add real MBB destinations and
// continue the loop. EH "end" pads are not real BBs and simply continue.
SmallVector<MachineBasicBlock *, 1> UnwindDests;
+ bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
+ EHPersonality::MSVC_CXX;
while (EHPadBB) {
const Instruction *Pad = EHPadBB->getFirstNonPHI();
- if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
- assert(FuncInfo.MBBMap[EHPadBB]);
- // Stop on cleanup pads and landingpads.
+ if (isa<LandingPadInst>(Pad)) {
+ // Stop on landingpads. They are not funclets.
UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
break;
+ } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
+ // Stop on cleanup pads. Cleanups are always funclet entries for all known
+ // personalities.
+ UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+ UnwindDests.back()->setIsEHFuncletEntry();
+ break;
} else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
// Add the catchpad handler to the possible destinations.
UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
+ // In MSVC C++, catchblocks are funclets and need prologues.
+ if (IsMSVCCXX)
+ UnwindDests.back()->setIsEHFuncletEntry();
EHPadBB = CPI->getUnwindDest();
} else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) {
EHPadBB = CEPI->getUnwindDest();
@@ -2043,13 +2052,11 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
}
}
- // Update successor info
+ // Update successor info.
// FIXME: The weights for catchpads will be wrong.
addSuccessorWithWeight(InvokeMBB, Return);
- for (auto *UnwindDest : UnwindDests) {
+ for (MachineBasicBlock *UnwindDest : UnwindDests) {
UnwindDest->setIsEHPad();
- if (!IsLandingPad)
- UnwindDest->setIsEHFuncletEntry();
addSuccessorWithWeight(InvokeMBB, UnwindDest);
}
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index c333c074900..ed3cd5d400b 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -2616,7 +2616,6 @@ static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
}
HT.Handler = CPI->getNormalDest();
- HT.HandlerMBB = nullptr;
// FIXME: Pass CPI->getArgOperand(1).
HT.CatchObjRecoverIdx = -1;
TBME.HandlerArray.push_back(HT);
@@ -2645,7 +2644,8 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
continue;
int N;
for (N = 0; N < NumHandlers; ++N) {
- if (Entry.HandlerArray[N].Handler != Handlers[N]->getHandlerBlockOrFunc())
+ if (Entry.HandlerArray[N].Handler.get<const Value *>() !=
+ Handlers[N]->getHandlerBlockOrFunc())
break; // breaks out of inner loop
}
// If all the handlers match, this is what we were looking for.
@@ -2692,7 +2692,6 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
}
HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc());
- HT.HandlerMBB = nullptr;
HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
TBME.HandlerArray.push_back(HT);
}
@@ -2949,13 +2948,45 @@ void WinEHNumbering::findActionRootLPads(const Function &F) {
}
}
-static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) {
- for (const BasicBlock *PredBlock : predecessors(&BB))
- if (isa<CatchPadInst>(PredBlock->getFirstNonPHI()))
- return PredBlock;
+static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) {
+ for (const BasicBlock *PredBlock : predecessors(BB))
+ if (auto *CPI = dyn_cast<CatchPadInst>(PredBlock->getFirstNonPHI()))
+ return CPI;
return nullptr;
}
+/// Find all the catchpads that feed directly into the catchendpad. Frontends
+/// using this personality should ensure that each catchendpad and catchpad has
+/// one or zero catchpad predecessors.
+///
+/// The following C++ generates the IR after it:
+/// try {
+/// } catch (A) {
+/// } catch (B) {
+/// }
+///
+/// IR:
+/// %catchpad.A
+/// catchpad [i8* A typeinfo]
+/// to label %catch.A unwind label %catchpad.B
+/// %catchpad.B
+/// catchpad [i8* B typeinfo]
+/// to label %catch.B unwind label %endcatches
+/// %endcatches
+/// catchendblock unwind to caller
+void findCatchPadsForCatchEndPad(
+ const BasicBlock *CatchEndBB,
+ SmallVectorImpl<const CatchPadInst *> &Handlers) {
+ const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB);
+ while (CPI) {
+ Handlers.push_back(CPI);
+ CPI = getSingleCatchPadPredecessor(CPI->getParent());
+ }
+ // We've pushed these back into reverse source order. Reverse them to get
+ // the list back into source order.
+ std::reverse(Handlers.begin(), Handlers.end());
+}
+
// Given BB which ends in an unwind edge, return the EHPad that this BB belongs
// to. If the unwind edge came from an invoke, return null.
static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
@@ -2970,9 +3001,9 @@ static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
}
-static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
- const BasicBlock &BB,
- int ParentState) {
+static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
+ const BasicBlock &BB,
+ int ParentState) {
assert(BB.isEHPad());
const Instruction *FirstNonPHI = BB.getFirstNonPHI();
// All catchpad instructions will be handled when we process their
@@ -2981,36 +3012,30 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
return;
if (isa<CatchEndPadInst>(FirstNonPHI)) {
- const BasicBlock *TryPad = &BB;
- const BasicBlock *LastTryPad = nullptr;
SmallVector<const CatchPadInst *, 2> Handlers;
- do {
- LastTryPad = TryPad;
- TryPad = getSingleCatchPadPredecessor(*TryPad);
- if (TryPad)
- Handlers.push_back(cast<CatchPadInst>(TryPad->getFirstNonPHI()));
- } while (TryPad);
- // We've pushed these back into reverse source order. Reverse them to get
- // the list back into source order.
- std::reverse(Handlers.begin(), Handlers.end());
+ findCatchPadsForCatchEndPad(&BB, Handlers);
+ const BasicBlock *FirstTryPad = Handlers.front()->getParent();
int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
- for (const BasicBlock *PredBlock : predecessors(LastTryPad))
+ for (const BasicBlock *PredBlock : predecessors(FirstTryPad))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
- calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow);
+ calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow);
int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
+
+ // catchpads are separate funclets in C++ EH due to the way rethrow works.
+ // In SEH, they aren't, so no invokes will unwind to the catchendpad.
FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
int TryHigh = CatchLow - 1;
for (const BasicBlock *PredBlock : predecessors(&BB))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
- calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow);
+ calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow);
int CatchHigh = FuncInfo.getLastStateNumber();
addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
- DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow
+ DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow
<< '\n');
- DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh
+ DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh
<< '\n');
- DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh
+ DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
<< '\n');
} else if (isa<CleanupPadInst>(FirstNonPHI)) {
int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
@@ -3019,7 +3044,73 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
<< BB.getName() << '\n');
for (const BasicBlock *PredBlock : predecessors(&BB))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
- calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState);
+ calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
+ } else if (isa<TerminatePadInst>(FirstNonPHI)) {
+ report_fatal_error("Not yet implemented!");
+ } else {
+ llvm_unreachable("unexpected EH Pad!");
+ }
+}
+
+static int addSEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
+ const Function *Filter, const BasicBlock *Handler) {
+ SEHUnwindMapEntry Entry;
+ Entry.ToState = ParentState;
+ Entry.Filter = Filter;
+ Entry.Handler = Handler;
+ FuncInfo.SEHUnwindMap.push_back(Entry);
+ return FuncInfo.SEHUnwindMap.size() - 1;
+}
+
+static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
+ const BasicBlock &BB,
+ int ParentState) {
+ assert(BB.isEHPad());
+ const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+ // All catchpad instructions will be handled when we process their
+ // respective catchendpad instruction.
+ if (isa<CatchPadInst>(FirstNonPHI))
+ return;
+
+ if (isa<CatchEndPadInst>(FirstNonPHI)) {
+ // Extract the filter function and the __except basic block and create a
+ // state for them.
+ SmallVector<const CatchPadInst *, 1> Handlers;
+ findCatchPadsForCatchEndPad(&BB, Handlers);
+ assert(Handlers.size() == 1 &&
+ "SEH doesn't have multiple handlers per __try");
+ const CatchPadInst *CPI = Handlers.front();
+ const BasicBlock *CatchPadBB = CPI->getParent();
+ const Function *Filter =
+ cast<Function>(CPI->getArgOperand(0)->stripPointerCasts());
+ int TryState =
+ addSEHHandler(FuncInfo, ParentState, Filter, CPI->getNormalDest());
+
+ // Everything in the __try block uses TryState as its parent state.
+ FuncInfo.EHPadStateMap[CPI] = TryState;
+ DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
+ << CatchPadBB->getName() << '\n');
+ for (const BasicBlock *PredBlock : predecessors(CatchPadBB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState);
+
+ // Everything in the __except block unwinds to ParentState, just like code
+ // outside the __try.
+ FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
+ DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
+ << BB.getName() << '\n');
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
+ } else if (isa<CleanupPadInst>(FirstNonPHI)) {
+ int CleanupState =
+ addSEHHandler(FuncInfo, ParentState, /*Filter=*/nullptr, &BB);
+ FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
+ DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
+ << BB.getName() << '\n');
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
} else if (isa<TerminatePadInst>(FirstNonPHI)) {
report_fatal_error("Not yet implemented!");
} else {
@@ -3027,6 +3118,37 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
}
}
+/// Check if the EH Pad unwinds to caller. Cleanups are a little bit of a
+/// special case because we have to look at the cleanupret instruction that uses
+/// the cleanuppad.
+static bool doesEHPadUnwindToCaller(const Instruction *EHPad) {
+ auto *CPI = dyn_cast<CleanupPadInst>(EHPad);
+ if (!CPI)
+ return EHPad->mayThrow();
+
+ // This cleanup does not return or unwind, so we say it unwinds to caller.
+ if (CPI->use_empty())
+ return true;
+
+ const Instruction *User = CPI->user_back();
+ if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
+ return CRI->unwindsToCaller();
+ return cast<CleanupEndPadInst>(User)->unwindsToCaller();
+}
+
+void llvm::calculateSEHStateNumbers(const Function *ParentFn,
+ WinEHFuncInfo &FuncInfo) {
+ // Don't compute state numbers twice.
+ if (!FuncInfo.SEHUnwindMap.empty())
+ return;
+
+ for (const BasicBlock &BB : *ParentFn) {
+ if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI()))
+ continue;
+ calculateExplicitSEHStateNumbers(FuncInfo, BB, -1);
+ }
+}
+
void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
WinEHFuncInfo &FuncInfo) {
// Return if it's already been done.
@@ -3041,28 +3163,9 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
// Skip cleanupendpads; they are exits, not entries.
if (isa<CleanupEndPadInst>(FirstNonPHI))
continue;
- // Check if the EH Pad has no exceptional successors (i.e. it unwinds to
- // caller). Cleanups are a little bit of a special case because their
- // control flow cannot be determined by looking at the pad but instead by
- // the pad's users.
- bool HasNoSuccessors = false;
- if (FirstNonPHI->mayThrow()) {
- HasNoSuccessors = true;
- } else if (auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) {
- if (CPI->use_empty()) {
- HasNoSuccessors = true;
- } else {
- const Instruction *User = CPI->user_back();
- if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
- HasNoSuccessors = CRI->unwindsToCaller();
- else
- HasNoSuccessors = cast<CleanupEndPadInst>(User)->unwindsToCaller();
- }
- }
-
- if (!HasNoSuccessors)
+ if (!doesEHPadUnwindToCaller(FirstNonPHI))
continue;
- calculateExplicitStateNumbers(FuncInfo, BB, -1);
+ calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
IsExplicit = true;
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b793213d955..0225b081edf 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -16880,6 +16880,16 @@ SDValue X86TargetLowering::LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Op);
MVT PtrVT = getPointerTy(DAG.getDataLayout());
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ if (isAsynchronousEHPersonality(
+ classifyEHPersonality(MF.getFunction()->getPersonalityFn()))) {
+ // For SEH, codegen catchret as a branch for now.
+ // FIXME: Insert something to restore the frame.
+ return DAG.getNode(ISD::BR, DL, MVT::Other, Chain, Dest);
+ }
+
+
unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX);
// Load the address of the destination block.
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp
index ccec7743b3b..38dc5db3430 100644
--- a/llvm/lib/Target/X86/X86WinEHState.cpp
+++ b/llvm/lib/Target/X86/X86WinEHState.cpp
@@ -68,9 +68,10 @@ private:
void unlinkExceptionRegistration(IRBuilder<> &Builder);
void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo);
void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo);
- void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
- Function &F, int BaseState);
+ void addStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
+ Function &F, int BaseState);
void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
+ void insertRestoreFrame(BasicBlock *BB);
Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
@@ -91,6 +92,7 @@ private:
Function *FrameRecover = nullptr;
Function *FrameAddress = nullptr;
Function *FrameEscape = nullptr;
+ Function *RestoreFrame = nullptr;
// Per-function state
EHPersonality Personality = EHPersonality::Unknown;
@@ -123,6 +125,8 @@ bool WinEHStatePass::doInitialization(Module &M) {
FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
+ RestoreFrame =
+ Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
return false;
}
@@ -414,7 +418,7 @@ void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
calculateWinCXXEHStateNumbers(&F, FuncInfo);
// The base state for the parent is -1.
- addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1);
+ addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
// Set up RegNodeEscapeIndex
int RegNodeEscapeIndex = escapeRegNode(F);
@@ -434,7 +438,7 @@ void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)});
RecoveredRegNode =
Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0));
- addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
+ addStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
}
}
@@ -470,11 +474,17 @@ int WinEHStatePass::escapeRegNode(Function &F) {
return Args.size() - 1;
}
-void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
- WinEHFuncInfo &FuncInfo,
- Function &F, int BaseState) {
- Function *RestoreFrame =
- Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
+void WinEHStatePass::insertRestoreFrame(BasicBlock *BB) {
+ Instruction *Start = BB->getFirstInsertionPt();
+ if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>()))
+ return;
+ IRBuilder<> Builder(Start);
+ Builder.CreateCall(RestoreFrame, {});
+}
+
+void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode,
+ WinEHFuncInfo &FuncInfo,
+ Function &F, int BaseState) {
// Iterate all the instructions and emit state number stores.
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
@@ -494,16 +504,14 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
}
}
- // Insert calls to llvm.x86.seh.restoreframe at catchret destinations.
- if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator())) {
- Instruction *Start = CR->getSuccessor()->begin();
- assert(!isa<PHINode>(Start) &&
- "winehprepare failed to demote phi after catchret");
- if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>()))
- continue;
- IRBuilder<> Builder(Start);
- Builder.CreateCall(RestoreFrame, {});
- }
+ // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. In
+ // SEH, insert them before the catchret.
+ // FIXME: We should probably do this as part of catchret lowering in the
+ // DAG.
+ if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator()))
+ insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH
+ ? CR->getParent()
+ : CR->getSuccessor());
}
}
@@ -519,6 +527,23 @@ void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
int RegNodeEscapeIndex = escapeRegNode(F);
FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex;
+ // If this funciton uses the new EH IR, use the explicit state numbering
+ // algorithm and return early.
+ bool UsesLPads = false;
+ for (BasicBlock &BB : F) {
+ if (BB.isLandingPad()) {
+ UsesLPads = true;
+ break;
+ }
+ }
+ if (!UsesLPads) {
+ calculateSEHStateNumbers(&F, FuncInfo);
+ addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
+ return;
+ }
+ // FIXME: Delete the rest of this code and clean things up when new EH is
+ // done.
+
// Iterate all the instructions and emit state number stores.
int CurState = 0;
SmallPtrSet<BasicBlock *, 4> ExceptBlocks;
OpenPOWER on IntegriCloud