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