#include "llvm/CodeGen/WinEHPrepare.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
usingnamespacellvm;
#define DEBUG_TYPE …
static cl::opt<bool> DisableDemotion(
"disable-demotion", cl::Hidden,
cl::desc(
"Clone multicolor basic blocks but do not demote cross scopes"),
cl::init(false));
static cl::opt<bool> DisableCleanups(
"disable-cleanups", cl::Hidden,
cl::desc("Do not remove implausible terminators or other similar cleanups"),
cl::init(false));
static cl::opt<bool> DemoteCatchSwitchPHIOnlyOpt(
"demote-catchswitch-only", cl::Hidden,
cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false));
namespace {
class WinEHPrepareImpl { … };
class WinEHPrepare : public FunctionPass { … };
}
PreservedAnalyses WinEHPreparePass::run(Function &F,
FunctionAnalysisManager &) { … }
char WinEHPrepare::ID = …;
INITIALIZE_PASS(…)
FunctionPass *llvm::createWinEHPass(bool DemoteCatchSwitchPHIOnly) { … }
bool WinEHPrepareImpl::runOnFunction(Function &Fn) { … }
static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
const BasicBlock *BB) { … }
static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
int TryHigh, int CatchHigh,
ArrayRef<const CatchPadInst *> Handlers) { … }
static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) { … }
static void calculateStateNumbersForInvokes(const Function *Fn,
WinEHFuncInfo &FuncInfo) { … }
struct WorkItem { … };
void llvm::calculateCXXStateForAsynchEH(const BasicBlock *BB, int State,
WinEHFuncInfo &EHInfo) { … }
void llvm::calculateSEHStateForAsynchEH(const BasicBlock *BB, int State,
WinEHFuncInfo &EHInfo) { … }
static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
Value *ParentPad) { … }
static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
const Instruction *FirstNonPHI,
int ParentState) { … }
static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState,
const Function *Filter, const BasicBlock *Handler) { … }
static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState,
const BasicBlock *Handler) { … }
static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
const Instruction *FirstNonPHI,
int ParentState) { … }
static bool isTopLevelPadForMSVC(const Instruction *EHPad) { … }
void llvm::calculateSEHStateNumbers(const Function *Fn,
WinEHFuncInfo &FuncInfo) { … }
void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
WinEHFuncInfo &FuncInfo) { … }
static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
int TryParentState, ClrHandlerType HandlerType,
uint32_t TypeToken, const BasicBlock *Handler) { … }
void llvm::calculateClrEHStateNumbers(const Function *Fn,
WinEHFuncInfo &FuncInfo) { … }
void WinEHPrepareImpl::colorFunclets(Function &F) { … }
void WinEHPrepareImpl::demotePHIsOnFunclets(Function &F,
bool DemoteCatchSwitchPHIOnly) { … }
void WinEHPrepareImpl::cloneCommonBlocks(Function &F) { … }
void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { … }
void WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) { … }
#ifndef NDEBUG
void WinEHPrepareImpl::verifyPreparedFunclets(Function &F) {
for (BasicBlock &BB : F) {
size_t NumColors = BlockColors[&BB].size();
assert(NumColors == 1 && "Expected monochromatic BB!");
if (NumColors == 0)
report_fatal_error("Uncolored BB!");
if (NumColors > 1)
report_fatal_error("Multicolor BB!");
assert((DisableDemotion || !(BB.isEHPad() && isa<PHINode>(BB.begin()))) &&
"EH Pad still has a PHI!");
}
}
#endif
bool WinEHPrepareImpl::prepareExplicitEH(Function &F) { … }
AllocaInst *WinEHPrepareImpl::insertPHILoads(PHINode *PN, Function &F) { … }
void WinEHPrepareImpl::insertPHIStores(PHINode *OriginalPHI,
AllocaInst *SpillSlot) { … }
void WinEHPrepareImpl::insertPHIStore(
BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) { … }
void WinEHPrepareImpl::replaceUseWithLoad(
Value *V, Use &U, AllocaInst *&SpillSlot,
DenseMap<BasicBlock *, Value *> &Loads, Function &F) { … }
void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II,
MCSymbol *InvokeBegin,
MCSymbol *InvokeEnd) { … }
void WinEHFuncInfo::addIPToStateRange(int State, MCSymbol* InvokeBegin,
MCSymbol* InvokeEnd) { … }
WinEHFuncInfo::WinEHFuncInfo() = default;