Skip to content

Commit 14e7735

Browse files
committed
[WinEH] Delete the old landingpad implementation of Windows EH
The new implementation works at least as well as the old implementation did. Also delete the associated preparation tests. They don't exercise interesting corner cases of the new implementation. All the codegen tests of the EH tables have already been ported. llvm-svn: 249918
1 parent eb7cd6c commit 14e7735

39 files changed

+108
-8039
lines changed

llvm/include/llvm/CodeGen/WinEHFuncInfo.h

Lines changed: 6 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -33,99 +33,18 @@ class MCSymbol;
3333
class MachineBasicBlock;
3434
class Value;
3535

36-
enum ActionType { Catch, Cleanup };
37-
38-
class ActionHandler {
39-
public:
40-
ActionHandler(BasicBlock *BB, ActionType Type)
41-
: StartBB(BB), Type(Type), EHState(-1), HandlerBlockOrFunc(nullptr) {}
42-
43-
ActionType getType() const { return Type; }
44-
BasicBlock *getStartBlock() const { return StartBB; }
45-
46-
bool hasBeenProcessed() { return HandlerBlockOrFunc != nullptr; }
47-
48-
void setHandlerBlockOrFunc(Constant *F) { HandlerBlockOrFunc = F; }
49-
Constant *getHandlerBlockOrFunc() { return HandlerBlockOrFunc; }
50-
51-
void setEHState(int State) { EHState = State; }
52-
int getEHState() const { return EHState; }
53-
54-
private:
55-
BasicBlock *StartBB;
56-
ActionType Type;
57-
int EHState;
58-
59-
// Can be either a BlockAddress or a Function depending on the EH personality.
60-
Constant *HandlerBlockOrFunc;
61-
};
62-
63-
class CatchHandler : public ActionHandler {
64-
public:
65-
CatchHandler(BasicBlock *BB, Constant *Selector, BasicBlock *NextBB)
66-
: ActionHandler(BB, ActionType::Catch), Selector(Selector),
67-
NextBB(NextBB), ExceptionObjectVar(nullptr),
68-
ExceptionObjectIndex(-1) {}
69-
70-
// Method for support type inquiry through isa, cast, and dyn_cast:
71-
static inline bool classof(const ActionHandler *H) {
72-
return H->getType() == ActionType::Catch;
73-
}
74-
75-
Constant *getSelector() const { return Selector; }
76-
BasicBlock *getNextBB() const { return NextBB; }
77-
78-
const Value *getExceptionVar() { return ExceptionObjectVar; }
79-
TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; }
80-
81-
void setExceptionVar(const Value *Val) { ExceptionObjectVar = Val; }
82-
void setExceptionVarIndex(int Index) { ExceptionObjectIndex = Index; }
83-
int getExceptionVarIndex() const { return ExceptionObjectIndex; }
84-
void setReturnTargets(TinyPtrVector<BasicBlock *> &Targets) {
85-
ReturnTargets = Targets;
86-
}
87-
88-
private:
89-
Constant *Selector;
90-
BasicBlock *NextBB;
91-
// While catch handlers are being outlined the ExceptionObjectVar field will
92-
// be populated with the instruction in the parent frame that corresponds
93-
// to the exception object (or nullptr if the catch does not use an
94-
// exception object) and the ExceptionObjectIndex field will be -1.
95-
// When the parseEHActions function is called to populate a vector of
96-
// instances of this class, the ExceptionObjectVar field will be nullptr
97-
// and the ExceptionObjectIndex will be the index of the exception object in
98-
// the parent function's localescape block.
99-
const Value *ExceptionObjectVar;
100-
int ExceptionObjectIndex;
101-
TinyPtrVector<BasicBlock *> ReturnTargets;
102-
};
103-
104-
class CleanupHandler : public ActionHandler {
105-
public:
106-
CleanupHandler(BasicBlock *BB) : ActionHandler(BB, ActionType::Cleanup) {}
107-
108-
// Method for support type inquiry through isa, cast, and dyn_cast:
109-
static inline bool classof(const ActionHandler *H) {
110-
return H->getType() == ActionType::Cleanup;
111-
}
112-
};
113-
114-
void parseEHActions(const IntrinsicInst *II,
115-
SmallVectorImpl<std::unique_ptr<ActionHandler>> &Actions);
116-
117-
// The following structs respresent the .xdata for functions using C++
118-
// exceptions on Windows.
36+
// The following structs respresent the .xdata tables for various
37+
// Windows-related EH personalities.
11938

12039
typedef PointerUnion<const BasicBlock *, MachineBasicBlock *> MBBOrBasicBlock;
12140
typedef PointerUnion<const Value *, const MachineBasicBlock *> ValueOrMBB;
12241

123-
struct WinEHUnwindMapEntry {
42+
struct CxxUnwindMapEntry {
12443
int ToState;
12544
ValueOrMBB Cleanup;
12645
};
12746

128-
/// Similar to WinEHUnwindMapEntry, but supports SEH filters.
47+
/// Similar to CxxUnwindMapEntry, but supports SEH filters.
12948
struct SEHUnwindMapEntry {
13049
/// If unwinding continues through this handler, transition to the handler at
13150
/// this state. This indexes into SEHUnwindMap.
@@ -174,13 +93,13 @@ struct WinEHFuncInfo {
17493
DenseMap<const CatchReturnInst *, const BasicBlock *>
17594
CatchRetSuccessorColorMap;
17695
DenseMap<MCSymbol *, std::pair<int, MCSymbol *>> InvokeToStateMap;
177-
SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
96+
SmallVector<CxxUnwindMapEntry, 4> CxxUnwindMap;
17897
SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
17998
SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap;
18099
SmallVector<ClrEHUnwindMapEntry, 4> ClrEHUnwindMap;
181100
int UnwindHelpFrameIdx = INT_MAX;
182101

183-
int getLastStateNumber() const { return UnwindMap.size() - 1; }
102+
int getLastStateNumber() const { return CxxUnwindMap.size() - 1; }
184103

185104
void addIPToStateRange(const BasicBlock *PadBB, MCSymbol *InvokeBegin,
186105
MCSymbol *InvokeEnd);

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -429,13 +429,6 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>;
429429
def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>;
430430
def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>;
431431

432-
// eh.begincatch takes a pointer returned by a landingpad instruction and
433-
// copies the exception object into the memory pointed to by the second
434-
// parameter. If the second parameter is null, no copy occurs.
435-
def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
436-
[NoCapture<0>, NoCapture<1>]>;
437-
def int_eh_endcatch : Intrinsic<[], []>;
438-
439432
// eh.exceptionpointer returns the pointer to the exception caught by
440433
// the given `catchpad`.
441434
def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty],
@@ -444,12 +437,6 @@ def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty],
444437
// Gets the exception code from a catchpad token. Only used on some platforms.
445438
def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>;
446439

447-
// Represents the list of actions to take when an exception is thrown.
448-
def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
449-
450-
// FIXME: Remove this when landing pad EH can be removed.
451-
def int_eh_exceptioncode_old : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
452-
453440
// __builtin_unwind_init is an undocumented GCC intrinsic that causes all
454441
// callee-saved registers to be saved and restored (regardless of whether they
455442
// are used) in the calling function. It is used by libgcc_eh.

llvm/lib/Analysis/Lint.cpp

Lines changed: 0 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,6 @@ void Lint::visitCallSite(CallSite CS) {
345345
visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0,
346346
nullptr, MemRef::Read | MemRef::Write);
347347
break;
348-
349-
case Intrinsic::eh_begincatch:
350-
visitEHBeginCatch(II);
351-
break;
352-
case Intrinsic::eh_endcatch:
353-
visitEHEndCatch(II);
354-
break;
355348
}
356349
}
357350

@@ -511,187 +504,6 @@ void Lint::visitShl(BinaryOperator &I) {
511504
"Undefined result: Shift count out of range", &I);
512505
}
513506

514-
static bool
515-
allPredsCameFromLandingPad(BasicBlock *BB,
516-
SmallSet<BasicBlock *, 4> &VisitedBlocks) {
517-
VisitedBlocks.insert(BB);
518-
if (BB->isLandingPad())
519-
return true;
520-
// If we find a block with no predecessors, the search failed.
521-
if (pred_empty(BB))
522-
return false;
523-
for (BasicBlock *Pred : predecessors(BB)) {
524-
if (VisitedBlocks.count(Pred))
525-
continue;
526-
if (!allPredsCameFromLandingPad(Pred, VisitedBlocks))
527-
return false;
528-
}
529-
return true;
530-
}
531-
532-
static bool
533-
allSuccessorsReachEndCatch(BasicBlock *BB, BasicBlock::iterator InstBegin,
534-
IntrinsicInst **SecondBeginCatch,
535-
SmallSet<BasicBlock *, 4> &VisitedBlocks) {
536-
VisitedBlocks.insert(BB);
537-
for (BasicBlock::iterator I = InstBegin, E = BB->end(); I != E; ++I) {
538-
IntrinsicInst *IC = dyn_cast<IntrinsicInst>(I);
539-
if (IC && IC->getIntrinsicID() == Intrinsic::eh_endcatch)
540-
return true;
541-
// If we find another begincatch while looking for an endcatch,
542-
// that's also an error.
543-
if (IC && IC->getIntrinsicID() == Intrinsic::eh_begincatch) {
544-
*SecondBeginCatch = IC;
545-
return false;
546-
}
547-
}
548-
549-
// If we reach a block with no successors while searching, the
550-
// search has failed.
551-
if (succ_empty(BB))
552-
return false;
553-
// Otherwise, search all of the successors.
554-
for (BasicBlock *Succ : successors(BB)) {
555-
if (VisitedBlocks.count(Succ))
556-
continue;
557-
if (!allSuccessorsReachEndCatch(Succ, Succ->begin(), SecondBeginCatch,
558-
VisitedBlocks))
559-
return false;
560-
}
561-
return true;
562-
}
563-
564-
void Lint::visitEHBeginCatch(IntrinsicInst *II) {
565-
// The checks in this function make a potentially dubious assumption about
566-
// the CFG, namely that any block involved in a catch is only used for the
567-
// catch. This will very likely be true of IR generated by a front end,
568-
// but it may cease to be true, for example, if the IR is run through a
569-
// pass which combines similar blocks.
570-
//
571-
// In general, if we encounter a block the isn't dominated by the catch
572-
// block while we are searching the catch block's successors for a call
573-
// to end catch intrinsic, then it is possible that it will be legal for
574-
// a path through this block to never reach a call to llvm.eh.endcatch.
575-
// An analogous statement could be made about our search for a landing
576-
// pad among the catch block's predecessors.
577-
//
578-
// What is actually required is that no path is possible at runtime that
579-
// reaches a call to llvm.eh.begincatch without having previously visited
580-
// a landingpad instruction and that no path is possible at runtime that
581-
// calls llvm.eh.begincatch and does not subsequently call llvm.eh.endcatch
582-
// (mentally adjusting for the fact that in reality these calls will be
583-
// removed before code generation).
584-
//
585-
// Because this is a lint check, we take a pessimistic approach and warn if
586-
// the control flow is potentially incorrect.
587-
588-
SmallSet<BasicBlock *, 4> VisitedBlocks;
589-
BasicBlock *CatchBB = II->getParent();
590-
591-
// The begin catch must occur in a landing pad block or all paths
592-
// to it must have come from a landing pad.
593-
Assert(allPredsCameFromLandingPad(CatchBB, VisitedBlocks),
594-
"llvm.eh.begincatch may be reachable without passing a landingpad",
595-
II);
596-
597-
// Reset the visited block list.
598-
VisitedBlocks.clear();
599-
600-
IntrinsicInst *SecondBeginCatch = nullptr;
601-
602-
// This has to be called before it is asserted. Otherwise, the first assert
603-
// below can never be hit.
604-
bool EndCatchFound = allSuccessorsReachEndCatch(
605-
CatchBB, std::next(static_cast<BasicBlock::iterator>(II)),
606-
&SecondBeginCatch, VisitedBlocks);
607-
Assert(
608-
SecondBeginCatch == nullptr,
609-
"llvm.eh.begincatch may be called a second time before llvm.eh.endcatch",
610-
II, SecondBeginCatch);
611-
Assert(EndCatchFound,
612-
"Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch",
613-
II);
614-
}
615-
616-
static bool allPredCameFromBeginCatch(
617-
BasicBlock *BB, BasicBlock::reverse_iterator InstRbegin,
618-
IntrinsicInst **SecondEndCatch, SmallSet<BasicBlock *, 4> &VisitedBlocks) {
619-
VisitedBlocks.insert(BB);
620-
// Look for a begincatch in this block.
621-
for (BasicBlock::reverse_iterator RI = InstRbegin, RE = BB->rend(); RI != RE;
622-
++RI) {
623-
IntrinsicInst *IC = dyn_cast<IntrinsicInst>(&*RI);
624-
if (IC && IC->getIntrinsicID() == Intrinsic::eh_begincatch)
625-
return true;
626-
// If we find another end catch before we find a begin catch, that's
627-
// an error.
628-
if (IC && IC->getIntrinsicID() == Intrinsic::eh_endcatch) {
629-
*SecondEndCatch = IC;
630-
return false;
631-
}
632-
// If we encounter a landingpad instruction, the search failed.
633-
if (isa<LandingPadInst>(*RI))
634-
return false;
635-
}
636-
// If while searching we find a block with no predeccesors,
637-
// the search failed.
638-
if (pred_empty(BB))
639-
return false;
640-
// Search any predecessors we haven't seen before.
641-
for (BasicBlock *Pred : predecessors(BB)) {
642-
if (VisitedBlocks.count(Pred))
643-
continue;
644-
if (!allPredCameFromBeginCatch(Pred, Pred->rbegin(), SecondEndCatch,
645-
VisitedBlocks))
646-
return false;
647-
}
648-
return true;
649-
}
650-
651-
void Lint::visitEHEndCatch(IntrinsicInst *II) {
652-
// The check in this function makes a potentially dubious assumption about
653-
// the CFG, namely that any block involved in a catch is only used for the
654-
// catch. This will very likely be true of IR generated by a front end,
655-
// but it may cease to be true, for example, if the IR is run through a
656-
// pass which combines similar blocks.
657-
//
658-
// In general, if we encounter a block the isn't post-dominated by the
659-
// end catch block while we are searching the end catch block's predecessors
660-
// for a call to the begin catch intrinsic, then it is possible that it will
661-
// be legal for a path to reach the end catch block without ever having
662-
// called llvm.eh.begincatch.
663-
//
664-
// What is actually required is that no path is possible at runtime that
665-
// reaches a call to llvm.eh.endcatch without having previously visited
666-
// a call to llvm.eh.begincatch (mentally adjusting for the fact that in
667-
// reality these calls will be removed before code generation).
668-
//
669-
// Because this is a lint check, we take a pessimistic approach and warn if
670-
// the control flow is potentially incorrect.
671-
672-
BasicBlock *EndCatchBB = II->getParent();
673-
674-
// Alls paths to the end catch call must pass through a begin catch call.
675-
676-
// If llvm.eh.begincatch wasn't called in the current block, we'll use this
677-
// lambda to recursively look for it in predecessors.
678-
SmallSet<BasicBlock *, 4> VisitedBlocks;
679-
IntrinsicInst *SecondEndCatch = nullptr;
680-
681-
// This has to be called before it is asserted. Otherwise, the first assert
682-
// below can never be hit.
683-
bool BeginCatchFound =
684-
allPredCameFromBeginCatch(EndCatchBB, BasicBlock::reverse_iterator(II),
685-
&SecondEndCatch, VisitedBlocks);
686-
Assert(
687-
SecondEndCatch == nullptr,
688-
"llvm.eh.endcatch may be called a second time after llvm.eh.begincatch",
689-
II, SecondEndCatch);
690-
Assert(BeginCatchFound,
691-
"llvm.eh.endcatch may be reachable without passing llvm.eh.begincatch",
692-
II);
693-
}
694-
695507
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
696508
AssumptionCache *AC) {
697509
// Assume undef could be zero.

0 commit comments

Comments
 (0)