34#define DEBUG_TYPE "sjljehprepare"
37STATISTIC(NumSpilled,
"Number of registers live across unwind edges");
42 Type *doubleUnderDataTy =
nullptr;
43 Type *doubleUnderJBufTy =
nullptr;
44 Type *FunctionContextTy =
nullptr;
47 Function *BuiltinSetupDispatchFn =
nullptr;
66 return "SJLJ Exception Handling preparation";
70 bool setupEntryBlockAndCallSites(
Function &
F);
79char SjLjEHPrepare::ID = 0;
85 return new SjLjEHPrepare(
TM);
90bool SjLjEHPrepare::doInitialization(
Module &M) {
97 doubleUnderDataTy = ArrayType::get(DataTy, 4);
98 doubleUnderJBufTy = ArrayType::get(VoidPtrTy, 5);
121 Builder.CreateGEP(FunctionContextTy, FuncCtx, Idxs,
"call_site");
125 Builder.CreateStore(CallSiteNoC, CallSite,
true );
132 if (!LiveBBs.
insert(BB).second)
146 while (!UseWorkList.empty()) {
147 Value *Val = UseWorkList.pop_back_val();
148 auto *EVI = dyn_cast<ExtractValueInst>(Val);
151 if (EVI->getNumIndices() != 1)
153 if (*EVI->idx_begin() == 0)
154 EVI->replaceAllUsesWith(ExnVal);
155 else if (*EVI->idx_begin() == 1)
156 EVI->replaceAllUsesWith(SelVal);
157 if (EVI->use_empty())
158 EVI->eraseFromParent();
168 auto *SelI = cast<Instruction>(SelVal);
170 LPadVal =
Builder.CreateInsertValue(LPadVal, ExnVal, 0,
"lpad.val");
171 LPadVal =
Builder.CreateInsertValue(LPadVal, SelVal, 1,
"lpad.val");
185 auto &
DL =
F.getParent()->getDataLayout();
186 const Align Alignment =
DL.getPrefTypeAlign(FunctionContextTy);
187 FuncCtx =
new AllocaInst(FunctionContextTy,
DL.getAllocaAddrSpace(),
nullptr,
188 Alignment,
"fn_context", &EntryBB->
front());
197 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 2,
"__data");
200 Value *ExceptionAddr =
Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,
201 0, 0,
"exception_gep");
202 Value *ExnVal =
Builder.CreateLoad(DataTy, ExceptionAddr,
true,
"exn_val");
205 Value *SelectorAddr =
Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,
206 0, 1,
"exn_selector_gep");
208 Builder.CreateLoad(DataTy, SelectorAddr,
true,
"exn_selector_val");
213 substituteLPadValues(LPI, ExnVal, SelVal);
218 Value *PersonalityFn =
F.getPersonalityFn();
219 Value *PersonalityFieldPtr =
Builder.CreateConstGEP2_32(
220 FunctionContextTy, FuncCtx, 0, 3,
"pers_fn_gep");
223 PersonalityFieldPtr,
true);
226 Value *LSDA =
Builder.CreateCall(LSDAAddrFn, {},
"lsda_addr");
227 Value *LSDAFieldPtr =
228 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 4,
"lsda_gep");
229 Builder.CreateStore(LSDA, LSDAFieldPtr,
true);
238void SjLjEHPrepare::lowerIncomingArguments(
Function &
F) {
240 while (isa<AllocaInst>(AfterAllocaInsPt) &&
241 cast<AllocaInst>(AfterAllocaInsPt)->isStaticAlloca())
243 assert(AfterAllocaInsPt !=
F.front().end());
245 for (
auto &AI :
F.args()) {
250 if (AI.isSwiftError())
253 Type *Ty = AI.getType();
260 AI.replaceAllUsesWith(SI);
263 SI->setOperand(1, &AI);
269void SjLjEHPrepare::lowerAcrossUnwindEdges(
Function &
F,
277 if (Inst.use_empty())
279 if (Inst.hasOneUse() &&
280 cast<Instruction>(Inst.user_back())->getParent() == &BB &&
281 !isa<PHINode>(Inst.user_back()))
286 if (
auto *AI = dyn_cast<AllocaInst>(&Inst))
287 if (AI->isStaticAlloca())
294 if (UI->
getParent() != &BB || isa<PHINode>(UI))
301 while (!
Users.empty()) {
304 if (!isa<PHINode>(U)) {
308 PHINode *PN = cast<PHINode>(U);
317 bool NeedsSpill =
false;
319 BasicBlock *UnwindBlock = Invoke->getUnwindDest();
320 if (UnwindBlock != &BB && LiveBBs.
count(UnwindBlock)) {
322 << UnwindBlock->
getName() <<
"\n");
341 BasicBlock *UnwindBlock = Invoke->getUnwindDest();
347 PHIsToDemote.
insert(cast<PHINode>(PN));
348 if (PHIsToDemote.
empty())
352 for (
PHINode *PN : PHIsToDemote)
363bool SjLjEHPrepare::setupEntryBlockAndCallSites(
Function &
F) {
370 if (
auto *II = dyn_cast<InvokeInst>(BB.getTerminator())) {
372 if (
Callee->getIntrinsicID() == Intrinsic::donothing) {
375 II->eraseFromParent();
380 LPads.
insert(II->getUnwindDest()->getLandingPadInst());
381 }
else if (
auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
388 NumInvokes += Invokes.
size();
390 lowerIncomingArguments(
F);
391 lowerAcrossUnwindEdges(
F, Invokes);
400 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 5,
"jbuf_gep");
413 Val =
Builder.CreateCall(StackAddrFn, {},
"sp");
414 Builder.CreateStore(Val, StackPtr,
true);
417 Builder.CreateCall(BuiltinSetupDispatchFn, {});
422 Builder.CreateCall(FuncCtxFn, FuncCtxArg);
426 for (
unsigned I = 0,
E = Invokes.
size();
I !=
E; ++
I) {
427 insertCallSiteStore(Invokes[
I],
I + 1);
443 if (&BB == &
F.front())
447 insertCallSiteStore(&
I, -1);
458 if (&BB == &
F.front())
461 if (
auto *CI = dyn_cast<CallInst>(&
I)) {
462 if (CI->getCalledFunction() != StackRestoreFn)
464 }
else if (!isa<AllocaInst>(&
I)) {
477 if (
CallInst *CI =
Return->getParent()->getTerminatingMustTailCall())
485bool SjLjEHPrepare::runOnFunction(
Function &
F) {
487 RegisterFn =
M.getOrInsertFunction(
489 PointerType::getUnqual(FunctionContextTy));
490 UnregisterFn =
M.getOrInsertFunction(
492 PointerType::getUnqual(FunctionContextTy));
494 &M, Intrinsic::frameaddress,
496 M.getDataLayout().getAllocaAddrSpace())});
499 BuiltinSetupDispatchFn =
505 bool Res = setupEntryBlockAndCallSites(
F);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
iv Induction Variable Users
Module.h This file contains the declarations for the Module class.
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
static void MarkBlocksLiveIn(BasicBlock *BB, SmallPtrSetImpl< BasicBlock * > &LiveBBs)
MarkBlocksLiveIn - Insert BB and all of its predecessors into LiveBBs until we reach blocks we've alr...
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static const unsigned FramePtr
an instruction to allocate memory on the stack
Represent the analysis usage information of a pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const LandingPadInst * getLandingPadInst() const
Return the landingpad instruction associated with the landing pad.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction & front() const
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const BasicBlock * getParent() const
void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
Class to represent integer types.
The landingpad instruction holds all of the information necessary to generate correct exception handl...
A Module instance is used to store all the information related to an LLVM module.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Wrapper class representing virtual and physical registers.
Return a value (possibly void), from a function.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", Instruction *InsertBefore=nullptr, Instruction *MDFrom=nullptr)
bool insert(const value_type &X)
Insert a new element into the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
iterator end()
Get an iterator to the end of the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Primary interface to the complete machine description for the target machine.
static constexpr unsigned DefaultSjLjDataSize
The integer bit size to use for SjLj based exception handling.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
static IntegerType * getInt32Ty(LLVMContext &C)
'undef' values are things that do not have specified contents.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createSjLjEHPreparePass(const TargetMachine *TM)
createSjLjEHPreparePass - This pass adapts exception handling code to use the GCC-style builtin setjm...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
AllocaInst * DemoteRegToStack(Instruction &X, bool VolatileLoads=false, Instruction *AllocaPoint=nullptr)
This function takes a virtual register computed by an Instruction and replaces it with a slot in the ...
AllocaInst * DemotePHIToStack(PHINode *P, Instruction *AllocaPoint=nullptr)
This function takes a virtual register computed by a phi node and replaces it with a slot in the stac...
This struct is a compact representation of a valid (non-zero power of two) alignment.