215 using namespace llvm;
217 #define DEBUG_TYPE "wasm-lower-em-ehsjlj"
221 cl::desc(
"The list of function names in which Emscripten-style "
222 "exception handling is enabled (see emscripten "
223 "EMSCRIPTEN_CATCHING_WHITELIST options)"),
227 class WebAssemblyLowerEmscriptenEHSjLj final :
public ModulePass {
228 static const char *ThrewGVName;
229 static const char *ThrewValueGVName;
230 static const char *TempRet0GVName;
231 static const char *ResumeFName;
232 static const char *EHTypeIDFName;
233 static const char *SetThrewFName;
234 static const char *SetTempRet0FName;
235 static const char *EmLongjmpFName;
236 static const char *EmLongjmpJmpbufFName;
237 static const char *SaveSetjmpFName;
238 static const char *TestSetjmpFName;
239 static const char *FindMatchingCatchPrefix;
240 static const char *InvokePrefix;
261 std::set<std::string> EHWhitelistSet;
264 return "WebAssembly Lower Emscripten Exceptions";
271 template <
typename CallOrInvoke>
Value *wrapInvoke(CallOrInvoke *CI);
275 template <
typename CallOrInvoke>
Function *getInvokeWrapper(CallOrInvoke *CI);
277 bool areAllExceptionsAllowed()
const {
return EHWhitelistSet.empty(); }
278 bool canLongjmp(
Module &M,
const Value *Callee)
const;
280 void createSetThrewFunction(
Module &M);
281 void createSetTempRet0Function(
Module &M);
288 WebAssemblyLowerEmscriptenEHSjLj(
bool EnableEH =
true,
bool EnableSjLj =
true)
289 :
ModulePass(
ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj),
290 ThrewGV(nullptr), ThrewValueGV(nullptr), TempRet0GV(nullptr),
291 ResumeF(nullptr), EHTypeIDF(nullptr), EmLongjmpF(nullptr),
292 EmLongjmpJmpbufF(nullptr), SaveSetjmpF(nullptr), TestSetjmpF(nullptr) {
295 bool runOnModule(
Module &M)
override;
303 const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewGVName =
"__THREW__";
304 const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewValueGVName =
"__threwValue";
305 const char *WebAssemblyLowerEmscriptenEHSjLj::TempRet0GVName =
"__tempRet0";
306 const char *WebAssemblyLowerEmscriptenEHSjLj::ResumeFName =
"__resumeException";
307 const char *WebAssemblyLowerEmscriptenEHSjLj::EHTypeIDFName =
308 "llvm_eh_typeid_for";
309 const char *WebAssemblyLowerEmscriptenEHSjLj::SetThrewFName =
"setThrew";
310 const char *WebAssemblyLowerEmscriptenEHSjLj::SetTempRet0FName =
"setTempRet0";
311 const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpFName =
312 "emscripten_longjmp";
313 const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpJmpbufFName =
314 "emscripten_longjmp_jmpbuf";
315 const char *WebAssemblyLowerEmscriptenEHSjLj::SaveSetjmpFName =
"saveSetjmp";
316 const char *WebAssemblyLowerEmscriptenEHSjLj::TestSetjmpFName =
"testSetjmp";
317 const char *WebAssemblyLowerEmscriptenEHSjLj::FindMatchingCatchPrefix =
318 "__cxa_find_matching_catch_";
319 const char *WebAssemblyLowerEmscriptenEHSjLj::InvokePrefix =
"__invoke_";
323 "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
328 return new WebAssemblyLowerEmscriptenEHSjLj(EnableEH, EnableSjLj);
332 if (
const auto *
F = dyn_cast<const Function>(V)) {
334 if (
F->isIntrinsic())
338 if (Name ==
"setjmp" || Name ==
"longjmp")
340 return !
F->doesNotThrow();
350 const std::string &Propose) {
351 std::string
Name = Propose;
367 OS <<
"_" << *ParamTy;
371 Sig.erase(
remove_if(Sig, isspace), Sig.end());
374 std::replace(Sig.begin(), Sig.end(),
',',
'.');
384 WebAssemblyLowerEmscriptenEHSjLj::getFindMatchingCatch(
Module &M,
385 unsigned NumClauses) {
386 if (FindMatchingCatches.count(NumClauses))
387 return FindMatchingCatches[NumClauses];
393 FindMatchingCatchPrefix +
Twine(NumClauses + 2), &M);
394 FindMatchingCatches[NumClauses] =
F;
405 template <
typename CallOrInvoke>
406 Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallOrInvoke *CI) {
412 if (CI->doesNotReturn()) {
413 if (
auto *F = dyn_cast<Function>(CI->getCalledValue()))
419 IRB.SetInsertPoint(CI);
423 IRB.CreateStore(IRB.getInt32(0), ThrewGV);
430 Args.
append(CI->arg_begin(), CI->arg_end());
431 CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(CI), Args);
442 for (
unsigned e = CI->getNumArgOperands(); i <= e; ++AI, ++
i) {
445 AttributesVec.
push_back(AttributeSet::get(C, i + 1,
B));
455 AttributeSet NewCallPAL = AttributeSet::get(C, AttributesVec);
458 CI->replaceAllUsesWith(NewCall);
462 Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() +
".val");
463 IRB.CreateStore(IRB.getInt32(0), ThrewGV);
468 template <
typename CallOrInvoke>
469 Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(CallOrInvoke *CI) {
470 Module *M = CI->getModule();
472 Value *Callee = CI->getCalledValue();
474 if (
auto *F = dyn_cast<Function>(Callee))
477 auto *CalleeTy = cast<PointerType>(Callee->
getType())->getElementType();
482 if (InvokeWrappers.find(Sig) != InvokeWrappers.end())
483 return InvokeWrappers[Sig];
493 InvokePrefix + Sig, M);
494 InvokeWrappers[Sig] =
F;
498 bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(
Module &M,
499 const Value *Callee)
const {
500 if (
auto *CalleeF = dyn_cast<Function>(Callee))
501 if (CalleeF->isIntrinsic())
509 if (Callee == SetjmpF || Callee == MallocF || Callee == FreeF)
513 if (Callee == ResumeF || Callee == EHTypeIDF || Callee == SaveSetjmpF ||
514 Callee == TestSetjmpF)
527 if (Callee == BeginCatchF || Callee == EndCatchF ||
528 Callee == AllocExceptionF || Callee == ThrowF || Callee == TerminateF)
549 void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
556 IRB.SetInsertPoint(InsertPt);
559 IRB.SetInsertPoint(BB);
563 Value *ThrewCmp = IRB.CreateICmpNE(Threw, IRB.getInt32(0));
565 IRB.CreateLoad(ThrewValueGV, ThrewValueGV->getName() +
".val");
566 Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0));
567 Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp,
"cmp1");
568 IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1);
572 IRB.SetInsertPoint(ThenBB1);
578 IRB.CreateLoad(ThrewInt, ThrewInt->
getName() +
".loaded");
579 Value *ThenLabel = IRB.CreateCall(
580 TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize},
"label");
581 Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0));
582 IRB.CreateCondBr(Cmp2, ThenBB2, EndBB2);
585 IRB.SetInsertPoint(ThenBB2);
586 IRB.CreateCall(EmLongjmpF, {Threw, ThrewValue});
587 IRB.CreateUnreachable();
590 IRB.SetInsertPoint(EndBB2);
591 IRB.CreateStore(ThrewValue, TempRet0GV);
592 IRB.CreateBr(EndBB1);
594 IRB.SetInsertPoint(ElseBB1);
595 IRB.CreateBr(EndBB1);
598 IRB.SetInsertPoint(EndBB1);
599 PHINode *LabelPHI = IRB.CreatePHI(IRB.getInt32Ty(), 2,
"label");
607 LongjmpResult = IRB.CreateLoad(TempRet0GV,
"longjmp_result");
617 void WebAssemblyLowerEmscriptenEHSjLj::createSetThrewFunction(
Module &M) {
626 Argument *Arg1 = &*(F->arg_begin());
634 IRB.SetInsertPoint(EntryBB);
635 Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() +
".val");
636 Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(0),
"cmp");
637 IRB.CreateCondBr(Cmp, ThenBB, EndBB);
639 IRB.SetInsertPoint(ThenBB);
640 IRB.CreateStore(Arg1, ThrewGV);
641 IRB.CreateStore(Arg2, ThrewValueGV);
644 IRB.SetInsertPoint(EndBB);
652 void WebAssemblyLowerEmscriptenEHSjLj::createSetTempRet0Function(
Module &M) {
661 F->arg_begin()->setName(
"value");
663 IRB.SetInsertPoint(EntryBB);
664 IRB.CreateStore(&*F->arg_begin(), TempRet0GV);
668 void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(
Function &F) {
669 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
674 for (
auto UI =
I.use_begin(), UE =
I.use_end(); UI != UE;) {
683 if (
PHINode *UserPN = dyn_cast<PHINode>(User))
684 if (UserPN->getIncomingBlock(U) == &BB)
695 bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(
Module &M) {
701 bool SetjmpUsed = SetjmpF && !SetjmpF->
use_empty();
702 bool LongjmpUsed = LongjmpF && !LongjmpF->
use_empty();
703 bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);
717 bool Changed =
false;
734 if (F.isDeclaration())
736 Changed |= runEHOnFunction(F);
744 Function *MallocF = M.getFunction(
"malloc");
745 Function *FreeF = M.getFunction(
"free");
746 if (!MallocF || !FreeF)
748 "malloc and free must be linked into the module if setjmp is used");
758 SaveSetjmpFName, &M);
764 TestSetjmpFName, &M);
771 EmLongjmpJmpbufFName, &M);
776 {IRB.getInt32Ty(), IRB.getInt32Ty()},
false);
783 for (User *U : SetjmpF->
users()) {
784 auto *UI = cast<Instruction>(U);
785 SetjmpUsers.
insert(UI->getFunction());
788 runSjLjOnFunction(*F);
793 ThrewGV->eraseFromParent();
797 ResumeF->eraseFromParent();
799 EHTypeIDF->eraseFromParent();
801 EmLongjmpF->eraseFromParent();
803 SaveSetjmpF->eraseFromParent();
805 TestSetjmpF->eraseFromParent();
812 createSetThrewFunction(M);
813 createSetTempRet0Function(M);
818 bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(
Function &F) {
822 bool Changed =
false;
825 bool AllowExceptions =
826 areAllExceptionsAllowed() || EHWhitelistSet.
count(F.
getName());
833 LandingPads.
insert(II->getLandingPadInst());
834 IRB.SetInsertPoint(II);
836 bool NeedInvoke = AllowExceptions &&
canThrow(II->getCalledValue());
839 Value *Threw = wrapInvoke(II);
843 Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(1),
"cmp");
844 IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest());
850 CallInst *NewCall = IRB.CreateCall(II->getCalledValue(),
Args);
851 NewCall->takeName(II);
852 NewCall->setCallingConv(II->getCallingConv());
853 NewCall->setDebugLoc(II->getDebugLoc());
854 NewCall->setAttributes(II->getAttributes());
855 II->replaceAllUsesWith(NewCall);
858 IRB.CreateBr(II->getNormalDest());
861 II->getUnwindDest()->removePredecessor(&BB);
874 Value *Input = RI->getValue();
875 IRB.SetInsertPoint(RI);
876 Value *Low = IRB.CreateExtractValue(Input, 0,
"low");
878 IRB.CreateCall(ResumeF, {Low});
880 IRB.CreateUnreachable();
891 const Function *Callee = CI->getCalledFunction();
897 IRB.SetInsertPoint(CI);
899 IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0),
"typeid");
908 if (
auto *LPI = dyn_cast<LandingPadInst>(I))
915 IRB.SetInsertPoint(LPI);
917 for (
unsigned i = 0, e = LPI->getNumClauses(); i < e; ++
i) {
918 Constant *Clause = LPI->getClause(i);
922 if (LPI->isFilter(i)) {
923 auto *ATy = cast<ArrayType>(Clause->
getType());
924 for (
unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
933 Function *FMCF = getFindMatchingCatch(M, FMCArgs.
size());
934 CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs,
"fmc");
936 Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0,
"pair0");
938 IRB.CreateLoad(TempRet0GV, TempRet0GV->
getName() +
".val");
939 Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1,
"pair1");
952 bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(
Function &F) {
958 std::vector<Instruction *> SetjmpTableInsts;
960 std::vector<Instruction *> SetjmpTableSizeInsts;
974 SetjmpTableSize, IRB.getInt32Ty(), IRB.getInt32Ty(), IRB.getInt32(40),
975 nullptr,
nullptr,
"setjmpTable");
977 IRB.SetInsertPoint(SetjmpTableSize);
978 IRB.CreateStore(IRB.getInt32(0), SetjmpTable);
979 SetjmpTableInsts.push_back(SetjmpTable);
980 SetjmpTableSizeInsts.push_back(SetjmpTableSize);
983 std::vector<PHINode *> SetjmpRetPHIs;
985 for (User *U : SetjmpF->
users()) {
1001 PHINode *SetjmpRet = IRB.CreatePHI(IRB.getInt32Ty(), 2,
"setjmp.ret");
1006 CI->replaceAllUsesWith(SetjmpRet);
1008 SetjmpRetPHIs.push_back(SetjmpRet);
1013 IRB.SetInsertPoint(CI);
1014 Value *Args[] = {CI->getArgOperand(0), IRB.getInt32(SetjmpRetPHIs.size()),
1015 SetjmpTable, SetjmpTableSize};
1017 IRB.CreateCall(SaveSetjmpF, Args,
"setjmpTable");
1019 IRB.CreateLoad(TempRet0GV,
"setjmpTableSize");
1020 SetjmpTableInsts.push_back(NewSetjmpTable);
1021 SetjmpTableSizeInsts.push_back(NewSetjmpTableSize);
1031 std::vector<BasicBlock *> BBs;
1036 for (
unsigned i = 0; i < BBs.size(); i++) {
1039 assert(!isa<InvokeInst>(&I));
1044 const Value *Callee = CI->getCalledValue();
1045 if (!canLongjmp(M, Callee))
1048 Value *Threw =
nullptr;
1059 if (
auto *LI = dyn_cast<LoadInst>(I))
1060 if (
auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand()))
1061 if (GV == ThrewGV) {
1062 Threw = ThrewLI = LI;
1070 if (
auto *SI = dyn_cast<StoreInst>(I))
1071 if (
auto *GV = dyn_cast<GlobalVariable>(
SI->getPointerOperand()))
1072 if (GV == ThrewGV &&
SI->getValueOperand() == IRB.getInt32(0)) {
1077 assert(Threw && ThrewLI &&
"Cannot find __THREW__ load after invoke");
1078 assert(ThrewResetSI &&
"Cannot find __THREW__ store after invoke");
1083 Threw = wrapInvoke(CI);
1096 Value *Label =
nullptr;
1097 Value *LongjmpResult =
nullptr;
1099 wrapTestSetjmp(BB, CI, Threw, SetjmpTable, SetjmpTableSize, Label,
1100 LongjmpResult, EndBB);
1101 assert(Label && LongjmpResult && EndBB);
1104 IRB.SetInsertPoint(EndBB);
1110 for (
unsigned i = 0; i < SetjmpRetPHIs.size(); i++) {
1111 SI->
addCase(IRB.getInt32(i + 1), SetjmpRetPHIs[
i]->getParent());
1112 SetjmpRetPHIs[
i]->addIncoming(LongjmpResult, EndBB);
1117 BBs.push_back(Tail);
1128 if (isa<ReturnInst>(TI))
1153 for (
auto UI = SetjmpTable->use_begin(), UE = SetjmpTable->use_end();
1163 for (
auto UI = SetjmpTableSize->
use_begin(), UE = SetjmpTableSize->
use_end();
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
Helper class for SSA formation on a set of values defined in multiple blocks.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
ModulePass * createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH, bool DoSjLj)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
BasicBlock * SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the specified block at the specified instruction - everything before SplitPt stays in Old and e...
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
A Module instance is used to store all the information related to an LLVM module. ...
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value...
void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
This class represents a function call, abstracting a target machine's calling convention.
ArrayRef< Type * > params() const
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
static PointerType * getInt32PtrTy(LLVMContext &C, unsigned AS=0)
Externally visible function.
const Function * getParent() const
Return the enclosing method, or null if none.
An instruction for reading from memory.
static Instruction * CreateFree(Value *Source, Instruction *InsertBefore)
Generate the IR for a call to the builtin free function.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static bool canThrow(const Value *V)
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
StringRef getName() const
Return a constant reference to the value's name.
void setCallingConv(CallingConv::ID CC)
AnalysisUsage & addRequired()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr it the function does no...
A Use represents the edge between a Value definition and its users.
param_iterator param_end() const
Instruction * getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void setName(const Twine &Name)
Change the name of the value.
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
Class to represent function types.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Class to represent pointers.
void setAttributes(AttributeSet Attrs)
Set the parameter attributes for this call.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Type * getParamType(unsigned i) const
Parameter type accessors.
The landingpad instruction holds all of the information necessary to generate correct exception handl...
Subclasses of this class are all able to terminate a basic block.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
This is an important base class in LLVM.
Resume the propagation of an exception.
param_iterator param_begin() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
User * getUser() const
Returns the User that contains this Use.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Type * getType() const
All values are typed, get the type of this value.
GlobalVariable * getNamedGlobal(StringRef Name)
Return the global variable in the module with the specified name, of arbitrary type.
const BasicBlock & getEntryBlock() const
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), Instruction *InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
iterator_range< user_iterator > users()
INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE,"WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp", false, false) ModulePass *llvm
static Instruction * CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, Type *AllocTy, Value *AllocSize, Value *ArraySize=nullptr, Function *MallocF=nullptr, const Twine &Name="")
Generate the IR for a call to malloc:
static IntegerType * getInt32Ty(LLVMContext &C)
bool hasAttributes(unsigned Index) const
Return true if attribute exists at the given index.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
static std::string createGlobalValueName(const Module &M, const std::string &Propose)
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
void recalculate(FT &F)
recalculate - compute a dominator tree for the given function
StringRef - Represent a constant reference to a string, i.e.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
Legacy analysis pass which computes a DominatorTree.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
void RewriteUse(Use &U)
Rewrite a use of the symbolic value.
static std::string getSignature(FunctionType *FTy)
const BasicBlock * getParent() const
LLVMContext & getContext() const
Get the global data context.
static cl::list< std::string > EHWhitelist("emscripten-cxx-exceptions-whitelist", cl::desc("The list of function names in which Emscripten-style ""exception handling is enabled (see emscripten ""EMSCRIPTEN_CATCHING_WHITELIST options)"), cl::CommaSeparated)
AttributeSet getFnAttributes() const
The function attributes are returned.