LLVM  8.0.0svn
WebAssemblyLowerEmscriptenEHSjLj.cpp
Go to the documentation of this file.
1 //=== WebAssemblyLowerEmscriptenEHSjLj.cpp - Lower exceptions for Emscripten =//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file lowers exception-related instructions and setjmp/longjmp
12 /// function calls in order to use Emscripten's JavaScript try and catch
13 /// mechanism.
14 ///
15 /// To handle exceptions and setjmp/longjmps, this scheme relies on JavaScript's
16 /// try and catch syntax and relevant exception-related libraries implemented
17 /// in JavaScript glue code that will be produced by Emscripten. This is similar
18 /// to the current Emscripten asm.js exception handling in fastcomp. For
19 /// fastcomp's EH / SjLj scheme, see these files in fastcomp LLVM branch:
20 /// (Location: https://github.com/kripken/emscripten-fastcomp)
21 /// lib/Target/JSBackend/NaCl/LowerEmExceptionsPass.cpp
22 /// lib/Target/JSBackend/NaCl/LowerEmSetjmp.cpp
23 /// lib/Target/JSBackend/JSBackend.cpp
24 /// lib/Target/JSBackend/CallHandlers.h
25 ///
26 /// * Exception handling
27 /// This pass lowers invokes and landingpads into library functions in JS glue
28 /// code. Invokes are lowered into function wrappers called invoke wrappers that
29 /// exist in JS side, which wraps the original function call with JS try-catch.
30 /// If an exception occurred, cxa_throw() function in JS side sets some
31 /// variables (see below) so we can check whether an exception occurred from
32 /// wasm code and handle it appropriately.
33 ///
34 /// * Setjmp-longjmp handling
35 /// This pass lowers setjmp to a reasonably-performant approach for emscripten.
36 /// The idea is that each block with a setjmp is broken up into two parts: the
37 /// part containing setjmp and the part right after the setjmp. The latter part
38 /// is either reached from the setjmp, or later from a longjmp. To handle the
39 /// longjmp, all calls that might longjmp are also called using invoke wrappers
40 /// and thus JS / try-catch. JS longjmp() function also sets some variables so
41 /// we can check / whether a longjmp occurred from wasm code. Each block with a
42 /// function call that might longjmp is also split up after the longjmp call.
43 /// After the longjmp call, we check whether a longjmp occurred, and if it did,
44 /// which setjmp it corresponds to, and jump to the right post-setjmp block.
45 /// We assume setjmp-longjmp handling always run after EH handling, which means
46 /// we don't expect any exception-related instructions when SjLj runs.
47 /// FIXME Currently this scheme does not support indirect call of setjmp,
48 /// because of the limitation of the scheme itself. fastcomp does not support it
49 /// either.
50 ///
51 /// In detail, this pass does following things:
52 ///
53 /// 1) Create three global variables: __THREW__, __threwValue, and __tempRet0.
54 /// __tempRet0 will be set within __cxa_find_matching_catch() function in
55 /// JS library, and __THREW__ and __threwValue will be set in invoke wrappers
56 /// in JS glue code. For what invoke wrappers are, refer to 3). These
57 /// variables are used for both exceptions and setjmp/longjmps.
58 /// __THREW__ indicates whether an exception or a longjmp occurred or not. 0
59 /// means nothing occurred, 1 means an exception occurred, and other numbers
60 /// mean a longjmp occurred. In the case of longjmp, __threwValue variable
61 /// indicates the corresponding setjmp buffer the longjmp corresponds to.
62 /// In exception handling, __tempRet0 indicates the type of an exception
63 /// caught, and in setjmp/longjmp, it means the second argument to longjmp
64 /// function.
65 ///
66 /// * Exception handling
67 ///
68 /// 2) Create setThrew and setTempRet0 functions.
69 /// The global variables created in 1) will exist in wasm address space,
70 /// but their values should be set in JS code, so we provide these functions
71 /// as interfaces to JS glue code. These functions are equivalent to the
72 /// following JS functions, which actually exist in asm.js version of JS
73 /// library.
74 ///
75 /// function setThrew(threw, value) {
76 /// if (__THREW__ == 0) {
77 /// __THREW__ = threw;
78 /// __threwValue = value;
79 /// }
80 /// }
81 ///
82 /// function setTempRet0(value) {
83 /// __tempRet0 = value;
84 /// }
85 ///
86 /// 3) Lower
87 /// invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad
88 /// into
89 /// __THREW__ = 0;
90 /// call @__invoke_SIG(func, arg1, arg2)
91 /// %__THREW__.val = __THREW__;
92 /// __THREW__ = 0;
93 /// if (%__THREW__.val == 1)
94 /// goto %lpad
95 /// else
96 /// goto %invoke.cont
97 /// SIG is a mangled string generated based on the LLVM IR-level function
98 /// signature. After LLVM IR types are lowered to the target wasm types,
99 /// the names for these wrappers will change based on wasm types as well,
100 /// as in invoke_vi (function takes an int and returns void). The bodies of
101 /// these wrappers will be generated in JS glue code, and inside those
102 /// wrappers we use JS try-catch to generate actual exception effects. It
103 /// also calls the original callee function. An example wrapper in JS code
104 /// would look like this:
105 /// function invoke_vi(index,a1) {
106 /// try {
107 /// Module["dynCall_vi"](index,a1); // This calls original callee
108 /// } catch(e) {
109 /// if (typeof e !== 'number' && e !== 'longjmp') throw e;
110 /// asm["setThrew"](1, 0); // setThrew is called here
111 /// }
112 /// }
113 /// If an exception is thrown, __THREW__ will be set to true in a wrapper,
114 /// so we can jump to the right BB based on this value.
115 ///
116 /// 4) Lower
117 /// %val = landingpad catch c1 catch c2 catch c3 ...
118 /// ... use %val ...
119 /// into
120 /// %fmc = call @__cxa_find_matching_catch_N(c1, c2, c3, ...)
121 /// %val = {%fmc, __tempRet0}
122 /// ... use %val ...
123 /// Here N is a number calculated based on the number of clauses.
124 /// Global variable __tempRet0 is set within __cxa_find_matching_catch() in
125 /// JS glue code.
126 ///
127 /// 5) Lower
128 /// resume {%a, %b}
129 /// into
130 /// call @__resumeException(%a)
131 /// where __resumeException() is a function in JS glue code.
132 ///
133 /// 6) Lower
134 /// call @llvm.eh.typeid.for(type) (intrinsic)
135 /// into
136 /// call @llvm_eh_typeid_for(type)
137 /// llvm_eh_typeid_for function will be generated in JS glue code.
138 ///
139 /// * Setjmp / Longjmp handling
140 ///
141 /// 7) In the function entry that calls setjmp, initialize setjmpTable and
142 /// sejmpTableSize as follows:
143 /// setjmpTableSize = 4;
144 /// setjmpTable = (int *) malloc(40);
145 /// setjmpTable[0] = 0;
146 /// setjmpTable and setjmpTableSize are used in saveSetjmp() function in JS
147 /// code.
148 ///
149 /// 8) Lower
150 /// setjmp(buf)
151 /// into
152 /// setjmpTable = saveSetjmp(buf, label, setjmpTable, setjmpTableSize);
153 /// setjmpTableSize = __tempRet0;
154 /// For each dynamic setjmp call, setjmpTable stores its ID (a number which
155 /// is incrementally assigned from 0) and its label (a unique number that
156 /// represents each callsite of setjmp). When we need more entries in
157 /// setjmpTable, it is reallocated in saveSetjmp() in JS code and it will
158 /// return the new table address, and assign the new table size in
159 /// __tempRet0. saveSetjmp also stores the setjmp's ID into the buffer buf.
160 /// A BB with setjmp is split into two after setjmp call in order to make the
161 /// post-setjmp BB the possible destination of longjmp BB.
162 ///
163 /// 9) Lower
164 /// longjmp(buf, value)
165 /// into
166 /// emscripten_longjmp_jmpbuf(buf, value)
167 /// emscripten_longjmp_jmpbuf will be lowered to emscripten_longjmp later.
168 ///
169 /// 10) Lower every call that might longjmp into
170 /// __THREW__ = 0;
171 /// call @__invoke_SIG(func, arg1, arg2)
172 /// %__THREW__.val = __THREW__;
173 /// __THREW__ = 0;
174 /// if (%__THREW__.val != 0 & __threwValue != 0) {
175 /// %label = testSetjmp(mem[%__THREW__.val], setjmpTable,
176 /// setjmpTableSize);
177 /// if (%label == 0)
178 /// emscripten_longjmp(%__THREW__.val, __threwValue);
179 /// __tempRet0 = __threwValue;
180 /// } else {
181 /// %label = -1;
182 /// }
183 /// longjmp_result = __tempRet0;
184 /// switch label {
185 /// label 1: goto post-setjmp BB 1
186 /// label 2: goto post-setjmp BB 2
187 /// ...
188 /// default: goto splitted next BB
189 /// }
190 /// testSetjmp examines setjmpTable to see if there is a matching setjmp
191 /// call. After calling an invoke wrapper, if a longjmp occurred, __THREW__
192 /// will be the address of matching jmp_buf buffer and __threwValue be the
193 /// second argument to longjmp. mem[__THREW__.val] is a setjmp ID that is
194 /// stored in saveSetjmp. testSetjmp returns a setjmp label, a unique ID to
195 /// each setjmp callsite. Label 0 means this longjmp buffer does not
196 /// correspond to one of the setjmp callsites in this function, so in this
197 /// case we just chain the longjmp to the caller. (Here we call
198 /// emscripten_longjmp, which is different from emscripten_longjmp_jmpbuf.
199 /// emscripten_longjmp_jmpbuf takes jmp_buf as its first argument, while
200 /// emscripten_longjmp takes an int. Both of them will eventually be lowered
201 /// to emscripten_longjmp in s2wasm, but here we need two signatures - we
202 /// can't translate an int value to a jmp_buf.)
203 /// Label -1 means no longjmp occurred. Otherwise we jump to the right
204 /// post-setjmp BB based on the label.
205 ///
206 ///===----------------------------------------------------------------------===//
207 
208 #include "WebAssembly.h"
209 #include "llvm/IR/CallSite.h"
210 #include "llvm/IR/Dominators.h"
211 #include "llvm/IR/IRBuilder.h"
214 
215 using namespace llvm;
216 
217 #define DEBUG_TYPE "wasm-lower-em-ehsjlj"
218 
220  EHWhitelist("emscripten-cxx-exceptions-whitelist",
221  cl::desc("The list of function names in which Emscripten-style "
222  "exception handling is enabled (see emscripten "
223  "EMSCRIPTEN_CATCHING_WHITELIST options)"),
225 
226 namespace {
227 class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
228  static const char *ResumeFName;
229  static const char *EHTypeIDFName;
230  static const char *EmLongjmpFName;
231  static const char *EmLongjmpJmpbufFName;
232  static const char *SaveSetjmpFName;
233  static const char *TestSetjmpFName;
234  static const char *FindMatchingCatchPrefix;
235  static const char *InvokePrefix;
236 
237  bool EnableEH; // Enable exception handling
238  bool EnableSjLj; // Enable setjmp/longjmp handling
239 
240  GlobalVariable *ThrewGV;
241  GlobalVariable *ThrewValueGV;
242  GlobalVariable *TempRet0GV;
243  Function *ResumeF;
244  Function *EHTypeIDF;
245  Function *EmLongjmpF;
246  Function *EmLongjmpJmpbufF;
247  Function *SaveSetjmpF;
248  Function *TestSetjmpF;
249 
250  // __cxa_find_matching_catch_N functions.
251  // Indexed by the number of clauses in an original landingpad instruction.
252  DenseMap<int, Function *> FindMatchingCatches;
253  // Map of <function signature string, invoke_ wrappers>
254  StringMap<Function *> InvokeWrappers;
255  // Set of whitelisted function names for exception handling
256  std::set<std::string> EHWhitelistSet;
257 
258  StringRef getPassName() const override {
259  return "WebAssembly Lower Emscripten Exceptions";
260  }
261 
262  bool runEHOnFunction(Function &F);
263  bool runSjLjOnFunction(Function &F);
264  Function *getFindMatchingCatch(Module &M, unsigned NumClauses);
265 
266  template <typename CallOrInvoke> Value *wrapInvoke(CallOrInvoke *CI);
267  void wrapTestSetjmp(BasicBlock *BB, Instruction *InsertPt, Value *Threw,
268  Value *SetjmpTable, Value *SetjmpTableSize, Value *&Label,
269  Value *&LongjmpResult, BasicBlock *&EndBB);
270  template <typename CallOrInvoke> Function *getInvokeWrapper(CallOrInvoke *CI);
271 
272  bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); }
273  bool canLongjmp(Module &M, const Value *Callee) const;
274 
275  void createSetThrewFunction(Module &M);
276  void createSetTempRet0Function(Module &M);
277 
278  void rebuildSSA(Function &F);
279 
280 public:
281  static char ID;
282 
283  WebAssemblyLowerEmscriptenEHSjLj(bool EnableEH = true, bool EnableSjLj = true)
284  : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj),
285  ThrewGV(nullptr), ThrewValueGV(nullptr), TempRet0GV(nullptr),
286  ResumeF(nullptr), EHTypeIDF(nullptr), EmLongjmpF(nullptr),
287  EmLongjmpJmpbufF(nullptr), SaveSetjmpF(nullptr), TestSetjmpF(nullptr) {
288  EHWhitelistSet.insert(EHWhitelist.begin(), EHWhitelist.end());
289  }
290  bool runOnModule(Module &M) override;
291 
292  void getAnalysisUsage(AnalysisUsage &AU) const override {
294  }
295 };
296 } // End anonymous namespace
297 
298 const char *WebAssemblyLowerEmscriptenEHSjLj::ResumeFName = "__resumeException";
299 const char *WebAssemblyLowerEmscriptenEHSjLj::EHTypeIDFName =
300  "llvm_eh_typeid_for";
301 const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpFName =
302  "emscripten_longjmp";
303 const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpJmpbufFName =
304  "emscripten_longjmp_jmpbuf";
305 const char *WebAssemblyLowerEmscriptenEHSjLj::SaveSetjmpFName = "saveSetjmp";
306 const char *WebAssemblyLowerEmscriptenEHSjLj::TestSetjmpFName = "testSetjmp";
307 const char *WebAssemblyLowerEmscriptenEHSjLj::FindMatchingCatchPrefix =
308  "__cxa_find_matching_catch_";
309 const char *WebAssemblyLowerEmscriptenEHSjLj::InvokePrefix = "__invoke_";
310 
312 INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE,
313  "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
314  false, false)
315 
317  bool EnableSjLj) {
318  return new WebAssemblyLowerEmscriptenEHSjLj(EnableEH, EnableSjLj);
319 }
320 
321 static bool canThrow(const Value *V) {
322  if (const auto *F = dyn_cast<const Function>(V)) {
323  // Intrinsics cannot throw
324  if (F->isIntrinsic())
325  return false;
326  StringRef Name = F->getName();
327  // leave setjmp and longjmp (mostly) alone, we process them properly later
328  if (Name == "setjmp" || Name == "longjmp")
329  return false;
330  return !F->doesNotThrow();
331  }
332  // not a function, so an indirect call - can throw, we can't tell
333  return true;
334 }
335 
337  const char *Name) {
338  if (M.getNamedGlobal(Name))
339  report_fatal_error(Twine("variable name is reserved: ") + Name);
340 
341  return new GlobalVariable(M, IRB.getInt32Ty(), false,
343 }
344 
345 // Simple function name mangler.
346 // This function simply takes LLVM's string representation of parameter types
347 // and concatenate them with '_'. There are non-alphanumeric characters but llc
348 // is ok with it, and we need to postprocess these names after the lowering
349 // phase anyway.
350 static std::string getSignature(FunctionType *FTy) {
351  std::string Sig;
352  raw_string_ostream OS(Sig);
353  OS << *FTy->getReturnType();
354  for (Type *ParamTy : FTy->params())
355  OS << "_" << *ParamTy;
356  if (FTy->isVarArg())
357  OS << "_...";
358  Sig = OS.str();
359  Sig.erase(remove_if(Sig, isspace), Sig.end());
360  // When s2wasm parses .s file, a comma means the end of an argument. So a
361  // mangled function name can contain any character but a comma.
362  std::replace(Sig.begin(), Sig.end(), ',', '.');
363  return Sig;
364 }
365 
366 // Returns __cxa_find_matching_catch_N function, where N = NumClauses + 2.
367 // This is because a landingpad instruction contains two more arguments, a
368 // personality function and a cleanup bit, and __cxa_find_matching_catch_N
369 // functions are named after the number of arguments in the original landingpad
370 // instruction.
371 Function *
372 WebAssemblyLowerEmscriptenEHSjLj::getFindMatchingCatch(Module &M,
373  unsigned NumClauses) {
374  if (FindMatchingCatches.count(NumClauses))
375  return FindMatchingCatches[NumClauses];
376  PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext());
377  SmallVector<Type *, 16> Args(NumClauses, Int8PtrTy);
378  FunctionType *FTy = FunctionType::get(Int8PtrTy, Args, false);
379  Function *F =
381  FindMatchingCatchPrefix + Twine(NumClauses + 2), &M);
382  FindMatchingCatches[NumClauses] = F;
383  return F;
384 }
385 
386 // Generate invoke wrapper seqence with preamble and postamble
387 // Preamble:
388 // __THREW__ = 0;
389 // Postamble:
390 // %__THREW__.val = __THREW__; __THREW__ = 0;
391 // Returns %__THREW__.val, which indicates whether an exception is thrown (or
392 // whether longjmp occurred), for future use.
393 template <typename CallOrInvoke>
394 Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallOrInvoke *CI) {
395  LLVMContext &C = CI->getModule()->getContext();
396 
397  // If we are calling a function that is noreturn, we must remove that
398  // attribute. The code we insert here does expect it to return, after we
399  // catch the exception.
400  if (CI->doesNotReturn()) {
401  if (auto *F = dyn_cast<Function>(CI->getCalledValue()))
402  F->removeFnAttr(Attribute::NoReturn);
403  CI->removeAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
404  }
405 
406  IRBuilder<> IRB(C);
407  IRB.SetInsertPoint(CI);
408 
409  // Pre-invoke
410  // __THREW__ = 0;
411  IRB.CreateStore(IRB.getInt32(0), ThrewGV);
412 
413  // Invoke function wrapper in JavaScript
415  // Put the pointer to the callee as first argument, so it can be called
416  // within the invoke wrapper later
417  Args.push_back(CI->getCalledValue());
418  Args.append(CI->arg_begin(), CI->arg_end());
419  CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(CI), Args);
420  NewCall->takeName(CI);
421  NewCall->setCallingConv(CI->getCallingConv());
422  NewCall->setDebugLoc(CI->getDebugLoc());
423 
424  // Because we added the pointer to the callee as first argument, all
425  // argument attribute indices have to be incremented by one.
426  SmallVector<AttributeSet, 8> ArgAttributes;
427  const AttributeList &InvokeAL = CI->getAttributes();
428 
429  // No attributes for the callee pointer.
430  ArgAttributes.push_back(AttributeSet());
431  // Copy the argument attributes from the original
432  for (unsigned i = 0, e = CI->getNumArgOperands(); i < e; ++i)
433  ArgAttributes.push_back(InvokeAL.getParamAttributes(i));
434 
435  // Reconstruct the AttributesList based on the vector we constructed.
436  AttributeList NewCallAL =
437  AttributeList::get(C, InvokeAL.getFnAttributes(),
438  InvokeAL.getRetAttributes(), ArgAttributes);
439  NewCall->setAttributes(NewCallAL);
440 
441  CI->replaceAllUsesWith(NewCall);
442 
443  // Post-invoke
444  // %__THREW__.val = __THREW__; __THREW__ = 0;
445  Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
446  IRB.CreateStore(IRB.getInt32(0), ThrewGV);
447  return Threw;
448 }
449 
450 // Get matching invoke wrapper based on callee signature
451 template <typename CallOrInvoke>
452 Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(CallOrInvoke *CI) {
453  Module *M = CI->getModule();
455  Value *Callee = CI->getCalledValue();
456  FunctionType *CalleeFTy;
457  if (auto *F = dyn_cast<Function>(Callee))
458  CalleeFTy = F->getFunctionType();
459  else {
460  auto *CalleeTy = cast<PointerType>(Callee->getType())->getElementType();
461  CalleeFTy = dyn_cast<FunctionType>(CalleeTy);
462  }
463 
464  std::string Sig = getSignature(CalleeFTy);
465  if (InvokeWrappers.find(Sig) != InvokeWrappers.end())
466  return InvokeWrappers[Sig];
467 
468  // Put the pointer to the callee as first argument
469  ArgTys.push_back(PointerType::getUnqual(CalleeFTy));
470  // Add argument types
471  ArgTys.append(CalleeFTy->param_begin(), CalleeFTy->param_end());
472 
473  FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys,
474  CalleeFTy->isVarArg());
476  InvokePrefix + Sig, M);
477  InvokeWrappers[Sig] = F;
478  return F;
479 }
480 
481 bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M,
482  const Value *Callee) const {
483  if (auto *CalleeF = dyn_cast<Function>(Callee))
484  if (CalleeF->isIntrinsic())
485  return false;
486 
487  // The reason we include malloc/free here is to exclude the malloc/free
488  // calls generated in setjmp prep / cleanup routines.
489  Function *SetjmpF = M.getFunction("setjmp");
490  Function *MallocF = M.getFunction("malloc");
491  Function *FreeF = M.getFunction("free");
492  if (Callee == SetjmpF || Callee == MallocF || Callee == FreeF)
493  return false;
494 
495  // There are functions in JS glue code
496  if (Callee == ResumeF || Callee == EHTypeIDF || Callee == SaveSetjmpF ||
497  Callee == TestSetjmpF)
498  return false;
499 
500  // __cxa_find_matching_catch_N functions cannot longjmp
501  if (Callee->getName().startswith(FindMatchingCatchPrefix))
502  return false;
503 
504  // Exception-catching related functions
505  Function *BeginCatchF = M.getFunction("__cxa_begin_catch");
506  Function *EndCatchF = M.getFunction("__cxa_end_catch");
507  Function *AllocExceptionF = M.getFunction("__cxa_allocate_exception");
508  Function *ThrowF = M.getFunction("__cxa_throw");
509  Function *TerminateF = M.getFunction("__clang_call_terminate");
510  if (Callee == BeginCatchF || Callee == EndCatchF ||
511  Callee == AllocExceptionF || Callee == ThrowF || Callee == TerminateF)
512  return false;
513 
514  // Otherwise we don't know
515  return true;
516 }
517 
518 // Generate testSetjmp function call seqence with preamble and postamble.
519 // The code this generates is equivalent to the following JavaScript code:
520 // if (%__THREW__.val != 0 & threwValue != 0) {
521 // %label = _testSetjmp(mem[%__THREW__.val], setjmpTable, setjmpTableSize);
522 // if (%label == 0)
523 // emscripten_longjmp(%__THREW__.val, threwValue);
524 // __tempRet0 = threwValue;
525 // } else {
526 // %label = -1;
527 // }
528 // %longjmp_result = __tempRet0;
529 //
530 // As output parameters. returns %label, %longjmp_result, and the BB the last
531 // instruction (%longjmp_result = ...) is in.
532 void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
533  BasicBlock *BB, Instruction *InsertPt, Value *Threw, Value *SetjmpTable,
534  Value *SetjmpTableSize, Value *&Label, Value *&LongjmpResult,
535  BasicBlock *&EndBB) {
536  Function *F = BB->getParent();
537  LLVMContext &C = BB->getModule()->getContext();
538  IRBuilder<> IRB(C);
539  IRB.SetInsertPoint(InsertPt);
540 
541  // if (%__THREW__.val != 0 & threwValue != 0)
542  IRB.SetInsertPoint(BB);
543  BasicBlock *ThenBB1 = BasicBlock::Create(C, "if.then1", F);
544  BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F);
545  BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F);
546  Value *ThrewCmp = IRB.CreateICmpNE(Threw, IRB.getInt32(0));
547  Value *ThrewValue =
548  IRB.CreateLoad(ThrewValueGV, ThrewValueGV->getName() + ".val");
549  Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0));
550  Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, "cmp1");
551  IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1);
552 
553  // %label = _testSetjmp(mem[%__THREW__.val], _setjmpTable, _setjmpTableSize);
554  // if (%label == 0)
555  IRB.SetInsertPoint(ThenBB1);
556  BasicBlock *ThenBB2 = BasicBlock::Create(C, "if.then2", F);
557  BasicBlock *EndBB2 = BasicBlock::Create(C, "if.end2", F);
558  Value *ThrewInt = IRB.CreateIntToPtr(Threw, Type::getInt32PtrTy(C),
559  Threw->getName() + ".i32p");
560  Value *LoadedThrew =
561  IRB.CreateLoad(ThrewInt, ThrewInt->getName() + ".loaded");
562  Value *ThenLabel = IRB.CreateCall(
563  TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize}, "label");
564  Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0));
565  IRB.CreateCondBr(Cmp2, ThenBB2, EndBB2);
566 
567  // emscripten_longjmp(%__THREW__.val, threwValue);
568  IRB.SetInsertPoint(ThenBB2);
569  IRB.CreateCall(EmLongjmpF, {Threw, ThrewValue});
570  IRB.CreateUnreachable();
571 
572  // __tempRet0 = threwValue;
573  IRB.SetInsertPoint(EndBB2);
574  IRB.CreateStore(ThrewValue, TempRet0GV);
575  IRB.CreateBr(EndBB1);
576 
577  IRB.SetInsertPoint(ElseBB1);
578  IRB.CreateBr(EndBB1);
579 
580  // longjmp_result = __tempRet0;
581  IRB.SetInsertPoint(EndBB1);
582  PHINode *LabelPHI = IRB.CreatePHI(IRB.getInt32Ty(), 2, "label");
583  LabelPHI->addIncoming(ThenLabel, EndBB2);
584 
585  LabelPHI->addIncoming(IRB.getInt32(-1), ElseBB1);
586 
587  // Output parameter assignment
588  Label = LabelPHI;
589  EndBB = EndBB1;
590  LongjmpResult = IRB.CreateLoad(TempRet0GV, "longjmp_result");
591 }
592 
593 // Create setThrew function
594 // function setThrew(threw, value) {
595 // if (__THREW__ == 0) {
596 // __THREW__ = threw;
597 // __threwValue = value;
598 // }
599 // }
600 void WebAssemblyLowerEmscriptenEHSjLj::createSetThrewFunction(Module &M) {
601  LLVMContext &C = M.getContext();
602  IRBuilder<> IRB(C);
603 
604  if (M.getNamedGlobal("setThrew"))
605  report_fatal_error("setThrew already exists");
606 
607  Type *Params[] = {IRB.getInt32Ty(), IRB.getInt32Ty()};
608  FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false);
609  Function *F =
610  Function::Create(FTy, GlobalValue::WeakODRLinkage, "setThrew", &M);
611  Argument *Arg1 = &*(F->arg_begin());
612  Argument *Arg2 = &*std::next(F->arg_begin());
613  Arg1->setName("threw");
614  Arg2->setName("value");
615  BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
616  BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", F);
617  BasicBlock *EndBB = BasicBlock::Create(C, "if.end", F);
618 
619  IRB.SetInsertPoint(EntryBB);
620  Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
621  Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(0), "cmp");
622  IRB.CreateCondBr(Cmp, ThenBB, EndBB);
623 
624  IRB.SetInsertPoint(ThenBB);
625  IRB.CreateStore(Arg1, ThrewGV);
626  IRB.CreateStore(Arg2, ThrewValueGV);
627  IRB.CreateBr(EndBB);
628 
629  IRB.SetInsertPoint(EndBB);
630  IRB.CreateRetVoid();
631 }
632 
633 // Create setTempRet0 function
634 // function setTempRet0(value) {
635 // __tempRet0 = value;
636 // }
637 void WebAssemblyLowerEmscriptenEHSjLj::createSetTempRet0Function(Module &M) {
638  LLVMContext &C = M.getContext();
639  IRBuilder<> IRB(C);
640 
641  if (M.getNamedGlobal("setTempRet0"))
642  report_fatal_error("setTempRet0 already exists");
643  Type *Params[] = {IRB.getInt32Ty()};
644  FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false);
645  Function *F =
646  Function::Create(FTy, GlobalValue::WeakODRLinkage, "setTempRet0", &M);
647  F->arg_begin()->setName("value");
648  BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
649  IRB.SetInsertPoint(EntryBB);
650  IRB.CreateStore(&*F->arg_begin(), TempRet0GV);
651  IRB.CreateRetVoid();
652 }
653 
654 void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) {
655  DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
656  DT.recalculate(F); // CFG has been changed
657  SSAUpdater SSA;
658  for (BasicBlock &BB : F) {
659  for (Instruction &I : BB) {
660  for (auto UI = I.use_begin(), UE = I.use_end(); UI != UE;) {
661  Use &U = *UI;
662  ++UI;
663  SSA.Initialize(I.getType(), I.getName());
664  SSA.AddAvailableValue(&BB, &I);
665  Instruction *User = cast<Instruction>(U.getUser());
666  if (User->getParent() == &BB)
667  continue;
668 
669  if (PHINode *UserPN = dyn_cast<PHINode>(User))
670  if (UserPN->getIncomingBlock(U) == &BB)
671  continue;
672 
673  if (DT.dominates(&I, User))
674  continue;
676  }
677  }
678  }
679 }
680 
681 bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
682  LLVMContext &C = M.getContext();
683  IRBuilder<> IRB(C);
684 
685  Function *SetjmpF = M.getFunction("setjmp");
686  Function *LongjmpF = M.getFunction("longjmp");
687  bool SetjmpUsed = SetjmpF && !SetjmpF->use_empty();
688  bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty();
689  bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);
690 
691  // Create global variables __THREW__, threwValue, and __tempRet0, which are
692  // used in common for both exception handling and setjmp/longjmp handling
693  ThrewGV = createGlobalVariableI32(M, IRB, "__THREW__");
694  ThrewValueGV = createGlobalVariableI32(M, IRB, "__threwValue");
695  TempRet0GV = createGlobalVariableI32(M, IRB, "__tempRet0");
696 
697  bool Changed = false;
698 
699  // Exception handling
700  if (EnableEH) {
701  // Register __resumeException function
702  FunctionType *ResumeFTy =
703  FunctionType::get(IRB.getVoidTy(), IRB.getInt8PtrTy(), false);
704  ResumeF = Function::Create(ResumeFTy, GlobalValue::ExternalLinkage,
705  ResumeFName, &M);
706 
707  // Register llvm_eh_typeid_for function
708  FunctionType *EHTypeIDTy =
709  FunctionType::get(IRB.getInt32Ty(), IRB.getInt8PtrTy(), false);
710  EHTypeIDF = Function::Create(EHTypeIDTy, GlobalValue::ExternalLinkage,
711  EHTypeIDFName, &M);
712 
713  for (Function &F : M) {
714  if (F.isDeclaration())
715  continue;
716  Changed |= runEHOnFunction(F);
717  }
718  }
719 
720  // Setjmp/longjmp handling
721  if (DoSjLj) {
722  Changed = true; // We have setjmp or longjmp somewhere
723 
724  // Register saveSetjmp function
725  FunctionType *SetjmpFTy = SetjmpF->getFunctionType();
726  SmallVector<Type *, 4> Params = {SetjmpFTy->getParamType(0),
728  IRB.getInt32Ty()};
729  FunctionType *FTy =
730  FunctionType::get(Type::getInt32PtrTy(C), Params, false);
732  SaveSetjmpFName, &M);
733 
734  // Register testSetjmp function
735  Params = {IRB.getInt32Ty(), Type::getInt32PtrTy(C), IRB.getInt32Ty()};
736  FTy = FunctionType::get(IRB.getInt32Ty(), Params, false);
738  TestSetjmpFName, &M);
739 
740  if (LongjmpF) {
741  // Replace all uses of longjmp with emscripten_longjmp_jmpbuf, which is
742  // defined in JS code
743  EmLongjmpJmpbufF = Function::Create(LongjmpF->getFunctionType(),
745  EmLongjmpJmpbufFName, &M);
746 
747  LongjmpF->replaceAllUsesWith(EmLongjmpJmpbufF);
748  }
749  FTy = FunctionType::get(IRB.getVoidTy(),
750  {IRB.getInt32Ty(), IRB.getInt32Ty()}, false);
751  EmLongjmpF =
752  Function::Create(FTy, GlobalValue::ExternalLinkage, EmLongjmpFName, &M);
753 
754  // Only traverse functions that uses setjmp in order not to insert
755  // unnecessary prep / cleanup code in every function
756  SmallPtrSet<Function *, 8> SetjmpUsers;
757  for (User *U : SetjmpF->users()) {
758  auto *UI = cast<Instruction>(U);
759  SetjmpUsers.insert(UI->getFunction());
760  }
761  for (Function *F : SetjmpUsers)
762  runSjLjOnFunction(*F);
763  }
764 
765  if (!Changed) {
766  // Delete unused global variables and functions
767  ThrewGV->eraseFromParent();
768  ThrewValueGV->eraseFromParent();
769  TempRet0GV->eraseFromParent();
770  if (ResumeF)
771  ResumeF->eraseFromParent();
772  if (EHTypeIDF)
773  EHTypeIDF->eraseFromParent();
774  if (EmLongjmpF)
775  EmLongjmpF->eraseFromParent();
776  if (SaveSetjmpF)
777  SaveSetjmpF->eraseFromParent();
778  if (TestSetjmpF)
779  TestSetjmpF->eraseFromParent();
780  return false;
781  }
782 
783  // If we have made any changes while doing exception handling or
784  // setjmp/longjmp handling, we have to create these functions for JavaScript
785  // to call.
786  createSetThrewFunction(M);
787  createSetTempRet0Function(M);
788 
789  return true;
790 }
791 
792 bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) {
793  Module &M = *F.getParent();
794  LLVMContext &C = F.getContext();
795  IRBuilder<> IRB(C);
796  bool Changed = false;
799  bool AllowExceptions =
800  areAllExceptionsAllowed() || EHWhitelistSet.count(F.getName());
801 
802  for (BasicBlock &BB : F) {
803  auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
804  if (!II)
805  continue;
806  Changed = true;
807  LandingPads.insert(II->getLandingPadInst());
808  IRB.SetInsertPoint(II);
809 
810  bool NeedInvoke = AllowExceptions && canThrow(II->getCalledValue());
811  if (NeedInvoke) {
812  // Wrap invoke with invoke wrapper and generate preamble/postamble
813  Value *Threw = wrapInvoke(II);
814  ToErase.push_back(II);
815 
816  // Insert a branch based on __THREW__ variable
817  Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(1), "cmp");
818  IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest());
819 
820  } else {
821  // This can't throw, and we don't need this invoke, just replace it with a
822  // call+branch
823  SmallVector<Value *, 16> Args(II->arg_begin(), II->arg_end());
824  CallInst *NewCall = IRB.CreateCall(II->getCalledValue(), Args);
825  NewCall->takeName(II);
826  NewCall->setCallingConv(II->getCallingConv());
827  NewCall->setDebugLoc(II->getDebugLoc());
828  NewCall->setAttributes(II->getAttributes());
829  II->replaceAllUsesWith(NewCall);
830  ToErase.push_back(II);
831 
832  IRB.CreateBr(II->getNormalDest());
833 
834  // Remove any PHI node entries from the exception destination
835  II->getUnwindDest()->removePredecessor(&BB);
836  }
837  }
838 
839  // Process resume instructions
840  for (BasicBlock &BB : F) {
841  // Scan the body of the basic block for resumes
842  for (Instruction &I : BB) {
843  auto *RI = dyn_cast<ResumeInst>(&I);
844  if (!RI)
845  continue;
846 
847  // Split the input into legal values
848  Value *Input = RI->getValue();
849  IRB.SetInsertPoint(RI);
850  Value *Low = IRB.CreateExtractValue(Input, 0, "low");
851  // Create a call to __resumeException function
852  IRB.CreateCall(ResumeF, {Low});
853  // Add a terminator to the block
854  IRB.CreateUnreachable();
855  ToErase.push_back(RI);
856  }
857  }
858 
859  // Process llvm.eh.typeid.for intrinsics
860  for (BasicBlock &BB : F) {
861  for (Instruction &I : BB) {
862  auto *CI = dyn_cast<CallInst>(&I);
863  if (!CI)
864  continue;
865  const Function *Callee = CI->getCalledFunction();
866  if (!Callee)
867  continue;
868  if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
869  continue;
870 
871  IRB.SetInsertPoint(CI);
872  CallInst *NewCI =
873  IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0), "typeid");
874  CI->replaceAllUsesWith(NewCI);
875  ToErase.push_back(CI);
876  }
877  }
878 
879  // Look for orphan landingpads, can occur in blocks with no predecessors
880  for (BasicBlock &BB : F) {
881  Instruction *I = BB.getFirstNonPHI();
882  if (auto *LPI = dyn_cast<LandingPadInst>(I))
883  LandingPads.insert(LPI);
884  }
885 
886  // Handle all the landingpad for this function together, as multiple invokes
887  // may share a single lp
888  for (LandingPadInst *LPI : LandingPads) {
889  IRB.SetInsertPoint(LPI);
890  SmallVector<Value *, 16> FMCArgs;
891  for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) {
892  Constant *Clause = LPI->getClause(i);
893  // As a temporary workaround for the lack of aggregate varargs support
894  // in the interface between JS and wasm, break out filter operands into
895  // their component elements.
896  if (LPI->isFilter(i)) {
897  auto *ATy = cast<ArrayType>(Clause->getType());
898  for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
899  Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter");
900  FMCArgs.push_back(EV);
901  }
902  } else
903  FMCArgs.push_back(Clause);
904  }
905 
906  // Create a call to __cxa_find_matching_catch_N function
907  Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
908  CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc");
909  Value *Undef = UndefValue::get(LPI->getType());
910  Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0");
911  Value *TempRet0 =
912  IRB.CreateLoad(TempRet0GV, TempRet0GV->getName() + ".val");
913  Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
914 
915  LPI->replaceAllUsesWith(Pair1);
916  ToErase.push_back(LPI);
917  }
918 
919  // Erase everything we no longer need in this function
920  for (Instruction *I : ToErase)
921  I->eraseFromParent();
922 
923  return Changed;
924 }
925 
926 bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
927  Module &M = *F.getParent();
928  LLVMContext &C = F.getContext();
929  IRBuilder<> IRB(C);
931  // Vector of %setjmpTable values
932  std::vector<Instruction *> SetjmpTableInsts;
933  // Vector of %setjmpTableSize values
934  std::vector<Instruction *> SetjmpTableSizeInsts;
935 
936  // Setjmp preparation
937 
938  // This instruction effectively means %setjmpTableSize = 4.
939  // We create this as an instruction intentionally, and we don't want to fold
940  // this instruction to a constant 4, because this value will be used in
941  // SSAUpdater.AddAvailableValue(...) later.
942  BasicBlock &EntryBB = F.getEntryBlock();
943  BinaryOperator *SetjmpTableSize = BinaryOperator::Create(
944  Instruction::Add, IRB.getInt32(4), IRB.getInt32(0), "setjmpTableSize",
945  &*EntryBB.getFirstInsertionPt());
946  // setjmpTable = (int *) malloc(40);
947  Instruction *SetjmpTable = CallInst::CreateMalloc(
948  SetjmpTableSize, IRB.getInt32Ty(), IRB.getInt32Ty(), IRB.getInt32(40),
949  nullptr, nullptr, "setjmpTable");
950  // setjmpTable[0] = 0;
951  IRB.SetInsertPoint(SetjmpTableSize);
952  IRB.CreateStore(IRB.getInt32(0), SetjmpTable);
953  SetjmpTableInsts.push_back(SetjmpTable);
954  SetjmpTableSizeInsts.push_back(SetjmpTableSize);
955 
956  // Setjmp transformation
957  std::vector<PHINode *> SetjmpRetPHIs;
958  Function *SetjmpF = M.getFunction("setjmp");
959  for (User *U : SetjmpF->users()) {
960  auto *CI = dyn_cast<CallInst>(U);
961  if (!CI)
962  report_fatal_error("Does not support indirect calls to setjmp");
963 
964  BasicBlock *BB = CI->getParent();
965  if (BB->getParent() != &F) // in other function
966  continue;
967 
968  // The tail is everything right after the call, and will be reached once
969  // when setjmp is called, and later when longjmp returns to the setjmp
970  BasicBlock *Tail = SplitBlock(BB, CI->getNextNode());
971  // Add a phi to the tail, which will be the output of setjmp, which
972  // indicates if this is the first call or a longjmp back. The phi directly
973  // uses the right value based on where we arrive from
974  IRB.SetInsertPoint(Tail->getFirstNonPHI());
975  PHINode *SetjmpRet = IRB.CreatePHI(IRB.getInt32Ty(), 2, "setjmp.ret");
976 
977  // setjmp initial call returns 0
978  SetjmpRet->addIncoming(IRB.getInt32(0), BB);
979  // The proper output is now this, not the setjmp call itself
980  CI->replaceAllUsesWith(SetjmpRet);
981  // longjmp returns to the setjmp will add themselves to this phi
982  SetjmpRetPHIs.push_back(SetjmpRet);
983 
984  // Fix call target
985  // Our index in the function is our place in the array + 1 to avoid index
986  // 0, because index 0 means the longjmp is not ours to handle.
987  IRB.SetInsertPoint(CI);
988  Value *Args[] = {CI->getArgOperand(0), IRB.getInt32(SetjmpRetPHIs.size()),
989  SetjmpTable, SetjmpTableSize};
990  Instruction *NewSetjmpTable =
991  IRB.CreateCall(SaveSetjmpF, Args, "setjmpTable");
992  Instruction *NewSetjmpTableSize =
993  IRB.CreateLoad(TempRet0GV, "setjmpTableSize");
994  SetjmpTableInsts.push_back(NewSetjmpTable);
995  SetjmpTableSizeInsts.push_back(NewSetjmpTableSize);
996  ToErase.push_back(CI);
997  }
998 
999  // Update each call that can longjmp so it can return to a setjmp where
1000  // relevant.
1001 
1002  // Because we are creating new BBs while processing and don't want to make
1003  // all these newly created BBs candidates again for longjmp processing, we
1004  // first make the vector of candidate BBs.
1005  std::vector<BasicBlock *> BBs;
1006  for (BasicBlock &BB : F)
1007  BBs.push_back(&BB);
1008 
1009  // BBs.size() will change within the loop, so we query it every time
1010  for (unsigned i = 0; i < BBs.size(); i++) {
1011  BasicBlock *BB = BBs[i];
1012  for (Instruction &I : *BB) {
1013  assert(!isa<InvokeInst>(&I));
1014  auto *CI = dyn_cast<CallInst>(&I);
1015  if (!CI)
1016  continue;
1017 
1018  const Value *Callee = CI->getCalledValue();
1019  if (!canLongjmp(M, Callee))
1020  continue;
1021 
1022  Value *Threw = nullptr;
1023  BasicBlock *Tail;
1024  if (Callee->getName().startswith(InvokePrefix)) {
1025  // If invoke wrapper has already been generated for this call in
1026  // previous EH phase, search for the load instruction
1027  // %__THREW__.val = __THREW__;
1028  // in postamble after the invoke wrapper call
1029  LoadInst *ThrewLI = nullptr;
1030  StoreInst *ThrewResetSI = nullptr;
1031  for (auto I = std::next(BasicBlock::iterator(CI)), IE = BB->end();
1032  I != IE; ++I) {
1033  if (auto *LI = dyn_cast<LoadInst>(I))
1034  if (auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand()))
1035  if (GV == ThrewGV) {
1036  Threw = ThrewLI = LI;
1037  break;
1038  }
1039  }
1040  // Search for the store instruction after the load above
1041  // __THREW__ = 0;
1042  for (auto I = std::next(BasicBlock::iterator(ThrewLI)), IE = BB->end();
1043  I != IE; ++I) {
1044  if (auto *SI = dyn_cast<StoreInst>(I))
1045  if (auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand()))
1046  if (GV == ThrewGV && SI->getValueOperand() == IRB.getInt32(0)) {
1047  ThrewResetSI = SI;
1048  break;
1049  }
1050  }
1051  assert(Threw && ThrewLI && "Cannot find __THREW__ load after invoke");
1052  assert(ThrewResetSI && "Cannot find __THREW__ store after invoke");
1053  Tail = SplitBlock(BB, ThrewResetSI->getNextNode());
1054 
1055  } else {
1056  // Wrap call with invoke wrapper and generate preamble/postamble
1057  Threw = wrapInvoke(CI);
1058  ToErase.push_back(CI);
1059  Tail = SplitBlock(BB, CI->getNextNode());
1060  }
1061 
1062  // We need to replace the terminator in Tail - SplitBlock makes BB go
1063  // straight to Tail, we need to check if a longjmp occurred, and go to the
1064  // right setjmp-tail if so
1065  ToErase.push_back(BB->getTerminator());
1066 
1067  // Generate a function call to testSetjmp function and preamble/postamble
1068  // code to figure out (1) whether longjmp occurred (2) if longjmp
1069  // occurred, which setjmp it corresponds to
1070  Value *Label = nullptr;
1071  Value *LongjmpResult = nullptr;
1072  BasicBlock *EndBB = nullptr;
1073  wrapTestSetjmp(BB, CI, Threw, SetjmpTable, SetjmpTableSize, Label,
1074  LongjmpResult, EndBB);
1075  assert(Label && LongjmpResult && EndBB);
1076 
1077  // Create switch instruction
1078  IRB.SetInsertPoint(EndBB);
1079  SwitchInst *SI = IRB.CreateSwitch(Label, Tail, SetjmpRetPHIs.size());
1080  // -1 means no longjmp happened, continue normally (will hit the default
1081  // switch case). 0 means a longjmp that is not ours to handle, needs a
1082  // rethrow. Otherwise the index is the same as the index in P+1 (to avoid
1083  // 0).
1084  for (unsigned i = 0; i < SetjmpRetPHIs.size(); i++) {
1085  SI->addCase(IRB.getInt32(i + 1), SetjmpRetPHIs[i]->getParent());
1086  SetjmpRetPHIs[i]->addIncoming(LongjmpResult, EndBB);
1087  }
1088 
1089  // We are splitting the block here, and must continue to find other calls
1090  // in the block - which is now split. so continue to traverse in the Tail
1091  BBs.push_back(Tail);
1092  }
1093  }
1094 
1095  // Erase everything we no longer need in this function
1096  for (Instruction *I : ToErase)
1097  I->eraseFromParent();
1098 
1099  // Free setjmpTable buffer before each return instruction
1100  for (BasicBlock &BB : F) {
1101  TerminatorInst *TI = BB.getTerminator();
1102  if (isa<ReturnInst>(TI))
1103  CallInst::CreateFree(SetjmpTable, TI);
1104  }
1105 
1106  // Every call to saveSetjmp can change setjmpTable and setjmpTableSize
1107  // (when buffer reallocation occurs)
1108  // entry:
1109  // setjmpTableSize = 4;
1110  // setjmpTable = (int *) malloc(40);
1111  // setjmpTable[0] = 0;
1112  // ...
1113  // somebb:
1114  // setjmpTable = saveSetjmp(buf, label, setjmpTable, setjmpTableSize);
1115  // setjmpTableSize = __tempRet0;
1116  // So we need to make sure the SSA for these variables is valid so that every
1117  // saveSetjmp and testSetjmp calls have the correct arguments.
1118  SSAUpdater SetjmpTableSSA;
1119  SSAUpdater SetjmpTableSizeSSA;
1120  SetjmpTableSSA.Initialize(Type::getInt32PtrTy(C), "setjmpTable");
1121  SetjmpTableSizeSSA.Initialize(Type::getInt32Ty(C), "setjmpTableSize");
1122  for (Instruction *I : SetjmpTableInsts)
1123  SetjmpTableSSA.AddAvailableValue(I->getParent(), I);
1124  for (Instruction *I : SetjmpTableSizeInsts)
1125  SetjmpTableSizeSSA.AddAvailableValue(I->getParent(), I);
1126 
1127  for (auto UI = SetjmpTable->use_begin(), UE = SetjmpTable->use_end();
1128  UI != UE;) {
1129  // Grab the use before incrementing the iterator.
1130  Use &U = *UI;
1131  // Increment the iterator before removing the use from the list.
1132  ++UI;
1133  if (Instruction *I = dyn_cast<Instruction>(U.getUser()))
1134  if (I->getParent() != &EntryBB)
1135  SetjmpTableSSA.RewriteUse(U);
1136  }
1137  for (auto UI = SetjmpTableSize->use_begin(), UE = SetjmpTableSize->use_end();
1138  UI != UE;) {
1139  Use &U = *UI;
1140  ++UI;
1141  if (Instruction *I = dyn_cast<Instruction>(U.getUser()))
1142  if (I->getParent() != &EntryBB)
1143  SetjmpTableSizeSSA.RewriteUse(U);
1144  }
1145 
1146  // Finally, our modifications to the cfg can break dominance of SSA variables.
1147  // For example, in this code,
1148  // if (x()) { .. setjmp() .. }
1149  // if (y()) { .. longjmp() .. }
1150  // We must split the longjmp block, and it can jump into the block splitted
1151  // from setjmp one. But that means that when we split the setjmp block, it's
1152  // first part no longer dominates its second part - there is a theoretically
1153  // possible control flow path where x() is false, then y() is true and we
1154  // reach the second part of the setjmp block, without ever reaching the first
1155  // part. So, we rebuild SSA form here.
1156  rebuildSSA(F);
1157  return true;
1158 }
uint64_t CallInst * C
use_iterator use_end()
Definition: Value.h:347
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional &#39;br Cond, TrueDest, FalseDest&#39; instruction.
Definition: IRBuilder.h:842
Helper class for SSA formation on a set of values defined in multiple blocks.
Definition: SSAUpdater.h:39
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
ModulePass * createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH, bool DoSjLj)
This class represents an incoming formal argument to a Function.
Definition: Argument.h:30
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1740
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:289
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type &#39;Ty&#39;.
Definition: SSAUpdater.cpp:54
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:64
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:54
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value...
Definition: SSAUpdater.cpp:67
void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
This class represents a function call, abstracting a target machine&#39;s calling convention.
static PointerType * getInt32PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:228
const GlobalVariable * getNamedGlobal(StringRef Name) const
Return the global variable in the module with the specified name, of arbitrary type.
Definition: Module.h:396
iterator find(StringRef Key)
Definition: StringMap.h:333
Externally visible function.
Definition: GlobalValue.h:49
F(f)
param_iterator param_end() const
Definition: DerivedTypes.h:129
An instruction for reading from memory.
Definition: Instructions.h:168
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)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:347
AnalysisUsage & addRequired()
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
Definition: BasicBlock.cpp:134
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:243
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:731
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:295
Type * getVoidTy()
Fetch the type representing void.
Definition: IRBuilder.h:380
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1321
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1624
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:267
User * getUser() const LLVM_READONLY
Returns the User that contains this Use.
Definition: Use.cpp:41
Class to represent function types.
Definition: DerivedTypes.h:103
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
AttributeSet getParamAttributes(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
bool isVarArg() const
Definition: DerivedTypes.h:123
Memory SSA
Definition: MemorySSA.cpp:66
An instruction for storing to memory.
Definition: Instructions.h:310
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:439
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:301
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Definition: Dominators.h:145
amdgpu Simplify well known AMD library false Value * Callee
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Definition: IRBuilder.h:127
Class to represent pointers.
Definition: DerivedTypes.h:467
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
const BasicBlock & getEntryBlock() const
Definition: Function.h:640
LoadInst * CreateLoad(Value *Ptr, const char *Name)
Provided to resolve &#39;CreateLoad(Ptr, "...")&#39; correctly, instead of converting the string to &#39;bool&#39; fo...
Definition: IRBuilder.h:1305
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:136
The landingpad instruction holds all of the information necessary to generate correct exception handl...
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Definition: BasicBlock.cpp:189
Subclasses of this class are all able to terminate a basic block.
Definition: InstrTypes.h:55
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
Definition: BasicBlock.cpp:218
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:304
LLVM Basic Block Representation.
Definition: BasicBlock.h:59
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
Definition: SSAUpdater.cpp:202
UnreachableInst * CreateUnreachable()
Definition: IRBuilder.h:926
This is an important base class in LLVM.
Definition: Constant.h:42
Resume the propagation of an exception.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:371
size_t size() const
Definition: BasicBlock.h:274
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Globals.cpp:359
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:130
param_iterator param_begin() const
Definition: DerivedTypes.h:128
Represent the analysis usage information of a pass.
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:297
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:101
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1736
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:382
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1082
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:194
static UndefValue * get(Type *T)
Static factory methods - Return an &#39;undef&#39; object of the specified type.
Definition: Constants.cpp:1392
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:1963
size_t size() const
Definition: SmallVector.h:53
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Definition: IRBuilder.h:385
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:220
std::string & str()
Flushes the stream contents to the target string and returns the string&#39;s reference.
Definition: raw_ostream.h:499
void setCallingConv(CallingConv::ID CC)
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition: IRBuilder.h:1866
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Definition: SmallPtrSet.h:418
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
Definition: DerivedTypes.h:482
static GlobalVariable * createGlobalVariableI32(Module &M, IRBuilder<> &IRB, const char *Name)
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Definition: Dominators.cpp:249
Type * getReturnType() const
Definition: DerivedTypes.h:124
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition: IRBuilder.h:307
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:194
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Definition: Module.cpp:175
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:164
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Definition: Instruction.cpp:56
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()
Definition: Value.h:400
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:394
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:
SwitchInst * CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases=10, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a switch instruction with the specified value, default dest, and with a hint for the number of...
Definition: IRBuilder.h:865
use_iterator use_begin()
Definition: Value.h:339
ReturnInst * CreateRetVoid()
Create a &#39;ret void&#39; instruction.
Definition: IRBuilder.h:812
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:176
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:224
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:108
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:225
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Function.cpp:215
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:141
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1112
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:206
Multiway switch.
INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE, "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp", false, false) ModulePass *llvm
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:483
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:566
LLVM Value Representation.
Definition: Value.h:73
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)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional &#39;br label X&#39; instruction.
Definition: IRBuilder.h:836
AttributeSet getFnAttributes() const
The function attributes are returned.
BasicBlock * SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Split the specified block at the specified instruction - everything before SplitPt stays in Old and e...
Invoke instruction.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:260
const TerminatorInst * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.cpp:138
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:1971
void RewriteUse(Use &U)
Rewrite a use of the symbolic value.
Definition: SSAUpdater.cpp:185
static std::string getSignature(FunctionType *FTy)
bool use_empty() const
Definition: Value.h:323
iterator end()
Definition: StringMap.h:318
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute >> Attrs)
Create an AttributeList with the specified parameters in it.
Definition: Attributes.cpp:873
const BasicBlock * getParent() const
Definition: Instruction.h:67
CallInst * CreateCall(Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:1871