LLVM  13.0.0git
WebAssemblyLowerEmscriptenEHSjLj.cpp
Go to the documentation of this file.
1 //=== WebAssemblyLowerEmscriptenEHSjLj.cpp - Lower exceptions for Emscripten =//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file lowers exception-related instructions and setjmp/longjmp
11 /// function calls in order to use Emscripten's JavaScript try and catch
12 /// mechanism.
13 ///
14 /// To handle exceptions and setjmp/longjmps, this scheme relies on JavaScript's
15 /// try and catch syntax and relevant exception-related libraries implemented
16 /// in JavaScript glue code that will be produced by Emscripten.
17 ///
18 /// * Exception handling
19 /// This pass lowers invokes and landingpads into library functions in JS glue
20 /// code. Invokes are lowered into function wrappers called invoke wrappers that
21 /// exist in JS side, which wraps the original function call with JS try-catch.
22 /// If an exception occurred, cxa_throw() function in JS side sets some
23 /// variables (see below) so we can check whether an exception occurred from
24 /// wasm code and handle it appropriately.
25 ///
26 /// * Setjmp-longjmp handling
27 /// This pass lowers setjmp to a reasonably-performant approach for emscripten.
28 /// The idea is that each block with a setjmp is broken up into two parts: the
29 /// part containing setjmp and the part right after the setjmp. The latter part
30 /// is either reached from the setjmp, or later from a longjmp. To handle the
31 /// longjmp, all calls that might longjmp are also called using invoke wrappers
32 /// and thus JS / try-catch. JS longjmp() function also sets some variables so
33 /// we can check / whether a longjmp occurred from wasm code. Each block with a
34 /// function call that might longjmp is also split up after the longjmp call.
35 /// After the longjmp call, we check whether a longjmp occurred, and if it did,
36 /// which setjmp it corresponds to, and jump to the right post-setjmp block.
37 /// We assume setjmp-longjmp handling always run after EH handling, which means
38 /// we don't expect any exception-related instructions when SjLj runs.
39 /// FIXME Currently this scheme does not support indirect call of setjmp,
40 /// because of the limitation of the scheme itself. fastcomp does not support it
41 /// either.
42 ///
43 /// In detail, this pass does following things:
44 ///
45 /// 1) Assumes the existence of global variables: __THREW__, __threwValue
46 /// __THREW__ and __threwValue are defined in compiler-rt in Emscripten.
47 /// These variables are used for both exceptions and setjmp/longjmps.
48 /// __THREW__ indicates whether an exception or a longjmp occurred or not. 0
49 /// means nothing occurred, 1 means an exception occurred, and other numbers
50 /// mean a longjmp occurred. In the case of longjmp, __THREW__ variable
51 /// indicates the corresponding setjmp buffer the longjmp corresponds to.
52 ///
53 /// * Exception handling
54 ///
55 /// 2) We assume the existence of setThrew and setTempRet0/getTempRet0 functions
56 /// at link time. setThrew exists in Emscripten's compiler-rt:
57 ///
58 /// void setThrew(uintptr_t threw, int value) {
59 /// if (__THREW__ == 0) {
60 /// __THREW__ = threw;
61 /// __threwValue = value;
62 /// }
63 /// }
64 //
65 /// setTempRet0 is called from __cxa_find_matching_catch() in JS glue code.
66 /// In exception handling, getTempRet0 indicates the type of an exception
67 /// caught, and in setjmp/longjmp, it means the second argument to longjmp
68 /// function.
69 ///
70 /// 3) Lower
71 /// invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad
72 /// into
73 /// __THREW__ = 0;
74 /// call @__invoke_SIG(func, arg1, arg2)
75 /// %__THREW__.val = __THREW__;
76 /// __THREW__ = 0;
77 /// if (%__THREW__.val == 1)
78 /// goto %lpad
79 /// else
80 /// goto %invoke.cont
81 /// SIG is a mangled string generated based on the LLVM IR-level function
82 /// signature. After LLVM IR types are lowered to the target wasm types,
83 /// the names for these wrappers will change based on wasm types as well,
84 /// as in invoke_vi (function takes an int and returns void). The bodies of
85 /// these wrappers will be generated in JS glue code, and inside those
86 /// wrappers we use JS try-catch to generate actual exception effects. It
87 /// also calls the original callee function. An example wrapper in JS code
88 /// would look like this:
89 /// function invoke_vi(index,a1) {
90 /// try {
91 /// Module["dynCall_vi"](index,a1); // This calls original callee
92 /// } catch(e) {
93 /// if (typeof e !== 'number' && e !== 'longjmp') throw e;
94 /// _setThrew(1, 0); // setThrew is called here
95 /// }
96 /// }
97 /// If an exception is thrown, __THREW__ will be set to true in a wrapper,
98 /// so we can jump to the right BB based on this value.
99 ///
100 /// 4) Lower
101 /// %val = landingpad catch c1 catch c2 catch c3 ...
102 /// ... use %val ...
103 /// into
104 /// %fmc = call @__cxa_find_matching_catch_N(c1, c2, c3, ...)
105 /// %val = {%fmc, getTempRet0()}
106 /// ... use %val ...
107 /// Here N is a number calculated based on the number of clauses.
108 /// setTempRet0 is called from __cxa_find_matching_catch() in JS glue code.
109 ///
110 /// 5) Lower
111 /// resume {%a, %b}
112 /// into
113 /// call @__resumeException(%a)
114 /// where __resumeException() is a function in JS glue code.
115 ///
116 /// 6) Lower
117 /// call @llvm.eh.typeid.for(type) (intrinsic)
118 /// into
119 /// call @llvm_eh_typeid_for(type)
120 /// llvm_eh_typeid_for function will be generated in JS glue code.
121 ///
122 /// * Setjmp / Longjmp handling
123 ///
124 /// In case calls to longjmp() exists
125 ///
126 /// 1) Lower
127 /// longjmp(buf, value)
128 /// into
129 /// emscripten_longjmp(buf, value)
130 ///
131 /// In case calls to setjmp() exists
132 ///
133 /// 2) In the function entry that calls setjmp, initialize setjmpTable and
134 /// sejmpTableSize as follows:
135 /// setjmpTableSize = 4;
136 /// setjmpTable = (int *) malloc(40);
137 /// setjmpTable[0] = 0;
138 /// setjmpTable and setjmpTableSize are used to call saveSetjmp() function in
139 /// Emscripten compiler-rt.
140 ///
141 /// 3) Lower
142 /// setjmp(buf)
143 /// into
144 /// setjmpTable = saveSetjmp(buf, label, setjmpTable, setjmpTableSize);
145 /// setjmpTableSize = getTempRet0();
146 /// For each dynamic setjmp call, setjmpTable stores its ID (a number which
147 /// is incrementally assigned from 0) and its label (a unique number that
148 /// represents each callsite of setjmp). When we need more entries in
149 /// setjmpTable, it is reallocated in saveSetjmp() in Emscripten's
150 /// compiler-rt and it will return the new table address, and assign the new
151 /// table size in setTempRet0(). saveSetjmp also stores the setjmp's ID into
152 /// the buffer buf. A BB with setjmp is split into two after setjmp call in
153 /// order to make the post-setjmp BB the possible destination of longjmp BB.
154 ///
155 ///
156 /// 4) Lower every call that might longjmp into
157 /// __THREW__ = 0;
158 /// call @__invoke_SIG(func, arg1, arg2)
159 /// %__THREW__.val = __THREW__;
160 /// __THREW__ = 0;
161 /// if (%__THREW__.val != 0 & __threwValue != 0) {
162 /// %label = testSetjmp(mem[%__THREW__.val], setjmpTable,
163 /// setjmpTableSize);
164 /// if (%label == 0)
165 /// emscripten_longjmp(%__THREW__.val, __threwValue);
166 /// setTempRet0(__threwValue);
167 /// } else {
168 /// %label = -1;
169 /// }
170 /// longjmp_result = getTempRet0();
171 /// switch label {
172 /// label 1: goto post-setjmp BB 1
173 /// label 2: goto post-setjmp BB 2
174 /// ...
175 /// default: goto splitted next BB
176 /// }
177 /// testSetjmp examines setjmpTable to see if there is a matching setjmp
178 /// call. After calling an invoke wrapper, if a longjmp occurred, __THREW__
179 /// will be the address of matching jmp_buf buffer and __threwValue be the
180 /// second argument to longjmp. mem[__THREW__.val] is a setjmp ID that is
181 /// stored in saveSetjmp. testSetjmp returns a setjmp label, a unique ID to
182 /// each setjmp callsite. Label 0 means this longjmp buffer does not
183 /// correspond to one of the setjmp callsites in this function, so in this
184 /// case we just chain the longjmp to the caller. Label -1 means no longjmp
185 /// occurred. Otherwise we jump to the right post-setjmp BB based on the
186 /// label.
187 ///
188 ///===----------------------------------------------------------------------===//
189 
190 #include "WebAssembly.h"
192 #include "llvm/ADT/StringExtras.h"
195 #include "llvm/IR/Dominators.h"
196 #include "llvm/IR/IRBuilder.h"
200 
201 using namespace llvm;
202 
203 #define DEBUG_TYPE "wasm-lower-em-ehsjlj"
204 
206  EHAllowlist("emscripten-cxx-exceptions-allowed",
207  cl::desc("The list of function names in which Emscripten-style "
208  "exception handling is enabled (see emscripten "
209  "EMSCRIPTEN_CATCHING_ALLOWED options)"),
211 
212 namespace {
213 class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
214  bool EnableEH; // Enable exception handling
215  bool EnableSjLj; // Enable setjmp/longjmp handling
216 
217  GlobalVariable *ThrewGV = nullptr;
218  GlobalVariable *ThrewValueGV = nullptr;
219  Function *GetTempRet0Func = nullptr;
220  Function *SetTempRet0Func = nullptr;
221  Function *ResumeF = nullptr;
222  Function *EHTypeIDF = nullptr;
223  Function *EmLongjmpF = nullptr;
224  Function *SaveSetjmpF = nullptr;
225  Function *TestSetjmpF = nullptr;
226 
227  // __cxa_find_matching_catch_N functions.
228  // Indexed by the number of clauses in an original landingpad instruction.
229  DenseMap<int, Function *> FindMatchingCatches;
230  // Map of <function signature string, invoke_ wrappers>
231  StringMap<Function *> InvokeWrappers;
232  // Set of allowed function names for exception handling
233  std::set<std::string> EHAllowlistSet;
234 
235  StringRef getPassName() const override {
236  return "WebAssembly Lower Emscripten Exceptions";
237  }
238 
239  bool runEHOnFunction(Function &F);
240  bool runSjLjOnFunction(Function &F);
241  Function *getFindMatchingCatch(Module &M, unsigned NumClauses);
242 
243  Value *wrapInvoke(CallBase *CI);
244  void wrapTestSetjmp(BasicBlock *BB, DebugLoc DL, Value *Threw,
245  Value *SetjmpTable, Value *SetjmpTableSize, Value *&Label,
246  Value *&LongjmpResult, BasicBlock *&EndBB);
247  Function *getInvokeWrapper(CallBase *CI);
248 
249  bool areAllExceptionsAllowed() const { return EHAllowlistSet.empty(); }
250  bool canLongjmp(Module &M, const Value *Callee) const;
251  bool isEmAsmCall(Module &M, const Value *Callee) const;
252 
253  void rebuildSSA(Function &F);
254 
255 public:
256  static char ID;
257 
258  WebAssemblyLowerEmscriptenEHSjLj(bool EnableEH = true, bool EnableSjLj = true)
259  : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj) {
260  EHAllowlistSet.insert(EHAllowlist.begin(), EHAllowlist.end());
261  }
262  bool runOnModule(Module &M) override;
263 
264  void getAnalysisUsage(AnalysisUsage &AU) const override {
266  }
267 };
268 } // End anonymous namespace
269 
271 INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE,
272  "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
273  false, false)
274 
276  bool EnableSjLj) {
277  return new WebAssemblyLowerEmscriptenEHSjLj(EnableEH, EnableSjLj);
278 }
279 
280 static bool canThrow(const Value *V) {
281  if (const auto *F = dyn_cast<const Function>(V)) {
282  // Intrinsics cannot throw
283  if (F->isIntrinsic())
284  return false;
285  StringRef Name = F->getName();
286  // leave setjmp and longjmp (mostly) alone, we process them properly later
287  if (Name == "setjmp" || Name == "longjmp")
288  return false;
289  return !F->doesNotThrow();
290  }
291  // not a function, so an indirect call - can throw, we can't tell
292  return true;
293 }
294 
295 // Get a global variable with the given name. If it doesn't exist declare it,
296 // which will generate an import and assume that it will exist at link time.
299  const char *Name) {
300  auto *GV = dyn_cast<GlobalVariable>(M.getOrInsertGlobal(Name, Ty));
301  if (!GV)
302  report_fatal_error(Twine("unable to create global: ") + Name);
303 
304  // If the target supports TLS, make this variable thread-local. We can't just
305  // unconditionally make it thread-local and depend on
306  // CoalesceFeaturesAndStripAtomics to downgrade it, because stripping TLS has
307  // the side effect of disallowing the object from being linked into a
308  // shared-memory module, which we don't want to be responsible for.
309  auto *Subtarget = TM.getSubtargetImpl();
310  auto TLS = Subtarget->hasAtomics() && Subtarget->hasBulkMemory()
313  GV->setThreadLocalMode(TLS);
314  return GV;
315 }
316 
317 // Simple function name mangler.
318 // This function simply takes LLVM's string representation of parameter types
319 // and concatenate them with '_'. There are non-alphanumeric characters but llc
320 // is ok with it, and we need to postprocess these names after the lowering
321 // phase anyway.
322 static std::string getSignature(FunctionType *FTy) {
323  std::string Sig;
324  raw_string_ostream OS(Sig);
325  OS << *FTy->getReturnType();
326  for (Type *ParamTy : FTy->params())
327  OS << "_" << *ParamTy;
328  if (FTy->isVarArg())
329  OS << "_...";
330  Sig = OS.str();
331  erase_if(Sig, isSpace);
332  // When s2wasm parses .s file, a comma means the end of an argument. So a
333  // mangled function name can contain any character but a comma.
334  std::replace(Sig.begin(), Sig.end(), ',', '.');
335  return Sig;
336 }
337 
339  Module *M) {
341  // Tell the linker that this function is expected to be imported from the
342  // 'env' module.
343  if (!F->hasFnAttribute("wasm-import-module")) {
345  B.addAttribute("wasm-import-module", "env");
346  F->addAttributes(llvm::AttributeList::FunctionIndex, B);
347  }
348  if (!F->hasFnAttribute("wasm-import-name")) {
350  B.addAttribute("wasm-import-name", F->getName());
351  F->addAttributes(llvm::AttributeList::FunctionIndex, B);
352  }
353  return F;
354 }
355 
356 // Returns an integer type for the target architecture's address space.
357 // i32 for wasm32 and i64 for wasm64.
359  IRBuilder<> IRB(M->getContext());
360  return IRB.getIntNTy(M->getDataLayout().getPointerSizeInBits());
361 }
362 
363 // Returns an integer pointer type for the target architecture's address space.
364 // i32* for wasm32 and i64* for wasm64.
366  return Type::getIntNPtrTy(M->getContext(),
367  M->getDataLayout().getPointerSizeInBits());
368 }
369 
370 // Returns an integer whose type is the integer type for the target's address
371 // space. Returns (i32 C) for wasm32 and (i64 C) for wasm64, when C is the
372 // integer.
373 static Value *getAddrSizeInt(Module *M, uint64_t C) {
374  IRBuilder<> IRB(M->getContext());
375  return IRB.getIntN(M->getDataLayout().getPointerSizeInBits(), C);
376 }
377 
378 // Returns __cxa_find_matching_catch_N function, where N = NumClauses + 2.
379 // This is because a landingpad instruction contains two more arguments, a
380 // personality function and a cleanup bit, and __cxa_find_matching_catch_N
381 // functions are named after the number of arguments in the original landingpad
382 // instruction.
383 Function *
384 WebAssemblyLowerEmscriptenEHSjLj::getFindMatchingCatch(Module &M,
385  unsigned NumClauses) {
386  if (FindMatchingCatches.count(NumClauses))
387  return FindMatchingCatches[NumClauses];
388  PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext());
389  SmallVector<Type *, 16> Args(NumClauses, Int8PtrTy);
390  FunctionType *FTy = FunctionType::get(Int8PtrTy, Args, false);
392  FTy, "__cxa_find_matching_catch_" + Twine(NumClauses + 2), &M);
393  FindMatchingCatches[NumClauses] = F;
394  return F;
395 }
396 
397 // Generate invoke wrapper seqence with preamble and postamble
398 // Preamble:
399 // __THREW__ = 0;
400 // Postamble:
401 // %__THREW__.val = __THREW__; __THREW__ = 0;
402 // Returns %__THREW__.val, which indicates whether an exception is thrown (or
403 // whether longjmp occurred), for future use.
404 Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) {
405  Module *M = CI->getModule();
406  LLVMContext &C = M->getContext();
407 
408  // If we are calling a function that is noreturn, we must remove that
409  // attribute. The code we insert here does expect it to return, after we
410  // catch the exception.
411  if (CI->doesNotReturn()) {
412  if (auto *F = CI->getCalledFunction())
413  F->removeFnAttr(Attribute::NoReturn);
414  CI->removeAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
415  }
416 
417  IRBuilder<> IRB(C);
418  IRB.SetInsertPoint(CI);
419 
420  // Pre-invoke
421  // __THREW__ = 0;
422  IRB.CreateStore(getAddrSizeInt(M, 0), ThrewGV);
423 
424  // Invoke function wrapper in JavaScript
426  // Put the pointer to the callee as first argument, so it can be called
427  // within the invoke wrapper later
428  Args.push_back(CI->getCalledOperand());
429  Args.append(CI->arg_begin(), CI->arg_end());
430  CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(CI), Args);
431  NewCall->takeName(CI);
433  NewCall->setDebugLoc(CI->getDebugLoc());
434 
435  // Because we added the pointer to the callee as first argument, all
436  // argument attribute indices have to be incremented by one.
437  SmallVector<AttributeSet, 8> ArgAttributes;
438  const AttributeList &InvokeAL = CI->getAttributes();
439 
440  // No attributes for the callee pointer.
441  ArgAttributes.push_back(AttributeSet());
442  // Copy the argument attributes from the original
443  for (unsigned I = 0, E = CI->getNumArgOperands(); I < E; ++I)
444  ArgAttributes.push_back(InvokeAL.getParamAttributes(I));
445 
446  AttrBuilder FnAttrs(InvokeAL.getFnAttributes());
447  if (FnAttrs.contains(Attribute::AllocSize)) {
448  // The allocsize attribute (if any) referes to parameters by index and needs
449  // to be adjusted.
450  unsigned SizeArg;
451  Optional<unsigned> NEltArg;
452  std::tie(SizeArg, NEltArg) = FnAttrs.getAllocSizeArgs();
453  SizeArg += 1;
454  if (NEltArg.hasValue())
455  NEltArg = NEltArg.getValue() + 1;
456  FnAttrs.addAllocSizeAttr(SizeArg, NEltArg);
457  }
458 
459  // Reconstruct the AttributesList based on the vector we constructed.
460  AttributeList NewCallAL =
462  InvokeAL.getRetAttributes(), ArgAttributes);
463  NewCall->setAttributes(NewCallAL);
464 
465  CI->replaceAllUsesWith(NewCall);
466 
467  // Post-invoke
468  // %__THREW__.val = __THREW__; __THREW__ = 0;
469  Value *Threw =
470  IRB.CreateLoad(getAddrIntType(M), ThrewGV, ThrewGV->getName() + ".val");
471  IRB.CreateStore(getAddrSizeInt(M, 0), ThrewGV);
472  return Threw;
473 }
474 
475 // Get matching invoke wrapper based on callee signature
476 Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(CallBase *CI) {
477  Module *M = CI->getModule();
479  FunctionType *CalleeFTy = CI->getFunctionType();
480 
481  std::string Sig = getSignature(CalleeFTy);
482  if (InvokeWrappers.find(Sig) != InvokeWrappers.end())
483  return InvokeWrappers[Sig];
484 
485  // Put the pointer to the callee as first argument
486  ArgTys.push_back(PointerType::getUnqual(CalleeFTy));
487  // Add argument types
488  ArgTys.append(CalleeFTy->param_begin(), CalleeFTy->param_end());
489 
490  FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys,
491  CalleeFTy->isVarArg());
492  Function *F = getEmscriptenFunction(FTy, "__invoke_" + Sig, M);
493  InvokeWrappers[Sig] = F;
494  return F;
495 }
496 
497 bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M,
498  const Value *Callee) const {
499  if (auto *CalleeF = dyn_cast<Function>(Callee))
500  if (CalleeF->isIntrinsic())
501  return false;
502 
503  // Attempting to transform inline assembly will result in something like:
504  // call void @__invoke_void(void ()* asm ...)
505  // which is invalid because inline assembly blocks do not have addresses
506  // and can't be passed by pointer. The result is a crash with illegal IR.
507  if (isa<InlineAsm>(Callee))
508  return false;
509  StringRef CalleeName = Callee->getName();
510 
511  // The reason we include malloc/free here is to exclude the malloc/free
512  // calls generated in setjmp prep / cleanup routines.
513  if (CalleeName == "setjmp" || CalleeName == "malloc" || CalleeName == "free")
514  return false;
515 
516  // There are functions in Emscripten's JS glue code or compiler-rt
517  if (CalleeName == "__resumeException" || CalleeName == "llvm_eh_typeid_for" ||
518  CalleeName == "saveSetjmp" || CalleeName == "testSetjmp" ||
519  CalleeName == "getTempRet0" || CalleeName == "setTempRet0")
520  return false;
521 
522  // __cxa_find_matching_catch_N functions cannot longjmp
523  if (Callee->getName().startswith("__cxa_find_matching_catch_"))
524  return false;
525 
526  // Exception-catching related functions
527  if (CalleeName == "__cxa_begin_catch" || CalleeName == "__cxa_end_catch" ||
528  CalleeName == "__cxa_allocate_exception" || CalleeName == "__cxa_throw" ||
529  CalleeName == "__clang_call_terminate")
530  return false;
531 
532  // Otherwise we don't know
533  return true;
534 }
535 
536 bool WebAssemblyLowerEmscriptenEHSjLj::isEmAsmCall(Module &M,
537  const Value *Callee) const {
538  StringRef CalleeName = Callee->getName();
539  // This is an exhaustive list from Emscripten's <emscripten/em_asm.h>.
540  return CalleeName == "emscripten_asm_const_int" ||
541  CalleeName == "emscripten_asm_const_double" ||
542  CalleeName == "emscripten_asm_const_int_sync_on_main_thread" ||
543  CalleeName == "emscripten_asm_const_double_sync_on_main_thread" ||
544  CalleeName == "emscripten_asm_const_async_on_main_thread";
545 }
546 
547 // Generate testSetjmp function call seqence with preamble and postamble.
548 // The code this generates is equivalent to the following JavaScript code:
549 // if (%__THREW__.val != 0 & threwValue != 0) {
550 // %label = _testSetjmp(mem[%__THREW__.val], setjmpTable, setjmpTableSize);
551 // if (%label == 0)
552 // emscripten_longjmp(%__THREW__.val, threwValue);
553 // setTempRet0(threwValue);
554 // } else {
555 // %label = -1;
556 // }
557 // %longjmp_result = getTempRet0();
558 //
559 // As output parameters. returns %label, %longjmp_result, and the BB the last
560 // instruction (%longjmp_result = ...) is in.
561 void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
562  BasicBlock *BB, DebugLoc DL, Value *Threw, Value *SetjmpTable,
563  Value *SetjmpTableSize, Value *&Label, Value *&LongjmpResult,
564  BasicBlock *&EndBB) {
565  Function *F = BB->getParent();
566  Module *M = F->getParent();
567  LLVMContext &C = M->getContext();
568  IRBuilder<> IRB(C);
569  IRB.SetCurrentDebugLocation(DL);
570 
571  // if (%__THREW__.val != 0 & threwValue != 0)
572  IRB.SetInsertPoint(BB);
573  BasicBlock *ThenBB1 = BasicBlock::Create(C, "if.then1", F);
574  BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F);
575  BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F);
576  Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0));
577  Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV,
578  ThrewValueGV->getName() + ".val");
579  Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0));
580  Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, "cmp1");
581  IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1);
582 
583  // %label = _testSetjmp(mem[%__THREW__.val], _setjmpTable, _setjmpTableSize);
584  // if (%label == 0)
585  IRB.SetInsertPoint(ThenBB1);
586  BasicBlock *ThenBB2 = BasicBlock::Create(C, "if.then2", F);
587  BasicBlock *EndBB2 = BasicBlock::Create(C, "if.end2", F);
588  Value *ThrewPtr =
589  IRB.CreateIntToPtr(Threw, getAddrPtrType(M), Threw->getName() + ".p");
590  Value *LoadedThrew = IRB.CreateLoad(getAddrIntType(M), ThrewPtr,
591  ThrewPtr->getName() + ".loaded");
592  Value *ThenLabel = IRB.CreateCall(
593  TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize}, "label");
594  Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0));
595  IRB.CreateCondBr(Cmp2, ThenBB2, EndBB2);
596 
597  // emscripten_longjmp(%__THREW__.val, threwValue);
598  IRB.SetInsertPoint(ThenBB2);
599  IRB.CreateCall(EmLongjmpF, {Threw, ThrewValue});
600  IRB.CreateUnreachable();
601 
602  // setTempRet0(threwValue);
603  IRB.SetInsertPoint(EndBB2);
604  IRB.CreateCall(SetTempRet0Func, ThrewValue);
605  IRB.CreateBr(EndBB1);
606 
607  IRB.SetInsertPoint(ElseBB1);
608  IRB.CreateBr(EndBB1);
609 
610  // longjmp_result = getTempRet0();
611  IRB.SetInsertPoint(EndBB1);
612  PHINode *LabelPHI = IRB.CreatePHI(IRB.getInt32Ty(), 2, "label");
613  LabelPHI->addIncoming(ThenLabel, EndBB2);
614 
615  LabelPHI->addIncoming(IRB.getInt32(-1), ElseBB1);
616 
617  // Output parameter assignment
618  Label = LabelPHI;
619  EndBB = EndBB1;
620  LongjmpResult = IRB.CreateCall(GetTempRet0Func, None, "longjmp_result");
621 }
622 
623 void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) {
624  DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
625  DT.recalculate(F); // CFG has been changed
626  SSAUpdater SSA;
627  for (BasicBlock &BB : F) {
628  for (Instruction &I : BB) {
629  SSA.Initialize(I.getType(), I.getName());
630  SSA.AddAvailableValue(&BB, &I);
631  for (auto UI = I.use_begin(), UE = I.use_end(); UI != UE;) {
632  Use &U = *UI;
633  ++UI;
634  auto *User = cast<Instruction>(U.getUser());
635  if (auto *UserPN = dyn_cast<PHINode>(User))
636  if (UserPN->getIncomingBlock(U) == &BB)
637  continue;
638 
639  if (DT.dominates(&I, User))
640  continue;
641  SSA.RewriteUseAfterInsertions(U);
642  }
643  }
644  }
645 }
646 
647 // Replace uses of longjmp with emscripten_longjmp. emscripten_longjmp takes
648 // arguments of type {i32, i32} (wasm32) / {i64, i32} (wasm64) and longjmp takes
649 // {jmp_buf*, i32}, so we need a ptrtoint instruction here to make the type
650 // match. jmp_buf* will eventually be lowered to i32 in the wasm backend.
652  Function *EmLongjmpF) {
653  Module *M = LongjmpF->getParent();
655  LLVMContext &C = LongjmpF->getParent()->getContext();
656  IRBuilder<> IRB(C);
657 
658  // For calls to longjmp, replace it with emscripten_longjmp and cast its first
659  // argument (jmp_buf*) to int
660  for (User *U : LongjmpF->users()) {
661  auto *CI = dyn_cast<CallInst>(U);
662  if (CI && CI->getCalledFunction() == LongjmpF) {
663  IRB.SetInsertPoint(CI);
664  Value *Jmpbuf =
665  IRB.CreatePtrToInt(CI->getArgOperand(0), getAddrIntType(M), "jmpbuf");
666  IRB.CreateCall(EmLongjmpF, {Jmpbuf, CI->getArgOperand(1)});
667  ToErase.push_back(CI);
668  }
669  }
670  for (auto *I : ToErase)
671  I->eraseFromParent();
672 
673  // If we have any remaining uses of longjmp's function pointer, replace it
674  // with (int(*)(jmp_buf*, int))emscripten_longjmp.
675  if (!LongjmpF->uses().empty()) {
676  Value *EmLongjmp =
677  IRB.CreateBitCast(EmLongjmpF, LongjmpF->getType(), "em_longjmp");
678  LongjmpF->replaceAllUsesWith(EmLongjmp);
679  }
680 }
681 
682 bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
683  LLVM_DEBUG(dbgs() << "********** Lower Emscripten EH & SjLj **********\n");
684 
685  LLVMContext &C = M.getContext();
686  IRBuilder<> IRB(C);
687 
688  Function *SetjmpF = M.getFunction("setjmp");
689  Function *LongjmpF = M.getFunction("longjmp");
690  bool SetjmpUsed = SetjmpF && !SetjmpF->use_empty();
691  bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty();
692  bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);
693 
694  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
695  assert(TPC && "Expected a TargetPassConfig");
696  auto &TM = TPC->getTM<WebAssemblyTargetMachine>();
697 
698  if (EnableEH && TM.Options.ExceptionModel == ExceptionHandling::Wasm)
699  report_fatal_error("-exception-model=wasm not allowed with "
700  "-enable-emscripten-cxx-exceptions");
701 
702  // Declare (or get) global variables __THREW__, __threwValue, and
703  // getTempRet0/setTempRet0 function which are used in common for both
704  // exception handling and setjmp/longjmp handling
705  ThrewGV = getGlobalVariable(M, getAddrIntType(&M), TM, "__THREW__");
706  ThrewValueGV = getGlobalVariable(M, IRB.getInt32Ty(), TM, "__threwValue");
707  GetTempRet0Func = getEmscriptenFunction(
708  FunctionType::get(IRB.getInt32Ty(), false), "getTempRet0", &M);
709  SetTempRet0Func = getEmscriptenFunction(
710  FunctionType::get(IRB.getVoidTy(), IRB.getInt32Ty(), false),
711  "setTempRet0", &M);
712  GetTempRet0Func->setDoesNotThrow();
713  SetTempRet0Func->setDoesNotThrow();
714 
715  bool Changed = false;
716 
717  // Exception handling
718  if (EnableEH) {
719  // Register __resumeException function
720  FunctionType *ResumeFTy =
721  FunctionType::get(IRB.getVoidTy(), IRB.getInt8PtrTy(), false);
722  ResumeF = getEmscriptenFunction(ResumeFTy, "__resumeException", &M);
723 
724  // Register llvm_eh_typeid_for function
725  FunctionType *EHTypeIDTy =
726  FunctionType::get(IRB.getInt32Ty(), IRB.getInt8PtrTy(), false);
727  EHTypeIDF = getEmscriptenFunction(EHTypeIDTy, "llvm_eh_typeid_for", &M);
728 
729  for (Function &F : M) {
730  if (F.isDeclaration())
731  continue;
732  Changed |= runEHOnFunction(F);
733  }
734  }
735 
736  // Setjmp/longjmp handling
737  if (DoSjLj) {
738  Changed = true; // We have setjmp or longjmp somewhere
739 
740  // Register emscripten_longjmp function
742  IRB.getVoidTy(), {getAddrIntType(&M), IRB.getInt32Ty()}, false);
743  EmLongjmpF = getEmscriptenFunction(FTy, "emscripten_longjmp", &M);
744 
745  if (LongjmpF)
746  replaceLongjmpWithEmscriptenLongjmp(LongjmpF, EmLongjmpF);
747 
748  if (SetjmpF) {
749  // Register saveSetjmp function
750  FunctionType *SetjmpFTy = SetjmpF->getFunctionType();
752  {SetjmpFTy->getParamType(0), IRB.getInt32Ty(),
754  false);
755  SaveSetjmpF = getEmscriptenFunction(FTy, "saveSetjmp", &M);
756 
757  // Register testSetjmp function
758  FTy = FunctionType::get(
759  IRB.getInt32Ty(),
760  {getAddrIntType(&M), Type::getInt32PtrTy(C), IRB.getInt32Ty()},
761  false);
762  TestSetjmpF = getEmscriptenFunction(FTy, "testSetjmp", &M);
763 
764  // Only traverse functions that uses setjmp in order not to insert
765  // unnecessary prep / cleanup code in every function
766  SmallPtrSet<Function *, 8> SetjmpUsers;
767  for (User *U : SetjmpF->users()) {
768  auto *UI = cast<Instruction>(U);
769  SetjmpUsers.insert(UI->getFunction());
770  }
771  for (Function *F : SetjmpUsers)
772  runSjLjOnFunction(*F);
773  }
774  }
775 
776  if (!Changed) {
777  // Delete unused global variables and functions
778  if (ResumeF)
779  ResumeF->eraseFromParent();
780  if (EHTypeIDF)
781  EHTypeIDF->eraseFromParent();
782  if (EmLongjmpF)
783  EmLongjmpF->eraseFromParent();
784  if (SaveSetjmpF)
785  SaveSetjmpF->eraseFromParent();
786  if (TestSetjmpF)
787  TestSetjmpF->eraseFromParent();
788  return false;
789  }
790 
791  return true;
792 }
793 
794 bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) {
795  Module &M = *F.getParent();
796  LLVMContext &C = F.getContext();
797  IRBuilder<> IRB(C);
798  bool Changed = false;
801  bool AllowExceptions = areAllExceptionsAllowed() ||
802  EHAllowlistSet.count(std::string(F.getName()));
803 
804  for (BasicBlock &BB : F) {
805  auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
806  if (!II)
807  continue;
808  Changed = true;
809  LandingPads.insert(II->getLandingPadInst());
810  IRB.SetInsertPoint(II);
811 
812  bool NeedInvoke = AllowExceptions && canThrow(II->getCalledOperand());
813  if (NeedInvoke) {
814  // Wrap invoke with invoke wrapper and generate preamble/postamble
815  Value *Threw = wrapInvoke(II);
816  ToErase.push_back(II);
817 
818  // Insert a branch based on __THREW__ variable
819  Value *Cmp = IRB.CreateICmpEQ(Threw, getAddrSizeInt(&M, 1), "cmp");
820  IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest());
821 
822  } else {
823  // This can't throw, and we don't need this invoke, just replace it with a
824  // call+branch
825  SmallVector<Value *, 16> Args(II->args());
826  CallInst *NewCall =
827  IRB.CreateCall(II->getFunctionType(), II->getCalledOperand(), Args);
828  NewCall->takeName(II);
829  NewCall->setCallingConv(II->getCallingConv());
830  NewCall->setDebugLoc(II->getDebugLoc());
831  NewCall->setAttributes(II->getAttributes());
832  II->replaceAllUsesWith(NewCall);
833  ToErase.push_back(II);
834 
835  IRB.CreateBr(II->getNormalDest());
836 
837  // Remove any PHI node entries from the exception destination
838  II->getUnwindDest()->removePredecessor(&BB);
839  }
840  }
841 
842  // Process resume instructions
843  for (BasicBlock &BB : F) {
844  // Scan the body of the basic block for resumes
845  for (Instruction &I : BB) {
846  auto *RI = dyn_cast<ResumeInst>(&I);
847  if (!RI)
848  continue;
849  Changed = true;
850 
851  // Split the input into legal values
852  Value *Input = RI->getValue();
853  IRB.SetInsertPoint(RI);
854  Value *Low = IRB.CreateExtractValue(Input, 0, "low");
855  // Create a call to __resumeException function
856  IRB.CreateCall(ResumeF, {Low});
857  // Add a terminator to the block
858  IRB.CreateUnreachable();
859  ToErase.push_back(RI);
860  }
861  }
862 
863  // Process llvm.eh.typeid.for intrinsics
864  for (BasicBlock &BB : F) {
865  for (Instruction &I : BB) {
866  auto *CI = dyn_cast<CallInst>(&I);
867  if (!CI)
868  continue;
869  const Function *Callee = CI->getCalledFunction();
870  if (!Callee)
871  continue;
872  if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
873  continue;
874  Changed = true;
875 
876  IRB.SetInsertPoint(CI);
877  CallInst *NewCI =
878  IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0), "typeid");
879  CI->replaceAllUsesWith(NewCI);
880  ToErase.push_back(CI);
881  }
882  }
883 
884  // Look for orphan landingpads, can occur in blocks with no predecessors
885  for (BasicBlock &BB : F) {
886  Instruction *I = BB.getFirstNonPHI();
887  if (auto *LPI = dyn_cast<LandingPadInst>(I))
888  LandingPads.insert(LPI);
889  }
890  Changed |= !LandingPads.empty();
891 
892  // Handle all the landingpad for this function together, as multiple invokes
893  // may share a single lp
894  for (LandingPadInst *LPI : LandingPads) {
895  IRB.SetInsertPoint(LPI);
896  SmallVector<Value *, 16> FMCArgs;
897  for (unsigned I = 0, E = LPI->getNumClauses(); I < E; ++I) {
898  Constant *Clause = LPI->getClause(I);
899  // TODO Handle filters (= exception specifications).
900  // https://bugs.llvm.org/show_bug.cgi?id=50396
901  if (LPI->isCatch(I))
902  FMCArgs.push_back(Clause);
903  }
904 
905  // Create a call to __cxa_find_matching_catch_N function
906  Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
907  CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc");
908  Value *Undef = UndefValue::get(LPI->getType());
909  Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0");
910  Value *TempRet0 = IRB.CreateCall(GetTempRet0Func, None, "tempret0");
911  Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
912 
913  LPI->replaceAllUsesWith(Pair1);
914  ToErase.push_back(LPI);
915  }
916 
917  // Erase everything we no longer need in this function
918  for (Instruction *I : ToErase)
919  I->eraseFromParent();
920 
921  return Changed;
922 }
923 
924 // This tries to get debug info from the instruction before which a new
925 // instruction will be inserted, and if there's no debug info in that
926 // instruction, tries to get the info instead from the previous instruction (if
927 // any). If none of these has debug info and a DISubprogram is provided, it
928 // creates a dummy debug info with the first line of the function, because IR
929 // verifier requires all inlinable callsites should have debug info when both a
930 // caller and callee have DISubprogram. If none of these conditions are met,
931 // returns empty info.
932 static DebugLoc getOrCreateDebugLoc(const Instruction *InsertBefore,
933  DISubprogram *SP) {
934  assert(InsertBefore);
935  if (InsertBefore->getDebugLoc())
936  return InsertBefore->getDebugLoc();
937  const Instruction *Prev = InsertBefore->getPrevNode();
938  if (Prev && Prev->getDebugLoc())
939  return Prev->getDebugLoc();
940  if (SP)
941  return DILocation::get(SP->getContext(), SP->getLine(), 1, SP);
942  return DebugLoc();
943 }
944 
945 bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
946  Module &M = *F.getParent();
947  LLVMContext &C = F.getContext();
948  IRBuilder<> IRB(C);
950  // Vector of %setjmpTable values
951  std::vector<Instruction *> SetjmpTableInsts;
952  // Vector of %setjmpTableSize values
953  std::vector<Instruction *> SetjmpTableSizeInsts;
954 
955  // Setjmp preparation
956 
957  // This instruction effectively means %setjmpTableSize = 4.
958  // We create this as an instruction intentionally, and we don't want to fold
959  // this instruction to a constant 4, because this value will be used in
960  // SSAUpdater.AddAvailableValue(...) later.
961  BasicBlock &EntryBB = F.getEntryBlock();
962  DebugLoc FirstDL = getOrCreateDebugLoc(&*EntryBB.begin(), F.getSubprogram());
963  BinaryOperator *SetjmpTableSize = BinaryOperator::Create(
964  Instruction::Add, IRB.getInt32(4), IRB.getInt32(0), "setjmpTableSize",
965  &*EntryBB.getFirstInsertionPt());
966  SetjmpTableSize->setDebugLoc(FirstDL);
967  // setjmpTable = (int *) malloc(40);
968  Instruction *SetjmpTable = CallInst::CreateMalloc(
969  SetjmpTableSize, IRB.getInt32Ty(), IRB.getInt32Ty(), IRB.getInt32(40),
970  nullptr, nullptr, "setjmpTable");
971  SetjmpTable->setDebugLoc(FirstDL);
972  // CallInst::CreateMalloc may return a bitcast instruction if the result types
973  // mismatch. We need to set the debug loc for the original call too.
974  auto *MallocCall = SetjmpTable->stripPointerCasts();
975  if (auto *MallocCallI = dyn_cast<Instruction>(MallocCall)) {
976  MallocCallI->setDebugLoc(FirstDL);
977  }
978  // setjmpTable[0] = 0;
979  IRB.SetInsertPoint(SetjmpTableSize);
980  IRB.CreateStore(IRB.getInt32(0), SetjmpTable);
981  SetjmpTableInsts.push_back(SetjmpTable);
982  SetjmpTableSizeInsts.push_back(SetjmpTableSize);
983 
984  // Setjmp transformation
985  std::vector<PHINode *> SetjmpRetPHIs;
986  Function *SetjmpF = M.getFunction("setjmp");
987  for (User *U : SetjmpF->users()) {
988  auto *CI = dyn_cast<CallInst>(U);
989  if (!CI)
990  report_fatal_error("Does not support indirect calls to setjmp");
991 
992  BasicBlock *BB = CI->getParent();
993  if (BB->getParent() != &F) // in other function
994  continue;
995 
996  // The tail is everything right after the call, and will be reached once
997  // when setjmp is called, and later when longjmp returns to the setjmp
999  // Add a phi to the tail, which will be the output of setjmp, which
1000  // indicates if this is the first call or a longjmp back. The phi directly
1001  // uses the right value based on where we arrive from
1002  IRB.SetInsertPoint(Tail->getFirstNonPHI());
1003  PHINode *SetjmpRet = IRB.CreatePHI(IRB.getInt32Ty(), 2, "setjmp.ret");
1004 
1005  // setjmp initial call returns 0
1006  SetjmpRet->addIncoming(IRB.getInt32(0), BB);
1007  // The proper output is now this, not the setjmp call itself
1008  CI->replaceAllUsesWith(SetjmpRet);
1009  // longjmp returns to the setjmp will add themselves to this phi
1010  SetjmpRetPHIs.push_back(SetjmpRet);
1011 
1012  // Fix call target
1013  // Our index in the function is our place in the array + 1 to avoid index
1014  // 0, because index 0 means the longjmp is not ours to handle.
1015  IRB.SetInsertPoint(CI);
1016  Value *Args[] = {CI->getArgOperand(0), IRB.getInt32(SetjmpRetPHIs.size()),
1017  SetjmpTable, SetjmpTableSize};
1018  Instruction *NewSetjmpTable =
1019  IRB.CreateCall(SaveSetjmpF, Args, "setjmpTable");
1020  Instruction *NewSetjmpTableSize =
1021  IRB.CreateCall(GetTempRet0Func, None, "setjmpTableSize");
1022  SetjmpTableInsts.push_back(NewSetjmpTable);
1023  SetjmpTableSizeInsts.push_back(NewSetjmpTableSize);
1024  ToErase.push_back(CI);
1025  }
1026 
1027  // Update each call that can longjmp so it can return to a setjmp where
1028  // relevant.
1029 
1030  // Because we are creating new BBs while processing and don't want to make
1031  // all these newly created BBs candidates again for longjmp processing, we
1032  // first make the vector of candidate BBs.
1033  std::vector<BasicBlock *> BBs;
1034  for (BasicBlock &BB : F)
1035  BBs.push_back(&BB);
1036 
1037  // BBs.size() will change within the loop, so we query it every time
1038  for (unsigned I = 0; I < BBs.size(); I++) {
1039  BasicBlock *BB = BBs[I];
1040  for (Instruction &I : *BB) {
1041  assert(!isa<InvokeInst>(&I));
1042  auto *CI = dyn_cast<CallInst>(&I);
1043  if (!CI)
1044  continue;
1045 
1046  const Value *Callee = CI->getCalledOperand();
1047  if (!canLongjmp(M, Callee))
1048  continue;
1049  if (isEmAsmCall(M, Callee))
1050  report_fatal_error("Cannot use EM_ASM* alongside setjmp/longjmp in " +
1051  F.getName() +
1052  ". Please consider using EM_JS, or move the "
1053  "EM_ASM into another function.",
1054  false);
1055 
1056  Value *Threw = nullptr;
1057  BasicBlock *Tail;
1058  if (Callee->getName().startswith("__invoke_")) {
1059  // If invoke wrapper has already been generated for this call in
1060  // previous EH phase, search for the load instruction
1061  // %__THREW__.val = __THREW__;
1062  // in postamble after the invoke wrapper call
1063  LoadInst *ThrewLI = nullptr;
1064  StoreInst *ThrewResetSI = nullptr;
1065  for (auto I = std::next(BasicBlock::iterator(CI)), IE = BB->end();
1066  I != IE; ++I) {
1067  if (auto *LI = dyn_cast<LoadInst>(I))
1068  if (auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand()))
1069  if (GV == ThrewGV) {
1070  Threw = ThrewLI = LI;
1071  break;
1072  }
1073  }
1074  // Search for the store instruction after the load above
1075  // __THREW__ = 0;
1076  for (auto I = std::next(BasicBlock::iterator(ThrewLI)), IE = BB->end();
1077  I != IE; ++I) {
1078  if (auto *SI = dyn_cast<StoreInst>(I)) {
1079  if (auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand())) {
1080  if (GV == ThrewGV &&
1081  SI->getValueOperand() == getAddrSizeInt(&M, 0)) {
1082  ThrewResetSI = SI;
1083  break;
1084  }
1085  }
1086  }
1087  }
1088  assert(Threw && ThrewLI && "Cannot find __THREW__ load after invoke");
1089  assert(ThrewResetSI && "Cannot find __THREW__ store after invoke");
1090  Tail = SplitBlock(BB, ThrewResetSI->getNextNode());
1091 
1092  } else {
1093  // Wrap call with invoke wrapper and generate preamble/postamble
1094  Threw = wrapInvoke(CI);
1095  ToErase.push_back(CI);
1096  Tail = SplitBlock(BB, CI->getNextNode());
1097  }
1098 
1099  // We need to replace the terminator in Tail - SplitBlock makes BB go
1100  // straight to Tail, we need to check if a longjmp occurred, and go to the
1101  // right setjmp-tail if so
1102  ToErase.push_back(BB->getTerminator());
1103 
1104  // Generate a function call to testSetjmp function and preamble/postamble
1105  // code to figure out (1) whether longjmp occurred (2) if longjmp
1106  // occurred, which setjmp it corresponds to
1107  Value *Label = nullptr;
1108  Value *LongjmpResult = nullptr;
1109  BasicBlock *EndBB = nullptr;
1110  wrapTestSetjmp(BB, CI->getDebugLoc(), Threw, SetjmpTable, SetjmpTableSize,
1111  Label, LongjmpResult, EndBB);
1112  assert(Label && LongjmpResult && EndBB);
1113 
1114  // Create switch instruction
1115  IRB.SetInsertPoint(EndBB);
1116  IRB.SetCurrentDebugLocation(EndBB->getInstList().back().getDebugLoc());
1117  SwitchInst *SI = IRB.CreateSwitch(Label, Tail, SetjmpRetPHIs.size());
1118  // -1 means no longjmp happened, continue normally (will hit the default
1119  // switch case). 0 means a longjmp that is not ours to handle, needs a
1120  // rethrow. Otherwise the index is the same as the index in P+1 (to avoid
1121  // 0).
1122  for (unsigned I = 0; I < SetjmpRetPHIs.size(); I++) {
1123  SI->addCase(IRB.getInt32(I + 1), SetjmpRetPHIs[I]->getParent());
1124  SetjmpRetPHIs[I]->addIncoming(LongjmpResult, EndBB);
1125  }
1126 
1127  // We are splitting the block here, and must continue to find other calls
1128  // in the block - which is now split. so continue to traverse in the Tail
1129  BBs.push_back(Tail);
1130  }
1131  }
1132 
1133  // Erase everything we no longer need in this function
1134  for (Instruction *I : ToErase)
1135  I->eraseFromParent();
1136 
1137  // Free setjmpTable buffer before each return instruction
1138  for (BasicBlock &BB : F) {
1139  Instruction *TI = BB.getTerminator();
1140  if (isa<ReturnInst>(TI)) {
1141  DebugLoc DL = getOrCreateDebugLoc(TI, F.getSubprogram());
1142  auto *Free = CallInst::CreateFree(SetjmpTable, TI);
1143  Free->setDebugLoc(DL);
1144  // CallInst::CreateFree may create a bitcast instruction if its argument
1145  // types mismatch. We need to set the debug loc for the bitcast too.
1146  if (auto *FreeCallI = dyn_cast<CallInst>(Free)) {
1147  if (auto *BitCastI = dyn_cast<BitCastInst>(FreeCallI->getArgOperand(0)))
1148  BitCastI->setDebugLoc(DL);
1149  }
1150  }
1151  }
1152 
1153  // Every call to saveSetjmp can change setjmpTable and setjmpTableSize
1154  // (when buffer reallocation occurs)
1155  // entry:
1156  // setjmpTableSize = 4;
1157  // setjmpTable = (int *) malloc(40);
1158  // setjmpTable[0] = 0;
1159  // ...
1160  // somebb:
1161  // setjmpTable = saveSetjmp(buf, label, setjmpTable, setjmpTableSize);
1162  // setjmpTableSize = getTempRet0();
1163  // So we need to make sure the SSA for these variables is valid so that every
1164  // saveSetjmp and testSetjmp calls have the correct arguments.
1165  SSAUpdater SetjmpTableSSA;
1166  SSAUpdater SetjmpTableSizeSSA;
1167  SetjmpTableSSA.Initialize(Type::getInt32PtrTy(C), "setjmpTable");
1168  SetjmpTableSizeSSA.Initialize(Type::getInt32Ty(C), "setjmpTableSize");
1169  for (Instruction *I : SetjmpTableInsts)
1170  SetjmpTableSSA.AddAvailableValue(I->getParent(), I);
1171  for (Instruction *I : SetjmpTableSizeInsts)
1172  SetjmpTableSizeSSA.AddAvailableValue(I->getParent(), I);
1173 
1174  for (auto UI = SetjmpTable->use_begin(), UE = SetjmpTable->use_end();
1175  UI != UE;) {
1176  // Grab the use before incrementing the iterator.
1177  Use &U = *UI;
1178  // Increment the iterator before removing the use from the list.
1179  ++UI;
1180  if (auto *I = dyn_cast<Instruction>(U.getUser()))
1181  if (I->getParent() != &EntryBB)
1182  SetjmpTableSSA.RewriteUse(U);
1183  }
1184  for (auto UI = SetjmpTableSize->use_begin(), UE = SetjmpTableSize->use_end();
1185  UI != UE;) {
1186  Use &U = *UI;
1187  ++UI;
1188  if (auto *I = dyn_cast<Instruction>(U.getUser()))
1189  if (I->getParent() != &EntryBB)
1190  SetjmpTableSizeSSA.RewriteUse(U);
1191  }
1192 
1193  // Finally, our modifications to the cfg can break dominance of SSA variables.
1194  // For example, in this code,
1195  // if (x()) { .. setjmp() .. }
1196  // if (y()) { .. longjmp() .. }
1197  // We must split the longjmp block, and it can jump into the block splitted
1198  // from setjmp one. But that means that when we split the setjmp block, it's
1199  // first part no longer dominates its second part - there is a theoretically
1200  // possible control flow path where x() is false, then y() is true and we
1201  // reach the second part of the setjmp block, without ever reaching the first
1202  // part. So, we rebuild SSA form here.
1203  rebuildSSA(F);
1204  return true;
1205 }
getGlobalVariable
static GlobalVariable * getGlobalVariable(Module &M, Type *Ty, WebAssemblyTargetMachine &TM, const char *Name)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:297
llvm::SSAUpdater::Initialize
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
Definition: SSAUpdater.cpp:53
llvm::IRBuilderBase::SetInsertPoint
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:184
llvm
Definition: AllocatorList.h:23
WebAssembly.h
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::Instruction::getModule
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Definition: Instruction.cpp:66
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:249
llvm::BasicBlock::iterator
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:90
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::CallBase::doesNotReturn
bool doesNotReturn() const
Determine if the call cannot return.
Definition: InstrTypes.h:1833
DebugInfoMetadata.h
llvm::Function
Definition: Function.h:61
llvm::IRBuilderBase::CreatePtrToInt
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2064
INITIALIZE_PASS
INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE, "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp", false, false) ModulePass *llvm
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:271
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:614
llvm::GlobalValue::NotThreadLocal
@ NotThreadLocal
Definition: GlobalValue.h:179
llvm::Function::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Function.cpp:371
llvm::ilist_node_with_parent::getNextNode
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:288
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1167
getSignature
static std::string getSignature(FunctionType *FTy)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:322
llvm::LandingPadInst
The landingpad instruction holds all of the information necessary to generate correct exception handl...
Definition: Instructions.h:2852
llvm::CallInst::CreateMalloc
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:
Definition: Instructions.cpp:712
llvm::cl::CommaSeparated
@ CommaSeparated
Definition: CommandLine.h:169
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::erase_if
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:1656
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:321
llvm::AttributeList::get
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute >> Attrs)
Create an AttributeList with the specified parameters in it.
Definition: Attributes.cpp:1211
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:151
llvm::Function::setDoesNotThrow
void setDoesNotThrow()
Definition: Function.h:611
llvm::StringMap::end
iterator end()
Definition: StringMap.h:205
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
llvm::createWebAssemblyLowerEmscriptenEHSjLj
ModulePass * createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH, bool DoSjLj)
llvm::AttributeList
Definition: Attributes.h:385
llvm::CallBase::getAttributes
AttributeList getAttributes() const
Return the parameter attributes for this call.
Definition: InstrTypes.h:1471
llvm::CallBase::getFunctionType
FunctionType * getFunctionType() const
Definition: InstrTypes.h:1244
llvm::Optional< unsigned >
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::count
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:145
llvm::IRBuilderBase::getIntN
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
Definition: IRBuilder.h:489
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:449
WebAssemblyTargetMachine.h
llvm::CallBase::getNumArgOperands
unsigned getNumArgOperands() const
Definition: InstrTypes.h:1339
llvm::CallBase::arg_begin
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Definition: InstrTypes.h:1306
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:218
replace
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
Definition: ConstantMerge.cpp:116
llvm::Type::getInt32PtrTy
static PointerType * getInt32PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:257
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:197
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
llvm::MDNode::get
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1198
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::FunctionType::isVarArg
bool isVarArg() const
Definition: DerivedTypes.h:122
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:288
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::DominatorTree::dominates
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Definition: Dominators.cpp:115
CommandLine.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::SmallVectorImpl::append
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:647
llvm::User
Definition: User.h:44
llvm::WebAssemblyTargetMachine
Definition: WebAssemblyTargetMachine.h:23
getOrCreateDebugLoc
static DebugLoc getOrCreateDebugLoc(const Instruction *InsertBefore, DISubprogram *SP)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:932
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::FunctionType::param_end
param_iterator param_end() const
Definition: DerivedTypes.h:128
llvm::AttributeList::getFnAttributes
AttributeSet getFnAttributes() const
The function attributes are returned.
Definition: Attributes.cpp:1565
llvm::CallBase::getCalledFunction
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation.
Definition: InstrTypes.h:1396
llvm::CallBase::setAttributes
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
Definition: InstrTypes.h:1475
llvm::BasicBlock::begin
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:296
llvm::IRBuilderBase::getIntNTy
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition: IRBuilder.h:531
canThrow
static bool canThrow(const Value *V)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:280
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::AttributeList::getParamAttributes
AttributeSet getParamAttributes(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
Definition: Attributes.cpp:1557
llvm::Value::uses
iterator_range< use_iterator > uses()
Definition: Value.h:377
llvm::BasicBlock::getFirstInsertionPt
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:249
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::FunctionType::param_begin
param_iterator param_begin() const
Definition: DerivedTypes.h:127
llvm::Instruction
Definition: Instruction.h:45
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:281
getAddrSizeInt
static Value * getAddrSizeInt(Module *M, uint64_t C)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:373
llvm::report_fatal_error
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
llvm::ExceptionHandling::Wasm
@ Wasm
WebAssembly Exception Handling.
EHAllowlist
static cl::list< std::string > EHAllowlist("emscripten-cxx-exceptions-allowed", cl::desc("The list of function names in which Emscripten-style " "exception handling is enabled (see emscripten " "EMSCRIPTEN_CATCHING_ALLOWED options)"), cl::CommaSeparated)
llvm::UndefValue::get
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1783
llvm::Use::getUser
User * getUser() const
Returns the User that contains this Use.
Definition: Use.h:73
llvm::FunctionType::params
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:129
DEBUG_TYPE
#define DEBUG_TYPE
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:203
llvm::None
const NoneType None
Definition: None.h:23
llvm::Value::use_empty
bool use_empty() const
Definition: Value.h:345
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:108
llvm::ARM_PROC::IE
@ IE
Definition: ARMBaseInfo.h:27
llvm::Type::getIntNPtrTy
static PointerType * getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS=0)
Definition: Type.cpp:241
llvm::Clause
Definition: DirectiveEmitter.h:123
SSA
Memory SSA
Definition: MemorySSA.cpp:73
llvm::IRBuilderBase::CreateBitCast
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2074
llvm::StoreInst
An instruction for storing to memory.
Definition: Instructions.h:303
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::PointerType::getUnqual
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Definition: DerivedTypes.h:653
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:572
llvm::AttributeSet::get
static AttributeSet get(LLVMContext &C, const AttrBuilder &B)
Definition: Attributes.cpp:731
llvm::PHINode::addIncoming
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Definition: Instructions.h:2750
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::DenseMap
Definition: DenseMap.h:714
llvm::CallBase::removeAttribute
void removeAttribute(unsigned i, Attribute::AttrKind Kind)
removes the attribute from the list of attributes.
Definition: InstrTypes.h:1522
llvm::CallingConv::Tail
@ Tail
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
Definition: CallingConv.h:81
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::AttrBuilder
Definition: Attributes.h:804
llvm::FunctionType::getParamType
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:134
StringExtras.h
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:634
llvm::Instruction::setDebugLoc
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:367
TargetPassConfig.h
llvm::Function::Create
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:137
llvm::ilist_node_with_parent::getPrevNode
NodeTy * getPrevNode()
Definition: ilist_node.h:274
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::RegState::Undef
@ Undef
Value of the register doesn't matter.
Definition: MachineInstrBuilder.h:52
SI
StandardInstrumentations SI(Debug, VerifyEach)
getAddrPtrType
static Type * getAddrPtrType(Module *M)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:365
llvm::Value::use_begin
use_iterator use_begin()
Definition: Value.h:361
getAddrIntType
static Type * getAddrIntType(Module *M)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:358
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::CallBase::arg_end
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
Definition: InstrTypes.h:1312
llvm::SmallPtrSetImpl::count
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:382
llvm::DominatorTreeBase::recalculate
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
Definition: GenericDomTree.h:778
llvm::BinaryOperator
Definition: InstrTypes.h:190
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:517
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
llvm::Value::use_end
use_iterator use_end()
Definition: Value.h:369
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
SSAUpdater.h
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:294
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:174
llvm::GlobalValue::LocalExecTLSModel
@ LocalExecTLSModel
Definition: GlobalValue.h:183
llvm::Value::stripPointerCasts
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:662
Callee
amdgpu Simplify well known AMD library false FunctionCallee Callee
Definition: AMDGPULibCalls.cpp:206
llvm::MDNode::getContext
LLVMContext & getContext() const
Definition: Metadata.h:957
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
llvm::pdb::PDB_SymType::Label
@ Label
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::X86::FirstMacroFusionInstKind::Cmp
@ Cmp
llvm::Module::getContext
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:261
llvm::CallInst::CreateFree
static Instruction * CreateFree(Value *Source, Instruction *InsertBefore)
Generate the IR for a call to the builtin free function.
Definition: Instructions.cpp:789
llvm::Function::getFunctionType
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:175
llvm::MCID::Add
@ Add
Definition: MCInstrDesc.h:183
llvm::CallBase::getCalledOperand
Value * getCalledOperand() const
Definition: InstrTypes.h:1389
llvm::GlobalValue::ExternalLinkage
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:48
llvm::AttributeList::FunctionIndex
@ FunctionIndex
Definition: Attributes.h:389
llvm::BasicBlock::getInstList
const InstListType & getInstList() const
Return the underlying instruction list container.
Definition: BasicBlock.h:363
llvm::AttributeList::getRetAttributes
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
Definition: Attributes.cpp:1561
llvm::AttributeSet
Definition: Attributes.h:254
llvm::Instruction::getDebugLoc
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Definition: Instruction.h:370
Dominators.h
llvm::CallBase::getArgOperand
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1341
llvm::SmallPtrSetImplBase::empty
LLVM_NODISCARD bool empty() const
Definition: SmallPtrSet.h:91
llvm::SSAUpdater::RewriteUse
void RewriteUse(Use &U)
Rewrite a use of the symbolic value.
Definition: SSAUpdater.cpp:187
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:94
llvm::PHINode
Definition: Instructions.h:2600
llvm::DISubprogram
Subprogram description.
Definition: DebugInfoMetadata.h:1800
llvm::CallBase
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1164
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:271
replaceLongjmpWithEmscriptenLongjmp
static void replaceLongjmpWithEmscriptenLongjmp(Function *LongjmpF, Function *EmLongjmpF)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:651
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1478
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3179
llvm::Value::takeName
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:367
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
llvm::SSAUpdater::AddAvailableValue
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
Definition: SSAUpdater.cpp:70
llvm::cl::desc
Definition: CommandLine.h:414
getEmscriptenFunction
static Function * getEmscriptenFunction(FunctionType *Ty, const Twine &Name, Module *M)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:338
llvm::SSAUpdater
Helper class for SSA formation on a set of values defined in multiple blocks.
Definition: SSAUpdater.h:38
llvm::BinaryOperator::Create
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.
Definition: Instructions.cpp:2550
BasicBlockUtils.h
llvm::SplitBlock
BasicBlock * SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="", bool Before=false)
Split the specified block at the specified instruction.
Definition: BasicBlockUtils.cpp:814
llvm::raw_string_ostream::str
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:632
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:123
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:422
llvm::IRBuilderBase::CreateCall
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2352
llvm::Optional::getValue
constexpr const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:282
llvm::CallingConv::WASM_EmscriptenInvoke
@ WASM_EmscriptenInvoke
Calling convention for emscripten __invoke_* functions.
Definition: CallingConv.h:247
llvm::CallBase::setCallingConv
void setCallingConv(CallingConv::ID CC)
Definition: InstrTypes.h:1456
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:102
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::SmallPtrSetImpl::insert
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:364
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::cl::list
Definition: CommandLine.h:1630