mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:50:30 +00:00
[WinEH] Add some support for code generating catchpad
We can now run 32-bit programs with empty catch bodies. The next step is to change PEI so that we get funclet prologues and epilogues. llvm-svn: 246235
This commit is contained in:
parent
78bdd69848
commit
1f54bd38ce
@ -165,6 +165,9 @@ public:
|
||||
unsigned CreateRegs(Type *Ty);
|
||||
|
||||
unsigned InitializeRegForValue(const Value *V) {
|
||||
// Tokens never live in vregs.
|
||||
if (V->getType()->isTokenTy())
|
||||
return 0;
|
||||
unsigned &R = ValueMap[V];
|
||||
assert(R == 0 && "Already initialized this value register!");
|
||||
return R = CreateRegs(V->getType());
|
||||
|
@ -591,6 +591,10 @@ namespace ISD {
|
||||
/// take a chain as input and return a chain.
|
||||
EH_LABEL,
|
||||
|
||||
CATCHRET,
|
||||
|
||||
CLEANUPRET,
|
||||
|
||||
/// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a
|
||||
/// value, the same type as the pointer type for the system, and an output
|
||||
/// chain.
|
||||
|
@ -85,18 +85,21 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
|
||||
|
||||
/// Alignment of the basic block. Zero if the basic block does not need to be
|
||||
/// aligned. The alignment is specified as log2(bytes).
|
||||
unsigned Alignment;
|
||||
unsigned Alignment = 0;
|
||||
|
||||
/// Indicate that this basic block is entered via an exception handler.
|
||||
bool IsLandingPad;
|
||||
bool IsEHPad = false;
|
||||
|
||||
/// Indicate that this basic block is potentially the target of an indirect
|
||||
/// branch.
|
||||
bool AddressTaken;
|
||||
bool AddressTaken = false;
|
||||
|
||||
/// Indicate that this basic block is the entry block of an EH funclet.
|
||||
bool IsEHFuncletEntry = false;
|
||||
|
||||
/// \brief since getSymbol is a relatively heavy-weight operation, the symbol
|
||||
/// is only computed once and is cached.
|
||||
mutable MCSymbol *CachedMCSymbol;
|
||||
mutable MCSymbol *CachedMCSymbol = nullptr;
|
||||
|
||||
// Intrusive list support
|
||||
MachineBasicBlock() {}
|
||||
@ -352,16 +355,22 @@ public:
|
||||
|
||||
/// Returns true if the block is a landing pad. That is this basic block is
|
||||
/// entered via an exception handler.
|
||||
bool isLandingPad() const { return IsLandingPad; }
|
||||
bool isEHPad() const { return IsEHPad; }
|
||||
|
||||
/// Indicates the block is a landing pad. That is this basic block is entered
|
||||
/// via an exception handler.
|
||||
void setIsLandingPad(bool V = true) { IsLandingPad = V; }
|
||||
void setIsEHPad(bool V = true) { IsEHPad = V; }
|
||||
|
||||
/// If this block has a successor that is a landing pad, return it. Otherwise
|
||||
/// return NULL.
|
||||
const MachineBasicBlock *getLandingPadSuccessor() const;
|
||||
|
||||
/// Returns true if this is the entry block of an EH funclet.
|
||||
bool isEHFuncletEntry() const { return IsEHFuncletEntry; }
|
||||
|
||||
/// Indicates if this is the entry block of an EH funclet.
|
||||
void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; }
|
||||
|
||||
// Code Layout methods.
|
||||
|
||||
/// Move 'this' block before or after the specified block. This only moves
|
||||
|
@ -163,6 +163,7 @@ class MachineModuleInfo : public ImmutablePass {
|
||||
|
||||
bool CallsEHReturn;
|
||||
bool CallsUnwindInit;
|
||||
bool HasEHFunclets;
|
||||
|
||||
/// DbgInfoAvailable - True if debugging information is available
|
||||
/// in this module.
|
||||
@ -371,6 +372,12 @@ public:
|
||||
return LandingPads;
|
||||
}
|
||||
|
||||
bool hasEHFunclets() const {
|
||||
return HasEHFunclets;
|
||||
}
|
||||
|
||||
void setHasEHFunclets(bool V) { HasEHFunclets = true; }
|
||||
|
||||
/// setCallSiteLandingPad - Map the landing pad's EH symbol to the call
|
||||
/// site indexes.
|
||||
void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef<unsigned> Sites);
|
||||
|
@ -264,6 +264,7 @@ private:
|
||||
/// personality specific tasks. Returns true if the block should be
|
||||
/// instruction selected, false if no code should be emitted for it.
|
||||
bool PrepareEHLandingPad();
|
||||
bool PrepareEHPad();
|
||||
|
||||
/// \brief Perform instruction selection on all basic blocks in the function.
|
||||
void SelectAllBasicBlocks(const Function &Fn);
|
||||
|
@ -27,6 +27,7 @@ class InvokeInst;
|
||||
class IntrinsicInst;
|
||||
class LandingPadInst;
|
||||
class MCSymbol;
|
||||
class MachineBasicBlock;
|
||||
class Value;
|
||||
|
||||
enum ActionType { Catch, Cleanup };
|
||||
@ -123,6 +124,7 @@ struct WinEHHandlerType {
|
||||
GlobalVariable *TypeDescriptor;
|
||||
int CatchObjRecoverIdx;
|
||||
const Value *Handler;
|
||||
MachineBasicBlock *HandlerMBB;
|
||||
};
|
||||
|
||||
struct WinEHTryBlockMapEntry {
|
||||
|
@ -451,6 +451,8 @@ def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>;
|
||||
def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
|
||||
def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
|
||||
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
|
||||
def catchret : SDNode<"ISD::CATCHRET" , SDTBr, [SDNPHasChain]>;
|
||||
|
||||
def trap : SDNode<"ISD::TRAP" , SDTNone,
|
||||
[SDNPHasChain, SDNPSideEffect]>;
|
||||
def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone,
|
||||
|
@ -2485,7 +2485,8 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
|
||||
}
|
||||
|
||||
// Print the main label for the block.
|
||||
if (MBB.pred_empty() || isBlockOnlyReachableByFallthrough(&MBB)) {
|
||||
if (MBB.pred_empty() ||
|
||||
(isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
|
||||
if (isVerbose()) {
|
||||
// NOTE: Want this comment at start of line, don't emit with AddComment.
|
||||
OutStreamer->emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false);
|
||||
@ -2523,7 +2524,7 @@ bool AsmPrinter::
|
||||
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
|
||||
// If this is a landing pad, it isn't a fall through. If it has no preds,
|
||||
// then nothing falls through to it.
|
||||
if (MBB->isLandingPad() || MBB->pred_empty())
|
||||
if (MBB->isEHPad() || MBB->pred_empty())
|
||||
return false;
|
||||
|
||||
// If there isn't exactly one predecessor, it can't be a fall through.
|
||||
|
@ -62,6 +62,7 @@ void WinException::beginFunction(const MachineFunction *MF) {
|
||||
|
||||
// If any landing pads survive, we need an EH table.
|
||||
bool hasLandingPads = !MMI->getLandingPads().empty();
|
||||
bool hasEHFunclets = MMI->hasEHFunclets();
|
||||
|
||||
const Function *F = MF->getFunction();
|
||||
const Function *ParentF = MMI->getWinEHParent(F);
|
||||
@ -78,19 +79,21 @@ void WinException::beginFunction(const MachineFunction *MF) {
|
||||
F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
|
||||
F->needsUnwindTableEntry();
|
||||
|
||||
shouldEmitPersonality = forceEmitPersonality || (hasLandingPads &&
|
||||
PerEncoding != dwarf::DW_EH_PE_omit && Per);
|
||||
shouldEmitPersonality =
|
||||
forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
|
||||
PerEncoding != dwarf::DW_EH_PE_omit && Per);
|
||||
|
||||
unsigned LSDAEncoding = TLOF.getLSDAEncoding();
|
||||
shouldEmitLSDA = shouldEmitPersonality &&
|
||||
LSDAEncoding != dwarf::DW_EH_PE_omit;
|
||||
|
||||
// If we're not using CFI, we don't want the CFI or the personality. If
|
||||
// WinEHPrepare outlined something, we should emit the LSDA.
|
||||
// If we're not using CFI, we don't want the CFI or the personality, but we
|
||||
// might want EH tables if we had EH pads.
|
||||
// FIXME: If WinEHPrepare outlined something, we should emit the LSDA. Remove
|
||||
// this once WinEHPrepare stops doing that.
|
||||
if (!Asm->MAI->usesWindowsCFI()) {
|
||||
bool HasOutlinedChildren =
|
||||
F->hasFnAttribute("wineh-parent") && F == ParentF;
|
||||
shouldEmitLSDA = HasOutlinedChildren;
|
||||
shouldEmitLSDA =
|
||||
hasEHFunclets || (F->hasFnAttribute("wineh-parent") && F == ParentF);
|
||||
shouldEmitPersonality = false;
|
||||
return;
|
||||
}
|
||||
@ -185,7 +188,10 @@ const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
|
||||
const MCExpr *WinException::create32bitRef(const Value *V) {
|
||||
if (!V)
|
||||
return MCConstantExpr::create(0, Asm->OutContext);
|
||||
return create32bitRef(Asm->getSymbol(cast<GlobalValue>(V)));
|
||||
// FIXME: Delete the GlobalValue case once the new IR is fully functional.
|
||||
if (const auto *GV = dyn_cast<GlobalValue>(V))
|
||||
return create32bitRef(Asm->getSymbol(GV));
|
||||
return create32bitRef(MMI->getAddrLabelSymbol(cast<BasicBlock>(V)));
|
||||
}
|
||||
|
||||
/// Emit the language-specific data that __C_specific_handler expects. This
|
||||
@ -320,14 +326,17 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
|
||||
|
||||
extendIP2StateTable(MF, ParentF, FuncInfo);
|
||||
|
||||
// Defer emission until we've visited the parent function and all the catch
|
||||
// handlers. Cleanups don't contribute to the ip2state table, so don't count
|
||||
// them.
|
||||
if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
|
||||
return;
|
||||
++FuncInfo.NumIPToStateFuncsVisited;
|
||||
if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
|
||||
return;
|
||||
if (!MMI->hasEHFunclets()) {
|
||||
// Defer emission until we've visited the parent function and all the
|
||||
// catch handlers. Cleanups don't contribute to the ip2state table, so
|
||||
// don't count them.
|
||||
if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
|
||||
return;
|
||||
++FuncInfo.NumIPToStateFuncsVisited;
|
||||
if (FuncInfo.NumIPToStateFuncsVisited !=
|
||||
FuncInfo.CatchHandlerMaxState.size())
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
|
||||
emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName);
|
||||
@ -410,11 +419,13 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
|
||||
|
||||
HandlerMaps.push_back(HandlerMapXData);
|
||||
|
||||
int CatchHigh = -1;
|
||||
for (WinEHHandlerType &HT : TBME.HandlerArray)
|
||||
CatchHigh =
|
||||
std::max(CatchHigh,
|
||||
FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]);
|
||||
int CatchHigh = TBME.CatchHigh;
|
||||
if (CatchHigh == -1) {
|
||||
for (WinEHHandlerType &HT : TBME.HandlerArray)
|
||||
CatchHigh = std::max(
|
||||
CatchHigh,
|
||||
FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]);
|
||||
}
|
||||
|
||||
assert(TBME.TryLow <= TBME.TryHigh);
|
||||
OS.EmitIntValue(TBME.TryLow, 4); // TryLow
|
||||
@ -456,7 +467,10 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
|
||||
OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
|
||||
OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
|
||||
OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
|
||||
OS.EmitValue(create32bitRef(HT.Handler), 4); // Handler
|
||||
if (HT.HandlerMBB) // Handler
|
||||
OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4);
|
||||
else
|
||||
OS.EmitValue(create32bitRef(HT.Handler), 4);
|
||||
|
||||
if (shouldEmitPersonality) {
|
||||
MCSymbol *ParentFrameOffset =
|
||||
|
@ -1001,7 +1001,7 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
|
||||
// Failing case: the only way IBB can be reached from PBB is via
|
||||
// exception handling. Happens for landing pads. Would be nice to have
|
||||
// a bit in the edge so we didn't have to do all this.
|
||||
if (IBB->isLandingPad()) {
|
||||
if (IBB->isEHPad()) {
|
||||
MachineFunction::iterator IP = PBB; IP++;
|
||||
MachineBasicBlock *PredNextBB = nullptr;
|
||||
if (IP != MF.end())
|
||||
@ -1178,13 +1178,13 @@ ReoptimizeBlock:
|
||||
// explicitly. Landing pads should not do this since the landing-pad table
|
||||
// points to this block. Blocks with their addresses taken shouldn't be
|
||||
// optimized away.
|
||||
if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) {
|
||||
if (IsEmptyBlock(MBB) && !MBB->isEHPad() && !MBB->hasAddressTaken()) {
|
||||
// Dead block? Leave for cleanup later.
|
||||
if (MBB->pred_empty()) return MadeChange;
|
||||
|
||||
if (FallThrough == MF.end()) {
|
||||
// TODO: Simplify preds to not branch here if possible!
|
||||
} else if (FallThrough->isLandingPad()) {
|
||||
} else if (FallThrough->isEHPad()) {
|
||||
// Don't rewrite to a landing pad fallthough. That could lead to the case
|
||||
// where a BB jumps to more than one landing pad.
|
||||
// TODO: Is it ever worth rewriting predecessors which don't already
|
||||
@ -1241,7 +1241,7 @@ ReoptimizeBlock:
|
||||
// AnalyzeBranch.
|
||||
if (PriorCond.empty() && !PriorTBB && MBB->pred_size() == 1 &&
|
||||
PrevBB.succ_size() == 1 &&
|
||||
!MBB->hasAddressTaken() && !MBB->isLandingPad()) {
|
||||
!MBB->hasAddressTaken() && !MBB->isEHPad()) {
|
||||
DEBUG(dbgs() << "\nMerging into block: " << PrevBB
|
||||
<< "From MBB: " << *MBB);
|
||||
// Remove redundant DBG_VALUEs first.
|
||||
@ -1472,7 +1472,7 @@ ReoptimizeBlock:
|
||||
// see if it has a fall-through into its successor.
|
||||
bool CurFallsThru = MBB->canFallThrough();
|
||||
|
||||
if (!MBB->isLandingPad()) {
|
||||
if (!MBB->isEHPad()) {
|
||||
// Check all the predecessors of this block. If one of them has no fall
|
||||
// throughs, move this block right after it.
|
||||
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
|
||||
@ -1523,7 +1523,7 @@ ReoptimizeBlock:
|
||||
// fallthrough to happen.
|
||||
if (SuccBB != MBB && &*SuccPrev != MBB &&
|
||||
!SuccPrev->canFallThrough() && !CurUnAnalyzable &&
|
||||
!SuccBB->isLandingPad()) {
|
||||
!SuccBB->isEHPad()) {
|
||||
MBB->moveBefore(SuccBB);
|
||||
MadeChange = true;
|
||||
goto ReoptimizeBlock;
|
||||
|
@ -299,7 +299,7 @@ void LiveIntervals::computeLiveInRegUnits() {
|
||||
const MachineBasicBlock *MBB = MFI;
|
||||
|
||||
// We only care about ABI blocks: Entry + landing pads.
|
||||
if ((MFI != MF->begin() && !MBB->isLandingPad()) || MBB->livein_empty())
|
||||
if ((MFI != MF->begin() && !MBB->isEHPad()) || MBB->livein_empty())
|
||||
continue;
|
||||
|
||||
// Create phi-defs at Begin for all live-in registers.
|
||||
|
@ -598,7 +598,7 @@ void LiveVariables::runOnBlock(MachineBasicBlock *MBB, const unsigned NumRegs) {
|
||||
for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(),
|
||||
SE = MBB->succ_end(); SI != SE; ++SI) {
|
||||
MachineBasicBlock *SuccMBB = *SI;
|
||||
if (SuccMBB->isLandingPad())
|
||||
if (SuccMBB->isEHPad())
|
||||
continue;
|
||||
for (unsigned LI : SuccMBB->liveins()) {
|
||||
if (!TRI->isInAllocatableClass(LI))
|
||||
|
@ -368,7 +368,7 @@ bool MIParser::parseBasicBlockDefinition(
|
||||
MBB->setAlignment(Alignment);
|
||||
if (HasAddressTaken)
|
||||
MBB->setHasAddressTaken();
|
||||
MBB->setIsLandingPad(IsLandingPad);
|
||||
MBB->setIsEHPad(IsLandingPad);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ void MIPrinter::print(const MachineBasicBlock &MBB) {
|
||||
OS << "address-taken";
|
||||
HasAttributes = true;
|
||||
}
|
||||
if (MBB.isLandingPad()) {
|
||||
if (MBB.isEHPad()) {
|
||||
OS << (HasAttributes ? ", " : " (");
|
||||
OS << "landing-pad";
|
||||
HasAttributes = true;
|
||||
|
@ -39,8 +39,7 @@ using namespace llvm;
|
||||
#define DEBUG_TYPE "codegen"
|
||||
|
||||
MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb)
|
||||
: BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false),
|
||||
AddressTaken(false), CachedMCSymbol(nullptr) {
|
||||
: BB(bb), Number(-1), xParent(&mf) {
|
||||
Insts.Parent = this;
|
||||
}
|
||||
|
||||
@ -203,7 +202,7 @@ const MachineBasicBlock *MachineBasicBlock::getLandingPadSuccessor() const {
|
||||
if (succ_size() > 2)
|
||||
return nullptr;
|
||||
for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I)
|
||||
if ((*I)->isLandingPad())
|
||||
if ((*I)->isEHPad())
|
||||
return *I;
|
||||
return nullptr;
|
||||
}
|
||||
@ -266,7 +265,7 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
LBB->printAsOperand(OS, /*PrintType=*/false, MST);
|
||||
Comma = ", ";
|
||||
}
|
||||
if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; }
|
||||
if (isEHPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; }
|
||||
if (hasAddressTaken()) { OS << Comma << "ADDRESS TAKEN"; Comma = ", "; }
|
||||
if (Alignment)
|
||||
OS << Comma << "Align " << Alignment << " (" << (1u << Alignment)
|
||||
@ -338,7 +337,7 @@ MachineBasicBlock::addLiveIn(MCPhysReg PhysReg, const TargetRegisterClass *RC) {
|
||||
assert(getParent() && "MBB must be inserted in function");
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(PhysReg) && "Expected physreg");
|
||||
assert(RC && "Register class is required");
|
||||
assert((isLandingPad() || this == &getParent()->front()) &&
|
||||
assert((isEHPad() || this == &getParent()->front()) &&
|
||||
"Only the entry block and landing pads can have physreg live ins");
|
||||
|
||||
bool LiveIn = isLiveIn(PhysReg);
|
||||
@ -396,7 +395,7 @@ void MachineBasicBlock::updateTerminator() {
|
||||
// its layout successor, insert a branch. First we have to locate the
|
||||
// only non-landing-pad successor, as that is the fallthrough block.
|
||||
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
|
||||
if ((*SI)->isLandingPad())
|
||||
if ((*SI)->isEHPad())
|
||||
continue;
|
||||
assert(!TBB && "Found more than one non-landing-pad successor!");
|
||||
TBB = *SI;
|
||||
@ -432,7 +431,7 @@ void MachineBasicBlock::updateTerminator() {
|
||||
// as the fallthrough successor.
|
||||
MachineBasicBlock *FallthroughBB = nullptr;
|
||||
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
|
||||
if ((*SI)->isLandingPad() || *SI == TBB)
|
||||
if ((*SI)->isEHPad() || *SI == TBB)
|
||||
continue;
|
||||
assert(!FallthroughBB && "Found more than one fallthrough successor.");
|
||||
FallthroughBB = *SI;
|
||||
@ -662,7 +661,7 @@ MachineBasicBlock *
|
||||
MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
|
||||
// Splitting the critical edge to a landing pad block is non-trivial. Don't do
|
||||
// it in this generic function.
|
||||
if (Succ->isLandingPad())
|
||||
if (Succ->isEHPad())
|
||||
return nullptr;
|
||||
|
||||
MachineFunction *MF = getParent();
|
||||
@ -1046,7 +1045,7 @@ bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA,
|
||||
while (SI != succ_end()) {
|
||||
const MachineBasicBlock *MBB = *SI;
|
||||
if (!SeenMBBs.insert(MBB).second ||
|
||||
(MBB != DestA && MBB != DestB && !MBB->isLandingPad())) {
|
||||
(MBB != DestA && MBB != DestB && !MBB->isEHPad())) {
|
||||
// This is a superfluous edge, remove it.
|
||||
SI = removeSuccessor(SI);
|
||||
Changed = true;
|
||||
|
@ -678,7 +678,7 @@ MachineBlockPlacement::findBestLoopExit(MachineFunction &F, MachineLoop &L,
|
||||
uint32_t WeightScale = 0;
|
||||
uint32_t SumWeight = MBPI->getSumForBlock(MBB, WeightScale);
|
||||
for (MachineBasicBlock *Succ : MBB->successors()) {
|
||||
if (Succ->isLandingPad())
|
||||
if (Succ->isEHPad())
|
||||
continue;
|
||||
if (Succ == MBB)
|
||||
continue;
|
||||
|
@ -529,7 +529,7 @@ void MachineLICM::HoistRegionPostRA() {
|
||||
// If the header of the loop containing this basic block is a landing pad,
|
||||
// then don't try to hoist instructions out of this loop.
|
||||
const MachineLoop *ML = MLI->getLoopFor(BB);
|
||||
if (ML && ML->getHeader()->isLandingPad()) continue;
|
||||
if (ML && ML->getHeader()->isEHPad()) continue;
|
||||
|
||||
// Conservatively treat live-in's as an external def.
|
||||
// FIXME: That means a reload that're reused in successor block(s) will not
|
||||
@ -725,7 +725,7 @@ void MachineLICM::HoistOutOfLoop(MachineDomTreeNode *HeaderN) {
|
||||
// If the header of the loop containing this basic block is a landing pad,
|
||||
// then don't try to hoist instructions out of this loop.
|
||||
const MachineLoop *ML = MLI->getLoopFor(BB);
|
||||
if (ML && ML->getHeader()->isLandingPad())
|
||||
if (ML && ML->getHeader()->isEHPad())
|
||||
continue;
|
||||
|
||||
// If this subregion is not in the top level loop at all, exit.
|
||||
|
@ -209,6 +209,7 @@ bool MachineModuleInfo::doInitialization(Module &M) {
|
||||
CurCallSite = 0;
|
||||
CallsEHReturn = false;
|
||||
CallsUnwindInit = false;
|
||||
HasEHFunclets = false;
|
||||
DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
|
||||
// Always emit some info, by default "no personality" info.
|
||||
Personalities.push_back(nullptr);
|
||||
@ -249,6 +250,7 @@ void MachineModuleInfo::EndFunction() {
|
||||
FilterEnds.clear();
|
||||
CallsEHReturn = false;
|
||||
CallsUnwindInit = false;
|
||||
HasEHFunclets = false;
|
||||
VariableDbgInfos.clear();
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ MachineBasicBlock *MachineSinking::FindSuccToSinkTo(MachineInstr *MI,
|
||||
|
||||
// It's not safe to sink instructions to EH landing pad. Control flow into
|
||||
// landing pad is implicitly defined.
|
||||
if (SuccToSinkTo && SuccToSinkTo->isLandingPad())
|
||||
if (SuccToSinkTo && SuccToSinkTo->isEHPad())
|
||||
return nullptr;
|
||||
|
||||
return SuccToSinkTo;
|
||||
|
@ -508,7 +508,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
|
||||
// If this block has allocatable physical registers live-in, check that
|
||||
// it is an entry block or landing pad.
|
||||
for (unsigned LI : MBB->liveins()) {
|
||||
if (isAllocatable(LI) && !MBB->isLandingPad() &&
|
||||
if (isAllocatable(LI) && !MBB->isEHPad() &&
|
||||
MBB != MBB->getParent()->begin()) {
|
||||
report("MBB has allocable live-in, but isn't entry or landing-pad.", MBB);
|
||||
}
|
||||
@ -519,7 +519,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
|
||||
SmallPtrSet<MachineBasicBlock*, 4> LandingPadSuccs;
|
||||
for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(),
|
||||
E = MBB->succ_end(); I != E; ++I) {
|
||||
if ((*I)->isLandingPad())
|
||||
if ((*I)->isEHPad())
|
||||
LandingPadSuccs.insert(*I);
|
||||
if (!FunctionBlocks.count(*I))
|
||||
report("MBB has successor that isn't part of the function.", MBB);
|
||||
@ -1606,7 +1606,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
|
||||
assert(LiveInts->isLiveInToMBB(LR, MFI));
|
||||
// We don't know how to track physregs into a landing pad.
|
||||
if (!TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||
MFI->isLandingPad()) {
|
||||
MFI->isEHPad()) {
|
||||
if (&*MFI == EndMBB)
|
||||
break;
|
||||
++MFI;
|
||||
|
@ -548,7 +548,7 @@ void PHIElimination::analyzePHINodes(const MachineFunction& MF) {
|
||||
bool PHIElimination::SplitPHIEdges(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB,
|
||||
MachineLoopInfo *MLI) {
|
||||
if (MBB.empty() || !MBB.front().isPHI() || MBB.isLandingPad())
|
||||
if (MBB.empty() || !MBB.front().isPHI() || MBB.isEHPad())
|
||||
return false; // Quick exit for basic blocks without PHIs.
|
||||
|
||||
const MachineLoop *CurLoop = MLI ? MLI->getLoopFor(&MBB) : nullptr;
|
||||
|
@ -28,7 +28,7 @@ llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB,
|
||||
// Usually, we just want to insert the copy before the first terminator
|
||||
// instruction. However, for the edge going to a landing pad, we must insert
|
||||
// the copy before the call/invoke instruction.
|
||||
if (!SuccMBB->isLandingPad())
|
||||
if (!SuccMBB->isEHPad())
|
||||
return MBB->getFirstTerminator();
|
||||
|
||||
// Discover any defs/uses in this basic block.
|
||||
|
@ -252,16 +252,17 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
|
||||
// Mark landing pad blocks.
|
||||
SmallVector<const LandingPadInst *, 4> LPads;
|
||||
for (BB = Fn->begin(); BB != EB; ++BB) {
|
||||
if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator()))
|
||||
MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
|
||||
if (BB->isLandingPad())
|
||||
LPads.push_back(BB->getLandingPadInst());
|
||||
if (BB->isEHPad())
|
||||
MBBMap[BB]->setIsEHPad();
|
||||
const Instruction *FNP = BB->getFirstNonPHI();
|
||||
if (const auto *LPI = dyn_cast<LandingPadInst>(FNP))
|
||||
LPads.push_back(LPI);
|
||||
}
|
||||
|
||||
// If this is an MSVC EH personality, we need to do a bit more work.
|
||||
EHPersonality Personality = EHPersonality::Unknown;
|
||||
if (Fn->hasPersonalityFn())
|
||||
Personality = classifyEHPersonality(Fn->getPersonalityFn());
|
||||
if (!Fn->hasPersonalityFn())
|
||||
return;
|
||||
EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn());
|
||||
if (!isMSVCEHPersonality(Personality))
|
||||
return;
|
||||
|
||||
@ -272,8 +273,13 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
|
||||
|
||||
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);
|
||||
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
|
||||
for (WinEHHandlerType &H : TBME.HandlerArray)
|
||||
if (const auto *BB = dyn_cast<BasicBlock>(H.Handler))
|
||||
H.HandlerMBB = MBBMap[BB];
|
||||
}
|
||||
|
||||
// Copy the state numbers to LandingPadInfo for the current function, which
|
||||
|
@ -1158,30 +1158,56 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
|
||||
llvm_unreachable("Can't get register for value!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
|
||||
// Update machine-CFG edges.
|
||||
MachineBasicBlock *PadMBB = FuncInfo.MBB;
|
||||
MachineBasicBlock *CatchingMBB = FuncInfo.MBBMap[I.getNormalDest()];
|
||||
MachineBasicBlock *UnwindMBB = FuncInfo.MBBMap[I.getUnwindDest()];
|
||||
PadMBB->addSuccessor(CatchingMBB);
|
||||
PadMBB->addSuccessor(UnwindMBB);
|
||||
|
||||
CatchingMBB->setIsEHFuncletEntry();
|
||||
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
|
||||
MMI.setHasEHFunclets(true);
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
|
||||
// Update machine-CFG edge.
|
||||
MachineBasicBlock *PadMBB = FuncInfo.MBB;
|
||||
MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
|
||||
PadMBB->addSuccessor(TargetMBB);
|
||||
|
||||
// Create the terminator node.
|
||||
SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
|
||||
getControlRoot(), DAG.getBasicBlock(TargetMBB));
|
||||
DAG.setRoot(Ret);
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
|
||||
// If this unwinds to caller, we don't need a DAG node hanging around.
|
||||
if (!I.hasUnwindDest())
|
||||
return;
|
||||
|
||||
// Update machine-CFG edge.
|
||||
MachineBasicBlock *PadMBB = FuncInfo.MBB;
|
||||
MachineBasicBlock *UnwindMBB = FuncInfo.MBBMap[I.getUnwindDest()];
|
||||
PadMBB->addSuccessor(UnwindMBB);
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
|
||||
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
|
||||
MMI.setHasEHFunclets(true);
|
||||
report_fatal_error("visitCleanupPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
|
||||
report_fatal_error("visitCleanupRet not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
|
||||
report_fatal_error("visitCatchEndPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
|
||||
report_fatal_error("visitCatchRet not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
|
||||
report_fatal_error("visitCatchPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
|
||||
report_fatal_error("visitTerminatePad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
|
||||
report_fatal_error("visitCleanupPad not yet implemented!");
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
auto &DL = DAG.getDataLayout();
|
||||
@ -2021,7 +2047,7 @@ void SelectionDAGBuilder::visitResume(const ResumeInst &RI) {
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) {
|
||||
assert(FuncInfo.MBB->isLandingPad() &&
|
||||
assert(FuncInfo.MBB->isEHPad() &&
|
||||
"Call to landingpad not in landing pad!");
|
||||
|
||||
MachineBasicBlock *MBB = FuncInfo.MBB;
|
||||
@ -5094,7 +5120,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
assert(Reg && "cannot get exception code on this platform");
|
||||
MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
|
||||
const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
|
||||
assert(FuncInfo.MBB->isLandingPad() && "eh.exceptioncode in non-lpad");
|
||||
assert(FuncInfo.MBB->isEHPad() && "eh.exceptioncode in non-lpad");
|
||||
unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC);
|
||||
SDValue N =
|
||||
DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT);
|
||||
|
@ -278,6 +278,10 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::CALLSEQ_START: return "callseq_start";
|
||||
case ISD::CALLSEQ_END: return "callseq_end";
|
||||
|
||||
// EH instructions
|
||||
case ISD::CATCHRET: return "catchret";
|
||||
case ISD::CLEANUPRET: return "cleanupret";
|
||||
|
||||
// Other operators
|
||||
case ISD::LOAD: return "load";
|
||||
case ISD::STORE: return "store";
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/LibCallSemantics.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/CodeGen/Analysis.h"
|
||||
#include "llvm/CodeGen/FastISel.h"
|
||||
@ -969,7 +970,7 @@ bool SelectionDAGISel::PrepareEHLandingPad() {
|
||||
InvokeBB->addSuccessor(ClauseBB);
|
||||
|
||||
// Mark the clause as a landing pad or MI passes will delete it.
|
||||
ClauseBB->setIsLandingPad();
|
||||
ClauseBB->setIsEHPad();
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,9 +999,9 @@ bool SelectionDAGISel::PrepareEHLandingPad() {
|
||||
static bool isFoldedOrDeadInstruction(const Instruction *I,
|
||||
FunctionLoweringInfo *FuncInfo) {
|
||||
return !I->mayWriteToMemory() && // Side-effecting instructions aren't folded.
|
||||
!isa<TerminatorInst>(I) && // Terminators aren't folded.
|
||||
!isa<TerminatorInst>(I) && // Terminators aren't folded.
|
||||
!isa<DbgInfoIntrinsic>(I) && // Debug instructions aren't folded.
|
||||
!isa<LandingPadInst>(I) && // Landingpad instructions aren't folded.
|
||||
!I->isEHPad() && // EH pad instructions aren't folded.
|
||||
!FuncInfo->isExportedInst(I); // Exported instrs must be computed.
|
||||
}
|
||||
|
||||
@ -1163,6 +1164,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
if (!PrepareEHLandingPad())
|
||||
continue;
|
||||
|
||||
|
||||
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
||||
if (FastIS) {
|
||||
FastIS->startNewBlock();
|
||||
@ -1251,7 +1253,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
// For the purpose of debugging, just abort.
|
||||
report_fatal_error("FastISel didn't select the entire block");
|
||||
|
||||
if (!Inst->getType()->isVoidTy() && !Inst->use_empty()) {
|
||||
if (!Inst->getType()->isVoidTy() && !Inst->getType()->isTokenTy() &&
|
||||
!Inst->use_empty()) {
|
||||
unsigned &R = FuncInfo->ValueMap[Inst];
|
||||
if (!R)
|
||||
R = FuncInfo->CreateRegs(Inst->getType());
|
||||
|
@ -2608,7 +2608,8 @@ static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
|
||||
HT.TypeDescriptor =
|
||||
cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
|
||||
}
|
||||
HT.Handler = CPI->getParent();
|
||||
HT.Handler = CPI->getNormalDest();
|
||||
HT.HandlerMBB = nullptr;
|
||||
// FIXME: Pass CPI->getArgOperand(1).
|
||||
HT.CatchObjRecoverIdx = -1;
|
||||
TBME.HandlerArray.push_back(HT);
|
||||
@ -2684,6 +2685,7 @@ 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);
|
||||
}
|
||||
|
@ -6931,7 +6931,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI,
|
||||
MachineModuleInfo &MMI = MF->getMMI();
|
||||
for (MachineFunction::iterator BB = MF->begin(), E = MF->end(); BB != E;
|
||||
++BB) {
|
||||
if (!BB->isLandingPad()) continue;
|
||||
if (!BB->isEHPad()) continue;
|
||||
|
||||
// FIXME: We should assert that the EH_LABEL is the first MI in the landing
|
||||
// pad.
|
||||
@ -6979,7 +6979,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI,
|
||||
|
||||
// Shove the dispatch's address into the return slot in the function context.
|
||||
MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
|
||||
DispatchBB->setIsLandingPad();
|
||||
DispatchBB->setIsEHPad();
|
||||
|
||||
MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
|
||||
unsigned trap_opcode;
|
||||
@ -7245,7 +7245,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI,
|
||||
BB->succ_end());
|
||||
while (!Successors.empty()) {
|
||||
MachineBasicBlock *SMBB = Successors.pop_back_val();
|
||||
if (SMBB->isLandingPad()) {
|
||||
if (SMBB->isEHPad()) {
|
||||
BB->removeSuccessor(SMBB);
|
||||
MBBLPads.push_back(SMBB);
|
||||
}
|
||||
@ -7293,7 +7293,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI,
|
||||
// landing pad now.
|
||||
for (SmallVectorImpl<MachineBasicBlock*>::iterator
|
||||
I = MBBLPads.begin(), E = MBBLPads.end(); I != E; ++I)
|
||||
(*I)->setIsLandingPad(false);
|
||||
(*I)->setIsEHPad(false);
|
||||
|
||||
// The instruction is gone now.
|
||||
MI->eraseFromParent();
|
||||
|
@ -951,7 +951,7 @@ void BT::visitBranchesFrom(const MachineInstr *BI) {
|
||||
// be processed.
|
||||
for (succ_iterator I = B.succ_begin(), E = B.succ_end(); I != E; ++I) {
|
||||
const MachineBasicBlock *SB = *I;
|
||||
if (SB->isLandingPad())
|
||||
if (SB->isEHPad())
|
||||
Targets.insert(SB);
|
||||
}
|
||||
if (FallsThrough) {
|
||||
|
@ -405,7 +405,7 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock*
|
||||
|
||||
// If this is a landing pad, it isn't a fall through. If it has no preds,
|
||||
// then nothing falls through to it.
|
||||
if (MBB->isLandingPad() || MBB->pred_empty())
|
||||
if (MBB->isEHPad() || MBB->pred_empty())
|
||||
return false;
|
||||
|
||||
// If there isn't exactly one predecessor, it can't be a fall through.
|
||||
|
@ -806,7 +806,7 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const {
|
||||
const MachineBasicBlock *Dst1) {
|
||||
return Prob.getEdgeWeight(&B, Dst0) < Prob.getEdgeWeight(&B, Dst1);
|
||||
});
|
||||
return S->isLandingPad() ? nullptr : S;
|
||||
return S->isEHPad() ? nullptr : S;
|
||||
}
|
||||
|
||||
std::pair<MipsInstrInfo::BranchType, MachineInstr *>
|
||||
|
@ -407,6 +407,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
||||
setOperationAction(ISD::SETCC , MVT::i64 , Custom);
|
||||
}
|
||||
setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
|
||||
setOperationAction(ISD::CATCHRET , MVT::Other, Custom);
|
||||
// NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support
|
||||
// SjLj exception handling but a light-weight setjmp/longjmp replacement to
|
||||
// support continuation, user-level threading, and etc.. As a result, no
|
||||
@ -16664,6 +16665,25 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
|
||||
DAG.getRegister(StoreAddrReg, PtrVT));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Dest = Op.getOperand(1);
|
||||
SDLoc DL(Op);
|
||||
|
||||
MVT PtrVT = getPointerTy(DAG.getDataLayout());
|
||||
unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX);
|
||||
|
||||
// Load the address of the destination block.
|
||||
MachineBasicBlock *DestMBB = cast<BasicBlockSDNode>(Dest)->getBasicBlock();
|
||||
SDValue BlockPtr = DAG.getMCSymbol(DestMBB->getSymbol(), PtrVT);
|
||||
unsigned WrapperKind =
|
||||
Subtarget->isPICStyleRIPRel() ? X86ISD::WrapperRIP : X86ISD::Wrapper;
|
||||
SDValue WrappedPtr = DAG.getNode(WrapperKind, DL, PtrVT, BlockPtr);
|
||||
Chain = DAG.getCopyToReg(Chain, DL, ReturnReg, WrappedPtr);
|
||||
return DAG.getNode(X86ISD::CATCHRET, DL, MVT::Other, Chain,
|
||||
DAG.getRegister(ReturnReg, PtrVT));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
@ -18903,6 +18923,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
||||
case ISD::CATCHRET: return LowerCATCHRET(Op, DAG);
|
||||
case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG);
|
||||
case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG);
|
||||
case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
|
||||
@ -19238,6 +19259,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP";
|
||||
case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP";
|
||||
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
|
||||
case X86ISD::CATCHRET: return "X86ISD::CATCHRET";
|
||||
case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN";
|
||||
case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m";
|
||||
case X86ISD::FNSTSW16r: return "X86ISD::FNSTSW16r";
|
||||
|
@ -261,6 +261,8 @@ namespace llvm {
|
||||
// Exception Handling helpers.
|
||||
EH_RETURN,
|
||||
|
||||
CATCHRET,
|
||||
|
||||
// SjLj exception handling setjmp.
|
||||
EH_SJLJ_SETJMP,
|
||||
|
||||
@ -998,6 +1000,7 @@ namespace llvm {
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
@ -152,6 +152,15 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
|
||||
}
|
||||
|
||||
let isTerminator = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1 in {
|
||||
def CATCHRET : I<0xC3, RawFrm, (outs), (ins GR32:$addr),
|
||||
"ret{l}\t# CATCHRET",
|
||||
[(X86catchret GR32:$addr)], IIC_RET>, Sched<[WriteJumpLd]>;
|
||||
def CATCHRET64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
"ret{q}\t# CATCHRET",
|
||||
[(X86catchret GR64:$addr)], IIC_RET>, Sched<[WriteJumpLd]>;
|
||||
}
|
||||
|
||||
let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
|
||||
usesCustomInserter = 1 in {
|
||||
def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf),
|
||||
|
@ -205,6 +205,8 @@ def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR,
|
||||
def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
def X86catchret : SDNode<"X86ISD::CATCHRET", SDT_X86EHRET, [SDNPHasChain]>;
|
||||
|
||||
def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP",
|
||||
SDTypeProfile<1, 1, [SDTCisInt<0>,
|
||||
SDTCisPtrTy<1>]>,
|
||||
|
@ -531,6 +531,12 @@ ReSimplify:
|
||||
break;
|
||||
}
|
||||
|
||||
case X86::CATCHRET: {
|
||||
OutMI = MCInst();
|
||||
OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget()));
|
||||
break;
|
||||
}
|
||||
|
||||
// TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions.
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPd:
|
||||
|
@ -471,6 +471,8 @@ int WinEHStatePass::escapeRegNode(Function &F) {
|
||||
void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
|
||||
WinEHFuncInfo &FuncInfo,
|
||||
Function &F, int BaseState) {
|
||||
Function *RestoreFrame =
|
||||
Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
|
||||
// Iterate all the instructions and emit state number stores.
|
||||
for (BasicBlock &BB : F) {
|
||||
for (Instruction &I : BB) {
|
||||
@ -489,6 +491,14 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
|
||||
insertStateNumberStore(ParentRegNode, II, State);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert calls to llvm.x86.seh.restoreframe at catchret destinations.
|
||||
if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator())) {
|
||||
//llvm::errs() << "BB: " << BB << '\n';
|
||||
//llvm::errs() << "CR->getSuccessor(): " << *CR->getSuccessor() << '\n';
|
||||
IRBuilder<> Builder(CR->getSuccessor()->begin());
|
||||
Builder.CreateCall(RestoreFrame, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
130
test/CodeGen/X86/win-catchpad.ll
Normal file
130
test/CodeGen/X86/win-catchpad.ll
Normal file
@ -0,0 +1,130 @@
|
||||
; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck --check-prefix=X86 %s
|
||||
; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck --check-prefix=X64 %s
|
||||
|
||||
; Loosely based on IR for this C++ source code:
|
||||
; void f(int p);
|
||||
; int main() {
|
||||
; try {
|
||||
; f(1);
|
||||
; } catch (int) {
|
||||
; f(2);
|
||||
; } catch (...) {
|
||||
; f(3);
|
||||
; }
|
||||
; }
|
||||
|
||||
%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
|
||||
%eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* }
|
||||
%eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] }
|
||||
%eh.ThrowInfo = type { i32, i8*, i8*, i8* }
|
||||
%eh.CatchHandlerType = type { i32, i8* }
|
||||
|
||||
$"\01??_R0H@8" = comdat any
|
||||
|
||||
@"\01??_7type_info@@6B@" = external constant i8*
|
||||
@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
|
||||
|
||||
@llvm.eh.handlertype.H.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata"
|
||||
@llvm.eh.handlertype.H.1 = private unnamed_addr constant %eh.CatchHandlerType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata"
|
||||
|
||||
declare void @f(i32 %p)
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
|
||||
define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
entry:
|
||||
invoke void @f(i32 1)
|
||||
to label %try.cont unwind label %catch.dispatch
|
||||
|
||||
catch.dispatch: ; preds = %entry
|
||||
%0 = catchpad [%eh.CatchHandlerType* @llvm.eh.handlertype.H.0, i8* null]
|
||||
to label %catch unwind label %catch.dispatch.2
|
||||
|
||||
catch: ; preds = %catch.dispatch
|
||||
invoke void @f(i32 2)
|
||||
to label %invoke.cont.2 unwind label %catchendblock
|
||||
|
||||
invoke.cont.2: ; preds = %catch
|
||||
catchret %0 to label %try.cont
|
||||
|
||||
catch.dispatch.2: ; preds = %catch.dispatch
|
||||
%1 = catchpad [%eh.CatchHandlerType* @llvm.eh.handlertype.H.0, i8* null]
|
||||
to label %catch.2 unwind label %catchendblock
|
||||
|
||||
catch.2: ; preds = %catch.dispatch.2
|
||||
invoke void @f(i32 3)
|
||||
to label %invoke.cont.3 unwind label %catchendblock
|
||||
|
||||
invoke.cont.3: ; preds = %catch.2
|
||||
catchret %1 to label %try.cont
|
||||
|
||||
try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
|
||||
ret i32 0
|
||||
|
||||
catchendblock: ; preds = %catch, %catch.2, %catch.dispatch.2
|
||||
catchendpad unwind to caller
|
||||
}
|
||||
|
||||
; X86-LABEL: _try_catch_catch:
|
||||
; X86: movl $0, -{{[0-9]+}}(%ebp)
|
||||
; X86: movl $1, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: [[contbb:LBB0_[0-9]+]]:
|
||||
; X86: movl -{{[0-9]+}}(%ebp), %esp
|
||||
; X86: retl
|
||||
|
||||
; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}}
|
||||
; X86: movl $1, -{{[0-9]+}}(%ebp)
|
||||
; X86: movl $2, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: movl $[[contbb]], %eax
|
||||
; X86-NEXT: retl
|
||||
|
||||
; X86: [[catch2bb:LBB0_[0-9]+]]: # %catch.2{{$}}
|
||||
; X86: movl $1, -{{[0-9]+}}(%ebp)
|
||||
; X86: movl $3, (%esp)
|
||||
; X86: calll _f
|
||||
; X86: movl $[[contbb]], %eax
|
||||
; X86-NEXT: retl
|
||||
|
||||
; X86: L__ehtable$try_catch_catch:
|
||||
; X86: $handlerMap$0$try_catch_catch:
|
||||
; X86: .long 0
|
||||
; X86: .long "??_R0H@8"
|
||||
; X86: .long 0
|
||||
; X86: .long [[catch1bb]]
|
||||
; X86: .long 0
|
||||
; X86: .long "??_R0H@8"
|
||||
; X86: .long 0
|
||||
; X86: .long [[catch2bb]]
|
||||
|
||||
; X64-LABEL: try_catch_catch:
|
||||
; X64: movl $1, %ecx
|
||||
; X64: callq f
|
||||
; X64: [[contbb:\.LBB0_[0-9]+]]:
|
||||
; X64: retq
|
||||
|
||||
; X64: [[catch1bb:\.LBB0_[0-9]+]]: # %catch{{$}}
|
||||
; X64: movl $2, %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: retq
|
||||
|
||||
; X64: [[catch2bb:\.LBB0_[0-9]+]]: # %catch.2{{$}}
|
||||
; X64: movl $3, %ecx
|
||||
; X64: callq f
|
||||
; X64: leaq [[contbb]](%rip), %rax
|
||||
; X64: retq
|
||||
|
||||
; FIXME: Get rid of these parent_frame_offset things below. They are leftover
|
||||
; from our IR outlining strategy.
|
||||
; X64: $handlerMap$0$try_catch_catch:
|
||||
; X64: .long 0
|
||||
; X64: .long "??_R0H@8"@IMGREL
|
||||
; X64: .long 0
|
||||
; X64: .long [[catch1bb]]@IMGREL
|
||||
; X64 .long .Lcatch$parent_frame_offset
|
||||
; X64: .long 0
|
||||
; X64: .long "??_R0H@8"@IMGREL
|
||||
; X64: .long 0
|
||||
; X64: .long [[catch2bb]]@IMGREL
|
||||
; X64 .long .Lcatch.2$parent_frame_offset
|
Loading…
Reference in New Issue
Block a user