272#include "llvm/IR/IntrinsicsWebAssembly.h" 
  283#define DEBUG_TYPE "wasm-lower-em-ehsjlj" 
  287                cl::desc(
"The list of function names in which Emscripten-style " 
  288                         "exception handling is enabled (see emscripten " 
  289                         "EMSCRIPTEN_CATCHING_ALLOWED options)"),
 
  293class WebAssemblyLowerEmscriptenEHSjLj final : 
public ModulePass {
 
  307  Function *WasmSetjmpTestF = 
nullptr;    
 
  312  Type *LongjmpArgsTy = 
nullptr;
 
  320  std::set<std::string, std::less<>> EHAllowlistSet;
 
  325    return "WebAssembly Lower Emscripten Exceptions";
 
  328  using InstVector = SmallVectorImpl<Instruction *>;
 
  329  bool runEHOnFunction(Function &
F);
 
  330  bool runSjLjOnFunction(Function &
F);
 
  331  void handleLongjmpableCallsForEmscriptenSjLj(
 
  332      Function &
F, Instruction *FunctionInvocationId,
 
  333      SmallVectorImpl<PHINode *> &SetjmpRetPHIs);
 
  335  handleLongjmpableCallsForWasmSjLj(Function &
F,
 
  336                                    Instruction *FunctionInvocationId,
 
  337                                    SmallVectorImpl<PHINode *> &SetjmpRetPHIs);
 
  340  Value *wrapInvoke(CallBase *CI);
 
  343                      Value *&LongjmpResult, BasicBlock *&CallEmLongjmpBB,
 
  344                      PHINode *&CallEmLongjmpBBThrewPHI,
 
  345                      PHINode *&CallEmLongjmpBBThrewValuePHI,
 
  347  Function *getInvokeWrapper(CallBase *CI);
 
  349  bool areAllExceptionsAllowed()
 const { 
return EHAllowlistSet.empty(); }
 
  350  bool supportsException(
const Function *
F)
 const {
 
  352           (areAllExceptionsAllowed() || EHAllowlistSet.count(
F->getName()));
 
  354  void replaceLongjmpWith(Function *LongjmpF, Function *NewF);
 
  356  void rebuildSSA(Function &
F);
 
  361  WebAssemblyLowerEmscriptenEHSjLj()
 
  365    assert(!(EnableEmSjLj && EnableWasmSjLj) &&
 
  366           "Two SjLj modes cannot be turned on at the same time");
 
  367    assert(!(EnableEmEH && EnableWasmSjLj) &&
 
  368           "Wasm SjLj should be only used with Wasm EH");
 
  371  bool runOnModule(
Module &M) 
override;
 
  373  void getAnalysisUsage(AnalysisUsage &AU)
 const override {
 
  379char WebAssemblyLowerEmscriptenEHSjLj::ID = 0;
 
  381                "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
 
  385  return new WebAssemblyLowerEmscriptenEHSjLj();
 
 
  391    if (
F->isIntrinsic())
 
  395    if (Name == 
"setjmp" || Name == 
"longjmp" || Name == 
"emscripten_longjmp")
 
  397    return !
F->doesNotThrow();
 
 
  429  OS << *FTy->getReturnType();
 
  430  for (
Type *ParamTy : FTy->params())
 
  431    OS << 
"_" << *ParamTy;
 
 
  451  if (!
F->hasFnAttribute(
"wasm-import-module")) {
 
  452    llvm::AttrBuilder 
B(
F->getParent()->getContext());
 
  453    B.addAttribute(
"wasm-import-module", 
"env");
 
  456  if (!
F->hasFnAttribute(
"wasm-import-name")) {
 
  457    llvm::AttrBuilder 
B(
F->getParent()->getContext());
 
  458    B.addAttribute(
"wasm-import-name", 
F->getName());
 
 
  467  return IRB.
getIntNTy(M->getDataLayout().getPointerSizeInBits());
 
 
  482  return IRB.
getIntN(M->getDataLayout().getPointerSizeInBits(), 
C);
 
 
  491WebAssemblyLowerEmscriptenEHSjLj::getFindMatchingCatch(
Module &M,
 
  492                                                       unsigned NumClauses) {
 
  496  PointerType *Int8PtrTy = PointerType::getUnqual(
M.getContext());
 
  498  FunctionType *FTy = FunctionType::get(Int8PtrTy, Args, 
false);
 
  500      FTy, 
"__cxa_find_matching_catch_" + Twine(NumClauses + 2), &M);
 
  513Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) {
 
  515  LLVMContext &
C = 
M->getContext();
 
  518  IRB.SetInsertPoint(CI);
 
  525  SmallVector<Value *, 16> 
Args;
 
  530  CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(CI), Args);
 
  544    ArgAttributes.
push_back(InvokeAL.getParamAttrs(
I));
 
  546  AttrBuilder FnAttrs(CI->
getContext(), InvokeAL.getFnAttrs());
 
  547  if (
auto Args = FnAttrs.getAllocSizeArgs()) {
 
  550    auto [SizeArg, NEltArg] = *
Args;
 
  553      NEltArg = *NEltArg + 1;
 
  554    FnAttrs.addAllocSizeAttr(SizeArg, NEltArg);
 
  558  FnAttrs.removeAttribute(Attribute::NoReturn);
 
  561  AttributeList NewCallAL = AttributeList::get(
 
  576Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(CallBase *CI) {
 
  582  auto It = InvokeWrappers.
find(Sig);
 
  583  if (It != InvokeWrappers.
end())
 
  589  ArgTys.
append(CalleeFTy->param_begin(), CalleeFTy->param_end());
 
  591  FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys,
 
  592                                        CalleeFTy->isVarArg());
 
  595  InvokeWrappers[Sig] = 
F;
 
  601    if (CalleeF->isIntrinsic())
 
  610  StringRef CalleeName = Callee->getName();
 
  616  if (CalleeName == 
"setjmp" || CalleeName == 
"malloc" || CalleeName == 
"free")
 
  620  if (CalleeName == 
"__resumeException" || CalleeName == 
"llvm_eh_typeid_for" ||
 
  621      CalleeName == 
"__wasm_setjmp" || CalleeName == 
"__wasm_setjmp_test" ||
 
  622      CalleeName == 
"getTempRet0" || CalleeName == 
"setTempRet0")
 
  626  if (Callee->getName().starts_with(
"__cxa_find_matching_catch_"))
 
  661  if (CalleeName == 
"__cxa_end_catch")
 
  663  if (CalleeName == 
"__cxa_begin_catch" ||
 
  664      CalleeName == 
"__cxa_allocate_exception" || CalleeName == 
"__cxa_throw" ||
 
  665      CalleeName == 
"__clang_call_terminate")
 
  670  if (CalleeName == 
"_ZSt9terminatev")
 
 
  678  StringRef CalleeName = Callee->getName();
 
  680  return CalleeName == 
"emscripten_asm_const_int" ||
 
  681         CalleeName == 
"emscripten_asm_const_double" ||
 
  682         CalleeName == 
"emscripten_asm_const_int_sync_on_main_thread" ||
 
  683         CalleeName == 
"emscripten_asm_const_double_sync_on_main_thread" ||
 
  684         CalleeName == 
"emscripten_asm_const_async_on_main_thread";
 
 
  703void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
 
  705    Value *&Label, 
Value *&LongjmpResult, BasicBlock *&CallEmLongjmpBB,
 
  706    PHINode *&CallEmLongjmpBBThrewPHI, PHINode *&CallEmLongjmpBBThrewValuePHI,
 
  707    BasicBlock *&EndBB) {
 
  710  LLVMContext &
C = 
M->getContext();
 
  712  IRB.SetCurrentDebugLocation(
DL);
 
  715  IRB.SetInsertPoint(BB);
 
  720  Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV,
 
  721                                     ThrewValueGV->
getName() + 
".val");
 
  722  Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0));
 
  723  Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, 
"cmp1");
 
  724  IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1);
 
  727  if (!CallEmLongjmpBB) {
 
  730    IRB.SetInsertPoint(CallEmLongjmpBB);
 
  731    CallEmLongjmpBBThrewPHI = IRB.CreatePHI(
getAddrIntType(M), 4, 
"threw.phi");
 
  732    CallEmLongjmpBBThrewValuePHI =
 
  733        IRB.CreatePHI(IRB.getInt32Ty(), 4, 
"threwvalue.phi");
 
  734    CallEmLongjmpBBThrewPHI->
addIncoming(Threw, ThenBB1);
 
  735    CallEmLongjmpBBThrewValuePHI->
addIncoming(ThrewValue, ThenBB1);
 
  736    IRB.CreateCall(EmLongjmpF,
 
  737                   {CallEmLongjmpBBThrewPHI, CallEmLongjmpBBThrewValuePHI});
 
  738    IRB.CreateUnreachable();
 
  740    CallEmLongjmpBBThrewPHI->
addIncoming(Threw, ThenBB1);
 
  741    CallEmLongjmpBBThrewValuePHI->
addIncoming(ThrewValue, ThenBB1);
 
  746  IRB.SetInsertPoint(ThenBB1);
 
  750  Value *ThenLabel = IRB.CreateCall(WasmSetjmpTestF,
 
  751                                    {ThrewPtr, FunctionInvocationId}, 
"label");
 
  752  Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0));
 
  753  IRB.CreateCondBr(Cmp2, CallEmLongjmpBB, EndBB2);
 
  756  IRB.SetInsertPoint(EndBB2);
 
  757  IRB.CreateCall(SetTempRet0F, ThrewValue);
 
  758  IRB.CreateBr(EndBB1);
 
  760  IRB.SetInsertPoint(ElseBB1);
 
  761  IRB.CreateBr(EndBB1);
 
  764  IRB.SetInsertPoint(EndBB1);
 
  765  PHINode *LabelPHI = IRB.CreatePHI(IRB.getInt32Ty(), 2, 
"label");
 
  773  LongjmpResult = IRB.CreateCall(GetTempRet0F, {}, 
"longjmp_result");
 
  776void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &
F) {
 
  777  DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
 
  781  for (BasicBlock &BB : 
F) {
 
  782    for (Instruction &
I : BB) {
 
  783      if (
I.getType()->isVoidTy())
 
  790        bool HasNonDominatedLifetimeMarker = 
any_of(
I.users(), [&](User *U) {
 
  791          auto *UserI = cast<Instruction>(U);
 
  792          return UserI->isLifetimeStartOrEnd() && !DT.dominates(&I, UserI);
 
  794        if (HasNonDominatedLifetimeMarker) {
 
  797            if (UserI->isLifetimeStartOrEnd())
 
  798              UserI->eraseFromParent();
 
  803      unsigned VarID = 
SSA.AddVariable(
I.getName(), 
I.getType());
 
  810      for (
auto &U : 
I.uses()) {
 
  813          if (UserPN->getIncomingBlock(U) == &BB)
 
  821  SSA.RewriteAllUses(&DT);
 
  832void WebAssemblyLowerEmscriptenEHSjLj::replaceLongjmpWith(Function *LongjmpF,
 
  834  assert(NewF == EmLongjmpF || NewF == WasmLongjmpF);
 
  842  for (User *U : LongjmpF->
users()) {
 
  845      IRB.SetInsertPoint(CI);
 
  846      Value *Env = 
nullptr;
 
  847      if (NewF == EmLongjmpF)
 
  851        Env = IRB.CreateBitCast(CI->
getArgOperand(0), IRB.getPtrTy(), 
"env");
 
  856  for (
auto *
I : ToErase)
 
  857    I->eraseFromParent();
 
  861  if (!LongjmpF->
uses().empty()) {
 
  863        IRB.CreateBitCast(NewF, LongjmpF->
getType(), 
"longjmp.cast");
 
  869  for (
const auto &BB : *
F)
 
  870    for (
const auto &
I : BB)
 
 
  901  for (
auto *
I : ToErase)
 
  902    I->eraseFromParent();
 
 
  905bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(
Module &M) {
 
  906  LLVM_DEBUG(
dbgs() << 
"********** Lower Emscripten EH & SjLj **********\n");
 
  908  LLVMContext &
C = 
M.getContext();
 
  911  Function *SetjmpF = 
M.getFunction(
"setjmp");
 
  912  Function *LongjmpF = 
M.getFunction(
"longjmp");
 
  917  Function *SetjmpF2 = 
M.getFunction(
"_setjmp");
 
  918  Function *LongjmpF2 = 
M.getFunction(
"_longjmp");
 
  933            "longjmp and _longjmp have different function types");
 
  941  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
 
  942  assert(TPC && 
"Expected a TargetPassConfig");
 
  943  auto &
TM = TPC->getTM<WebAssemblyTargetMachine>();
 
  950  GetTempRet0F = 
getFunction(FunctionType::get(IRB.getInt32Ty(), 
false),
 
  953      getFunction(FunctionType::get(IRB.getVoidTy(), IRB.getInt32Ty(), 
false),
 
  963    FunctionType *ResumeFTy =
 
  964        FunctionType::get(IRB.getVoidTy(), IRB.getPtrTy(), 
false);
 
  965    ResumeF = 
getFunction(ResumeFTy, 
"__resumeException", &M);
 
  969    FunctionType *EHTypeIDTy =
 
  970        FunctionType::get(IRB.getInt32Ty(), IRB.getPtrTy(), 
false);
 
  971    EHTypeIDF = 
getFunction(EHTypeIDTy, 
"llvm_eh_typeid_for", &M);
 
  976  SmallPtrSet<Function *, 4> SetjmpUsersToNullify;
 
  978  if ((EnableEmSjLj || EnableWasmSjLj) && SetjmpF) {
 
  980    for (User *U : SetjmpF->
users()) {
 
  982        auto *UserF = CB->getFunction();
 
  987          SetjmpUsers.
insert(UserF);
 
  989          SetjmpUsersToNullify.
insert(UserF);
 
  992        raw_string_ostream 
SS(S);
 
 1000  bool SetjmpUsed = SetjmpF && !SetjmpUsers.
empty();
 
 1001  bool LongjmpUsed = LongjmpF && !LongjmpF->
use_empty();
 
 1002  DoSjLj = (EnableEmSjLj | EnableWasmSjLj) && (SetjmpUsed || LongjmpUsed);
 
 1006    assert(EnableEmSjLj || EnableWasmSjLj);
 
 1009      FunctionType *FTy = FunctionType::get(
 
 1010          IRB.getVoidTy(), {getAddrIntType(&M), IRB.getInt32Ty()}, 
false);
 
 1011      EmLongjmpF = 
getFunction(FTy, 
"emscripten_longjmp", &M);
 
 1012      EmLongjmpF->
addFnAttr(Attribute::NoReturn);
 
 1014      Type *Int8PtrTy = IRB.getPtrTy();
 
 1016      FunctionType *FTy = FunctionType::get(
 
 1017          IRB.getVoidTy(), {Int8PtrTy, IRB.getInt32Ty()}, 
false);
 
 1018      WasmLongjmpF = 
getFunction(FTy, 
"__wasm_longjmp", &M);
 
 1019      WasmLongjmpF->
addFnAttr(Attribute::NoReturn);
 
 1023      Type *Int8PtrTy = IRB.getPtrTy();
 
 1024      Type *Int32PtrTy = IRB.getPtrTy();
 
 1029      FunctionType *FTy = FunctionType::get(
 
 1030          IRB.getVoidTy(), {SetjmpFTy->getParamType(0), Int32Ty, Int32PtrTy},
 
 1032      WasmSetjmpF = 
getFunction(FTy, 
"__wasm_setjmp", &M);
 
 1035      FTy = FunctionType::get(
Int32Ty, {Int32PtrTy, Int32PtrTy}, 
false);
 
 1036      WasmSetjmpTestF = 
getFunction(FTy, 
"__wasm_setjmp_test", &M);
 
 1050    for (Function &
F : M) {
 
 1051      if (
F.isDeclaration())
 
 1061      replaceLongjmpWith(LongjmpF, EnableEmSjLj ? EmLongjmpF : WasmLongjmpF);
 
 1065      for (Function *
F : SetjmpUsers)
 
 1066        runSjLjOnFunction(*
F);
 
 1070  if ((EnableEmSjLj || EnableWasmSjLj) && !SetjmpUsersToNullify.
empty()) {
 
 1073    for (Function *
F : SetjmpUsersToNullify)
 
 1078  for (
auto *V : {ThrewGV, ThrewValueGV})
 
 1079    if (V && 
V->use_empty())
 
 1080      V->eraseFromParent();
 
 1081  for (
auto *V : {GetTempRet0F, SetTempRet0F, ResumeF, EHTypeIDF, EmLongjmpF,
 
 1082                  WasmSetjmpF, WasmSetjmpTestF, WasmLongjmpF, CatchF})
 
 1083    if (V && 
V->use_empty())
 
 1084      V->eraseFromParent();
 
 1089bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &
F) {
 
 1091  LLVMContext &
C = 
F.getContext();
 
 1095  SmallPtrSet<LandingPadInst *, 32> LandingPads;
 
 1101  PHINode *RethrowLongjmpBBThrewPHI = 
nullptr;
 
 1103  for (BasicBlock &BB : 
F) {
 
 1108    LandingPads.
insert(
II->getLandingPadInst());
 
 1109    IRB.SetInsertPoint(
II);
 
 1112    bool NeedInvoke = supportsException(&
F) && 
canThrow(Callee);
 
 1115      Value *Threw = wrapInvoke(
II);
 
 1138      if (DoSjLj && EnableEmSjLj && !SetjmpUsers.
count(&
F) &&
 
 1141        if (!RethrowLongjmpBB) {
 
 1143          IRB.SetInsertPoint(RethrowLongjmpBB);
 
 1144          RethrowLongjmpBBThrewPHI =
 
 1146          RethrowLongjmpBBThrewPHI->
addIncoming(Threw, &BB);
 
 1147          Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV,
 
 1148                                             ThrewValueGV->
getName() + 
".val");
 
 1149          IRB.CreateCall(EmLongjmpF, {RethrowLongjmpBBThrewPHI, ThrewValue});
 
 1150          IRB.CreateUnreachable();
 
 1152          RethrowLongjmpBBThrewPHI->
addIncoming(Threw, &BB);
 
 1155        IRB.SetInsertPoint(
II); 
 
 1161        Value *
Or = IRB.CreateOr(CmpEqZero, CmpEqOne, 
"or");
 
 1162        IRB.CreateCondBr(
Or, 
Tail, RethrowLongjmpBB);
 
 1163        IRB.SetInsertPoint(
Tail);
 
 1164        BB.replaceSuccessorsPhiUsesWith(&BB, 
Tail);
 
 1169      IRB.CreateCondBr(Cmp, 
II->getUnwindDest(), 
II->getNormalDest());
 
 1179  for (BasicBlock &BB : 
F) {
 
 1181    for (Instruction &
I : BB) {
 
 1188      Value *Input = RI->getValue();
 
 1189      IRB.SetInsertPoint(RI);
 
 1190      Value *
Low = IRB.CreateExtractValue(Input, 0, 
"low");
 
 1192      IRB.CreateCall(ResumeF, {
Low});
 
 1194      IRB.CreateUnreachable();
 
 1200  for (BasicBlock &BB : 
F) {
 
 1201    for (Instruction &
I : BB) {
 
 1208      if (
Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
 
 1212      IRB.SetInsertPoint(CI);
 
 1221  for (BasicBlock &BB : 
F) {
 
 1230  for (LandingPadInst *LPI : LandingPads) {
 
 1231    IRB.SetInsertPoint(LPI);
 
 1232    SmallVector<Value *, 16> FMCArgs;
 
 1233    for (
unsigned I = 0, 
E = LPI->getNumClauses(); 
I < 
E; ++
I) {
 
 1237      if (LPI->isCatch(
I))
 
 1242    Function *FMCF = getFindMatchingCatch(M, FMCArgs.
size());
 
 1243    CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, 
"fmc");
 
 1245    Value *Pair0 = IRB.CreateInsertValue(
Poison, FMCI, 0, 
"pair0");
 
 1246    Value *TempRet0 = IRB.CreateCall(GetTempRet0F, {}, 
"tempret0");
 
 1247    Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, 
"pair1");
 
 1249    LPI->replaceAllUsesWith(Pair1);
 
 1254  for (Instruction *
I : ToErase)
 
 1255    I->eraseFromParent();
 
 1281bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &
F) {
 
 1282  assert(EnableEmSjLj || EnableWasmSjLj);
 
 1284  LLVMContext &
C = 
F.getContext();
 
 1291  for (Instruction &
I : 
F.getEntryBlock())
 
 1293      if (AI->isStaticAlloca())
 
 1301  for (AllocaInst *AI : StaticAllocas)
 
 1302    AI->moveBefore(
Entry->getTerminator()->getIterator());
 
 1304  IRB.SetInsertPoint(
Entry->getTerminator()->getIterator());
 
 1309      IRB.CreateAlloca(IRB.getInt32Ty(), 
nullptr, 
"functionInvocationId");
 
 1314  Function *SetjmpF = 
M.getFunction(
"setjmp");
 
 1322      raw_string_ostream 
SS(S);
 
 1323      SS << 
"In function " + 
F.getName() +
 
 1324                ": setjmp within a catch clause is not supported in Wasm EH:\n";
 
 1329    CallInst *CI = 
nullptr;
 
 1342    IRB.SetInsertPoint(
Tail, 
Tail->getFirstNonPHIIt());
 
 1343    PHINode *SetjmpRet = IRB.CreatePHI(IRB.getInt32Ty(), 2, 
"setjmp.ret");
 
 1355    IRB.SetInsertPoint(CI);
 
 1357                     FunctionInvocationId};
 
 1358    IRB.CreateCall(WasmSetjmpF, Args);
 
 1364    handleLongjmpableCallsForEmscriptenSjLj(
F, FunctionInvocationId,
 
 1367    handleLongjmpableCallsForWasmSjLj(
F, FunctionInvocationId, SetjmpRetPHIs);
 
 1370  for (Instruction *
I : ToErase)
 
 1371    I->eraseFromParent();
 
 1390void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForEmscriptenSjLj(
 
 1391    Function &
F, Instruction *FunctionInvocationId,
 
 1392    SmallVectorImpl<PHINode *> &SetjmpRetPHIs) {
 
 1394  LLVMContext &
C = 
F.getContext();
 
 1402  PHINode *CallEmLongjmpBBThrewPHI = 
nullptr;
 
 1405  PHINode *CallEmLongjmpBBThrewValuePHI = 
nullptr;
 
 1412  std::vector<BasicBlock *> BBs;
 
 1413  for (BasicBlock &BB : 
F)
 
 1417  for (
unsigned I = 0; 
I < BBs.size(); 
I++) {
 
 1419    for (Instruction &
I : *BB) {
 
 1422        raw_string_ostream 
SS(S);
 
 1423        SS << 
"In function " << 
F.getName()
 
 1424           << 
": When using Wasm EH with Emscripten SjLj, there is a " 
 1425              "restriction that `setjmp` function call and exception cannot be " 
 1426              "used within the same function:\n";
 
 1440                               ". Please consider using EM_JS, or move the " 
 1441                               "EM_ASM into another function.",
 
 1444      Value *Threw = 
nullptr;
 
 1446      if (
Callee->getName().starts_with(
"__invoke_")) {
 
 1451        LoadInst *ThrewLI = 
nullptr;
 
 1452        StoreInst *ThrewResetSI = 
nullptr;
 
 1457              if (GV == ThrewGV) {
 
 1458                Threw = ThrewLI = LI;
 
 1468              if (GV == ThrewGV &&
 
 1476        assert(Threw && ThrewLI && 
"Cannot find __THREW__ load after invoke");
 
 1477        assert(ThrewResetSI && 
"Cannot find __THREW__ store after invoke");
 
 1482        Threw = wrapInvoke(CI);
 
 1507        if (supportsException(&
F) && 
canThrow(Callee)) {
 
 1513          if (!RethrowExnBB) {
 
 1515            IRB.SetInsertPoint(RethrowExnBB);
 
 1517                IRB.CreateCall(getFindMatchingCatch(M, 0), {}, 
"exn");
 
 1518            IRB.CreateCall(ResumeF, {Exn});
 
 1519            IRB.CreateUnreachable();
 
 1522          IRB.SetInsertPoint(CI);
 
 1526          IRB.CreateCondBr(CmpEqOne, RethrowExnBB, NormalBB);
 
 1528          IRB.SetInsertPoint(NormalBB);
 
 1543      Value *LongjmpResult = 
nullptr;
 
 1545      wrapTestSetjmp(BB, CI->
getDebugLoc(), Threw, FunctionInvocationId, Label,
 
 1546                     LongjmpResult, CallEmLongjmpBB, CallEmLongjmpBBThrewPHI,
 
 1547                     CallEmLongjmpBBThrewValuePHI, EndBB);
 
 1548      assert(Label && LongjmpResult && EndBB);
 
 1551      IRB.SetInsertPoint(EndBB);
 
 1553      SwitchInst *
SI = IRB.CreateSwitch(Label, 
Tail, SetjmpRetPHIs.
size());
 
 1558      for (
unsigned I = 0; 
I < SetjmpRetPHIs.
size(); 
I++) {
 
 1559        SI->addCase(IRB.getInt32(
I + 1), SetjmpRetPHIs[
I]->getParent());
 
 1560        SetjmpRetPHIs[
I]->addIncoming(LongjmpResult, EndBB);
 
 1565      BBs.push_back(
Tail);
 
 1569  for (Instruction *
I : ToErase)
 
 1570    I->eraseFromParent();
 
 1576      return CRI->getUnwindDest();
 
 
 1585void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
 
 1586    Function &
F, Instruction *FunctionInvocationId,
 
 1587    SmallVectorImpl<PHINode *> &SetjmpRetPHIs) {
 
 1589  LLVMContext &
C = 
F.getContext();
 
 1596  if (!
F.hasPersonalityFn()) {
 
 1598    FunctionType *PersType =
 
 1599        FunctionType::get(IRB.getInt32Ty(),  
true);
 
 1600    Value *PersF = 
M.getOrInsertFunction(PersName, PersType).getCallee();
 
 1608  IRB.SetCurrentDebugLocation(FirstDL);
 
 1629  IRB.SetInsertPoint(CatchDispatchLongjmpBB);
 
 1630  CatchSwitchInst *CatchSwitchLongjmp =
 
 1635  CatchSwitchLongjmp->
addHandler(CatchLongjmpBB);
 
 1636  IRB.SetInsertPoint(CatchLongjmpBB);
 
 1637  CatchPadInst *CatchPad = IRB.CreateCatchPad(CatchSwitchLongjmp, {});
 
 1646      IRB.CreateConstGEP2_32(LongjmpArgsTy, LongjmpArgs, 0, 0, 
"env_gep");
 
 1648      IRB.CreateConstGEP2_32(LongjmpArgsTy, LongjmpArgs, 0, 1, 
"val_gep");
 
 1650  Instruction *Env = IRB.CreateLoad(IRB.getPtrTy(), EnvField, 
"env");
 
 1652  Instruction *Val = IRB.CreateLoad(IRB.getInt32Ty(), ValField, 
"val");
 
 1661  Value *
Label = IRB.CreateCall(WasmSetjmpTestF, {EnvP, FunctionInvocationId},
 
 1663  Value *
Cmp = IRB.CreateICmpEQ(Label, IRB.getInt32(0));
 
 1664  IRB.CreateCondBr(Cmp, ThenBB, EndBB);
 
 1666  IRB.SetInsertPoint(ThenBB);
 
 1667  CallInst *WasmLongjmpCI = IRB.CreateCall(
 
 1669  IRB.CreateUnreachable();
 
 1671  IRB.SetInsertPoint(EndBB);
 
 1673  IRB.CreateCatchRet(CatchPad, SetjmpDispatchBB);
 
 1683  IRB.SetInsertPoint(SetjmpDispatchBB);
 
 1684  PHINode *LabelPHI = IRB.CreatePHI(IRB.getInt32Ty(), 2, 
"label.phi");
 
 1687  SwitchInst *
SI = IRB.CreateSwitch(LabelPHI, OrigEntry, SetjmpRetPHIs.
size());
 
 1692  for (
unsigned I = 0; 
I < SetjmpRetPHIs.
size(); 
I++) {
 
 1693    SI->addCase(IRB.getInt32(
I + 1), SetjmpRetPHIs[
I]->getParent());
 
 1694    SetjmpRetPHIs[
I]->addIncoming(Val, SetjmpDispatchBB);
 
 1700  for (
auto *BB = &*
F.begin(); BB; BB = BB->getNextNode()) {
 
 1701    for (
auto &
I : *BB) {
 
 1711                               ". Please consider using EM_JS, or move the " 
 1712                               "EM_ASM into another function.",
 
 1717      if (CI == WasmLongjmpCI)
 
 1723  SmallDenseMap<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4>
 
 1724      UnwindDestToNewPreds;
 
 1725  for (
auto *CI : LongjmpableCalls) {
 
 1731      CalleeF->removeFnAttr(Attribute::NoUnwind);
 
 1740      while (!UnwindDest) {
 
 1742          UnwindDest = CPI->getCatchSwitch()->getUnwindDest();
 
 1752          Value *ParentPad = CPI->getParentPad();
 
 1760      UnwindDest = CatchDispatchLongjmpBB;
 
 1769  SmallVector<Instruction *, 16> ToErase;
 
 1770  for (
auto &BB : 
F) {
 
 1772      if (CSI != CatchSwitchLongjmp && CSI->unwindsToCaller()) {
 
 1773        IRB.SetInsertPoint(CSI);
 
 1775        auto *NewCSI = IRB.CreateCatchSwitch(CSI->getParentPad(),
 
 1776                                             CatchDispatchLongjmpBB, 1);
 
 1777        NewCSI->addHandler(*CSI->handler_begin());
 
 1778        NewCSI->takeName(CSI);
 
 1779        CSI->replaceAllUsesWith(NewCSI);
 
 1784      if (CRI->unwindsToCaller()) {
 
 1785        IRB.SetInsertPoint(CRI);
 
 1787        IRB.CreateCleanupRet(CRI->getCleanupPad(), CatchDispatchLongjmpBB);
 
 1792  for (Instruction *
I : ToErase)
 
 1793    I->eraseFromParent();
 
 1801  for (
auto &[UnwindDest, NewPreds] : UnwindDestToNewPreds) {
 
 1802    for (PHINode &PN : UnwindDest->
phis()) {
 
 1803      for (
auto *NewPred : NewPreds) {
 
 1804        assert(PN.getBasicBlockIndex(NewPred) == -1);
 
 1815  for (
auto &[UnwindDest, NewPreds] : UnwindDestToNewPreds) {
 
 1816    for (PHINode &PN : UnwindDest->
phis()) {
 
 1818      SSA.Initialize(PN.getType(), PN.getName());
 
 1819      for (
unsigned Idx = 0, 
E = PN.getNumIncomingValues(); Idx != 
E; ++Idx) {
 
 1820        if (NewPreds.contains(PN.getIncomingBlock(Idx)))
 
 1822        Value *
V = PN.getIncomingValue(Idx);
 
 1824          SSA.AddAvailableValue(
II->getNormalDest(), 
II);
 
 1826          SSA.AddAvailableValue(
I->getParent(), 
I);
 
 1828          SSA.AddAvailableValue(PN.getIncomingBlock(Idx), V);
 
 1830      for (
auto *NewPred : NewPreds)
 
 1831        PN.setIncomingValueForBlock(NewPred, 
SSA.GetValueAtEndOfBlock(NewPred));
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
 
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
 
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
 
Module.h This file contains the declarations for the Module class.
 
Machine Check Debug Module
 
uint64_t IntrinsicInst * II
 
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
 
Target-Independent Code Generator Pass Configuration Options pass.
 
static void nullifySetjmp(Function *F)
 
static void markAsImported(Function *F)
 
static bool canLongjmp(const Value *Callee)
 
static cl::list< std::string > EHAllowlist("emscripten-cxx-exceptions-allowed", cl::desc("The list of function names in which Emscripten-style " "exception handling is enabled (see emscripten " "EMSCRIPTEN_CATCHING_ALLOWED options)"), cl::CommaSeparated)
 
static Type * getAddrPtrType(Module *M)
 
static std::string getSignature(FunctionType *FTy)
 
static Type * getAddrIntType(Module *M)
 
static bool canThrow(const Value *V)
 
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
 
static DebugLoc getOrCreateDebugLoc(const Instruction *InsertBefore, DISubprogram *SP)
 
static bool containsLongjmpableCalls(const Function *F)
 
static Value * getAddrSizeInt(Module *M, uint64_t C)
 
static GlobalVariable * getGlobalVariable(Module &M, Type *Ty, WebAssemblyTargetMachine &TM, const char *Name)
 
static bool isEmAsmCall(const Value *Callee)
 
This file declares the WebAssembly-specific subclass of TargetMachine.
 
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
 
static BasicBlock * getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad)
 
AnalysisUsage & addRequired()
 
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
 
LLVM Basic Block Representation.
 
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
 
const Function * getParent() const
Return the enclosing method, or null if none.
 
const Instruction & back() const
 
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
 
InstListType::iterator iterator
Instruction iterators...
 
void setCallingConv(CallingConv::ID CC)
 
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
 
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
 
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
 
Value * getCalledOperand() const
 
void setAttributes(AttributeList A)
Set the attributes for this call.
 
Value * getArgOperand(unsigned i) const
 
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
 
FunctionType * getFunctionType() const
 
void removeFnAttr(Attribute::AttrKind Kind)
Removes the attribute from the function.
 
unsigned arg_size() const
 
AttributeList getAttributes() const
Return the attributes for this call.
 
This class represents a function call, abstracting a target machine's calling convention.
 
LLVM_ABI void addHandler(BasicBlock *Dest)
Add an entry to the switch instruction... Note: This action invalidates handler_end().
 
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
 
Subprogram description. Uses SubclassData1.
 
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
 
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
 
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
 
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
 
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
 
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
 
FunctionType * getFunctionType() const
Returns the FunctionType for me.
 
const Function & getFunction() const
 
Module * getParent()
Get the module that this global value is contained inside of...
 
PointerType * getType() const
Global values are always pointers.
 
@ ExternalLinkage
Externally visible function.
 
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
 
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
 
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
 
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
 
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
 
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
 
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
 
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
 
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
 
A Module instance is used to store all the information related to an LLVM module.
 
LLVMContext & getContext() const
Get the global data context.
 
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
 
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
 
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
 
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.
 
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
 
void push_back(const T &Elt)
 
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
 
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
 
iterator find(StringRef Key)
 
StringRef - Represent a constant reference to a string, i.e.
 
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.
 
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
 
The instances of the Type class are immutable: once they are created, they are never changed.
 
LLVM Value Representation.
 
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
 
iterator_range< user_iterator > users()
 
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
 
iterator_range< use_iterator > uses()
 
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
 
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
 
const ParentTy * getParent() const
 
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
 
A raw_ostream that writes to an std::string.
 
std::string & str()
Returns the string's reference.
 
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
 
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
 
@ C
The default llvm calling convention, compatible with C.
 
@ BasicBlock
Various leaf nodes.
 
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
 
cl::opt< bool > WasmEnableSjLj
 
cl::opt< bool > WasmEnableEmEH
 
cl::opt< bool > WasmEnableEmSjLj
 
@ User
could "use" a pointer
 
friend class Instruction
Iterator for Instructions in a `BasicBlock.
 
This is an optimization pass for GlobalISel generic memory operations.
 
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
 
FunctionAddr VTableAddr Value
 
std::tuple< const DIScope *, const DIScope *, const DILocalVariable * > VarID
A unique key that represents a debug variable.
 
LLVM_ABI StringRef getEHPersonalityName(EHPersonality Pers)
 
LLVM_ABI BasicBlock * changeToInvokeAndSplitBasicBlock(CallInst *CI, BasicBlock *UnwindEdge, DomTreeUpdater *DTU=nullptr)
Convert the CallInst to InvokeInst with the specified unwind edge basic block.
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
 
LLVM_ABI CallInst * changeToCall(InvokeInst *II, DomTreeUpdater *DTU=nullptr)
This function converts the specified invoke into a normal call.
 
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
 
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
 
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
 
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...
 
ModulePass * createWebAssemblyLowerEmscriptenEHSjLj()
 
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
 
OperandBundleDefT< Value * > OperandBundleDef
 
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
 
@ Or
Bitwise or logical OR of integers.
 
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
 
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="", bool Before=false)
Split the specified block at the specified instruction.
 
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
 
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.