35#define DEBUG_TYPE "sjlj-eh-prepare"
38STATISTIC(NumSpilled,
"Number of registers live across unwind edges");
41class SjLjEHPrepareImpl {
43 Type *doubleUnderDataTy =
nullptr;
44 Type *doubleUnderJBufTy =
nullptr;
45 Type *FunctionContextTy =
nullptr;
48 Function *BuiltinSetupDispatchFn =
nullptr;
62 explicit SjLjEHPrepareImpl(
const TargetMachine *TM =
nullptr) : TM(TM) {}
63 bool doInitialization(
Module &M);
67 bool setupEntryBlockAndCallSites(
Function &
F);
68 void substituteLPadValues(LandingPadInst *LPI,
Value *ExnVal,
Value *SelVal);
72 void insertCallSiteStore(Instruction *
I,
int Number);
76 SjLjEHPrepareImpl Impl;
80 explicit SjLjEHPrepare(
const TargetMachine *TM =
nullptr)
81 : FunctionPass(ID), Impl(TM) {}
82 bool doInitialization(
Module &M)
override {
return Impl.doInitialization(M); }
85 StringRef getPassName()
const override {
86 return "SJLJ Exception Handling preparation";
94 SjLjEHPrepareImpl Impl(TM);
95 Impl.doInitialization(*
F.getParent());
96 bool Changed = Impl.runOnFunction(
F);
100char SjLjEHPrepare::ID = 0;
106 return new SjLjEHPrepare(TM);
111bool SjLjEHPrepareImpl::doInitialization(
Module &M) {
112 ExceptionModel =
M.getExceptionModel();
140 Value *
Zero = ConstantInt::get(Int32Ty, 0);
141 Value *One = ConstantInt::get(Int32Ty, 1);
144 Builder.CreateGEP(FunctionContextTy, FuncCtx, Idxs,
"call_site");
148 Builder.CreateStore(CallSiteNoC, CallSite,
true );
155 if (!LiveBBs.
insert(BB).second)
166 while (!UseWorkList.empty()) {
167 Value *Val = UseWorkList.pop_back_val();
171 if (EVI->getNumIndices() != 1)
173 if (*EVI->idx_begin() == 0)
174 EVI->replaceAllUsesWith(ExnVal);
175 else if (*EVI->idx_begin() == 1)
176 EVI->replaceAllUsesWith(SelVal);
177 if (EVI->use_empty())
178 EVI->eraseFromParent();
189 IRBuilder<> Builder(SelI->getParent(), std::next(SelI->getIterator()));
190 LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0,
"lpad.val");
191 LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1,
"lpad.val");
199SjLjEHPrepareImpl::setupFunctionContext(
Function &
F,
206 auto &
DL =
F.getDataLayout();
208 FuncCtx =
new AllocaInst(FunctionContextTy,
DL.getAllocaAddrSpace(),
nullptr,
209 Alignment,
"fn_context", EntryBB->
begin());
214 LPI->
getParent()->getFirstInsertionPt());
218 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 2,
"__data");
221 Value *ExceptionAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,
222 0, 0,
"exception_gep");
223 Value *ExnVal = Builder.CreateLoad(DataTy, ExceptionAddr,
true,
"exn_val");
224 ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getPtrTy());
226 Value *SelectorAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,
227 0, 1,
"exn_selector_gep");
229 Builder.CreateLoad(DataTy, SelectorAddr,
true,
"exn_selector_val");
234 substituteLPadValues(LPI, ExnVal, SelVal);
239 Value *PersonalityFn =
F.getPersonalityFn();
240 Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32(
241 FunctionContextTy, FuncCtx, 0, 3,
"pers_fn_gep");
242 Builder.CreateStore(PersonalityFn, PersonalityFieldPtr,
true);
245 Value *LSDA = Builder.CreateCall(LSDAAddrFn, {},
"lsda_addr");
246 Value *LSDAFieldPtr =
247 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 4,
"lsda_gep");
248 Builder.CreateStore(LSDA, LSDAFieldPtr,
true);
257void SjLjEHPrepareImpl::lowerIncomingArguments(
Function &
F) {
262 assert(AfterAllocaInsPt !=
F.front().end());
264 for (
auto &AI :
F.args()) {
269 if (AI.isSwiftError())
272 Type *Ty = AI.getType();
279 AI.replaceAllUsesWith(
SI);
282 SI->setOperand(1, &AI);
288void SjLjEHPrepareImpl::lowerAcrossUnwindEdges(
Function &
F,
296 if (Inst.use_empty())
298 if (Inst.hasOneUse() &&
306 if (AI->isStaticAlloca())
320 while (!
Users.empty()) {
336 bool NeedsSpill =
false;
338 BasicBlock *UnwindBlock = Invoke->getUnwindDest();
339 if (UnwindBlock != &BB && LiveBBs.
count(UnwindBlock)) {
341 << UnwindBlock->
getName() <<
"\n");
360 BasicBlock *UnwindBlock = Invoke->getUnwindDest();
367 if (PHIsToDemote.
empty())
371 for (
PHINode *PN : PHIsToDemote)
382bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(
Function &
F) {
390 if (
Function *Callee =
II->getCalledFunction())
391 if (
Callee->getIntrinsicID() == Intrinsic::donothing) {
394 II->eraseFromParent();
399 LPads.
insert(
II->getUnwindDest()->getLandingPadInst());
407 NumInvokes += Invokes.
size();
409 lowerIncomingArguments(
F);
410 lowerAcrossUnwindEdges(
F, Invokes);
419 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 5,
"jbuf_gep");
422 Value *
FramePtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 0,
425 Value *Val = Builder.CreateCall(FrameAddrFn, Builder.getInt32(0),
"fp");
426 Builder.CreateStore(Val,
FramePtr,
true);
429 Value *
StackPtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 2,
432 Val = Builder.CreateCall(StackAddrFn, {},
"sp");
433 Builder.CreateStore(Val, StackPtr,
true);
436 Builder.CreateCall(BuiltinSetupDispatchFn, {});
440 Builder.CreateCall(FuncCtxFn, FuncCtx);
448 for (
unsigned I = 0,
E = Invokes.
size();
I !=
E; ++
I) {
449 insertCallSiteStore(Invokes[
I],
I + 1);
465 if (&BB == &
F.front())
469 insertCallSiteStore(&
I, -1);
475 if (&BB == &
F.front())
479 if (CI->getCalledFunction() != StackRestoreFn)
495 if (
CallInst *CI =
Return->getParent()->getTerminatingMustTailCall())
503bool SjLjEHPrepareImpl::runOnFunction(
Function &
F) {
509 RegisterFn =
M.getOrInsertFunction(
512 UnregisterFn =
M.getOrInsertFunction(
516 PointerType *AllocaPtrTy =
M.getDataLayout().getAllocaPtrType(
M.getContext());
523 &M, Intrinsic::stackrestore, {AllocaPtrTy});
524 BuiltinSetupDispatchFn =
532 bool Res = setupEntryBlockAndCallSites(
F);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
iv Induction Variable Users
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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 a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI const LandingPadInst * getLandingPadInst() const
Return the landingpad instruction associated with the landing pad.
const Instruction & front() const
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
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.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
iterator_range< user_iterator > users()
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
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.
Class to represent pointers.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
In order to facilitate speculative execution, many instructions do not invoke immediate undefined beh...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
iterator end()
Get an iterator to the end of the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
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.
void insert_range(Range &&R)
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.
static LLVM_ABI 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 LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
self_iterator getIterator()
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI AllocaInst * DemoteRegToStack(Instruction &X, bool VolatileLoads=false, std::optional< BasicBlock::iterator > AllocaPoint=std::nullopt)
This function takes a virtual register computed by an Instruction and replaces it with a slot in the ...
LLVM_ABI AllocaInst * DemotePHIToStack(PHINode *P, std::optional< BasicBlock::iterator > AllocaPoint=std::nullopt)
This function takes a virtual register computed by a phi node and replaces it with a slot in the stac...
iterator_range< idf_iterator< T > > inverse_depth_first(const T &G)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI FunctionPass * createSjLjEHPreparePass(const TargetMachine *TM)
createSjLjEHPreparePass - This pass adapts exception handling code to use the GCC-style builtin setjm...
@ SjLj
setjmp/longjmp based exceptions
@ Default
Not specified; resolve to the target's default model.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.