[llvm] r279075 - [WebAssembly] Refactor WebAssemblyLowerEmscriptenException pass for setjmp/longjmp

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 18 08:27:26 PDT 2016


Author: dschuff
Date: Thu Aug 18 10:27:25 2016
New Revision: 279075

URL: http://llvm.org/viewvc/llvm-project?rev=279075&view=rev
Log:
[WebAssembly] Refactor WebAssemblyLowerEmscriptenException pass for setjmp/longjmp

This patch changes the code structure of
WebAssemblyLowerEmscriptenException pass to support both exception
handling and setjmp/longjmp. It also changes the name of the pass and
the source file.

1. Change the file/pass name to WebAssemblyLowerEmscriptenExceptions ->
WebAssemblyLowerEmscriptenEHSjLj to make it clear that it supports both
EH and SjLj
2. List function / global variable names at the top so they
can be changed easily
3. Some cosmetic changes

Patch by Heejin Ahn

Differential Revision: https://reviews.llvm.org/D23588

Added:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
      - copied, changed from r279074, llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp
Removed:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp
Modified:
    llvm/trunk/lib/Target/WebAssembly/CMakeLists.txt
    llvm/trunk/lib/Target/WebAssembly/WebAssembly.h
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
    llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions-whitelist.ll
    llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions.ll

Modified: llvm/trunk/lib/Target/WebAssembly/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/CMakeLists.txt?rev=279075&r1=279074&r2=279075&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/WebAssembly/CMakeLists.txt Thu Aug 18 10:27:25 2016
@@ -20,7 +20,7 @@ add_llvm_target(WebAssemblyCodeGen
   WebAssemblyISelLowering.cpp
   WebAssemblyInstrInfo.cpp
   WebAssemblyLowerBrUnless.cpp
-  WebAssemblyLowerEmscriptenExceptions.cpp
+  WebAssemblyLowerEmscriptenEHSjLj.cpp
   WebAssemblyMachineFunctionInfo.cpp
   WebAssemblyMCInstLower.cpp
   WebAssemblyOptimizeLiveIntervals.cpp

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssembly.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssembly.h?rev=279075&r1=279074&r2=279075&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssembly.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssembly.h Thu Aug 18 10:27:25 2016
@@ -26,8 +26,8 @@ class ModulePass;
 class FunctionPass;
 
 // LLVM IR passes.
-ModulePass *createWebAssemblyLowerEmscriptenExceptions();
-void initializeWebAssemblyLowerEmscriptenExceptionsPass(PassRegistry &);
+ModulePass *createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH, bool DoSjLj);
+void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &);
 FunctionPass *createWebAssemblyOptimizeReturned();
 
 // ISel and immediate followup passes.

Copied: llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp (from r279074, llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp?p2=llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp&p1=llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp&r1=279074&r2=279075&rev=279075&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp Thu Aug 18 10:27:25 2016
@@ -1,4 +1,4 @@
-// WebAssemblyLowerEmscriptenExceptions.cpp - Lower exceptions for Emscripten //
+//=== WebAssemblyLowerEmscriptenEHSjLj.cpp - Lower exceptions for Emscripten =//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -23,9 +23,9 @@
 ///
 /// This pass does following things:
 ///
-/// 1) Create three global variables: __THREW__, threwValue, and tempRet0.
+/// 1) Create three global variables: __THREW__, __threwValue, and tempRet0.
 ///    tempRet0 will be set within __cxa_find_matching_catch() function in
-///    JS library, and __THREW__ and threwValue will be set in invoke wrappers
+///    JS library, and __THREW__ and __threwValue will be set in invoke wrappers
 ///    in JS glue code. For what invoke wrappers are, refer to 3).
 ///
 /// 2) Create setThrew and setTempRet0 functions.
@@ -38,7 +38,7 @@
 ///    function setThrew(threw, value) {
 ///      if (__THREW__ == 0) {
 ///        __THREW__ = threw;
-///        threwValue = value;
+///        __threwValue = value;
 ///      }
 ///    }
 ///
@@ -107,22 +107,49 @@
 
 using namespace llvm;
 
-#define DEBUG_TYPE "wasm-lower-em-exceptions"
+#define DEBUG_TYPE "wasm-lower-em-ehsjlj"
 
 static cl::list<std::string>
-    Whitelist("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);
+    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);
 
 namespace {
-class WebAssemblyLowerEmscriptenExceptions final : public ModulePass {
+class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
+  static const char *ThrewGVName;
+  static const char *ThrewValueGVName;
+  static const char *TempRet0GVName;
+  static const char *ResumeFName;
+  static const char *EHTypeIDFName;
+  static const char *SetThrewFName;
+  static const char *SetTempRet0FName;
+  static const char *FindMatchingCatchPrefix;
+  static const char *InvokePrefix;
+
+  bool DoEH;   // Enable exception handling
+  bool DoSjLj; // Enable setjmp/longjmp handling
+
+  GlobalVariable *ThrewGV;
+  GlobalVariable *ThrewValueGV;
+  GlobalVariable *TempRet0GV;
+  Function *ResumeF;
+  Function *EHTypeIDF;
+  // __cxa_find_matching_catch_N functions.
+  // Indexed by the number of clauses in an original landingpad instruction.
+  DenseMap<int, Function *> FindMatchingCatches;
+  // Map of <function signature string, invoke_ wrappers>
+  StringMap<Function *> InvokeWrappers;
+  // Set of whitelisted function names for exception handling
+  std::set<std::string> EHWhitelistSet;
+
   const char *getPassName() const override {
     return "WebAssembly Lower Emscripten Exceptions";
   }
 
-  bool runOnFunction(Function &F);
+  bool runEHOnFunction(Function &F);
+  bool runSjLjOnFunction(Function &F);
   // Returns __cxa_find_matching_catch_N function, where N = NumClauses + 2.
   // This is because a landingpad instruction contains two more arguments,
   // a personality function and a cleanup bit, and __cxa_find_matching_catch_N
@@ -131,39 +158,41 @@ class WebAssemblyLowerEmscriptenExceptio
   Function *getFindMatchingCatch(Module &M, unsigned NumClauses);
 
   Function *getInvokeWrapper(Module &M, InvokeInst *II);
-  bool areAllExceptionsAllowed() const { return WhitelistSet.empty(); }
-
-  GlobalVariable *ThrewGV;      // __THREW__
-  GlobalVariable *ThrewValueGV; // threwValue
-  GlobalVariable *TempRet0GV;   // tempRet0
-  Function *ResumeF;            // __resumeException
-  Function *EHTypeIdF;          // llvm_eh_typeid_for
-  // __cxa_find_matching_catch_N functions.
-  // Indexed by the number of clauses in an original landingpad instruction.
-  DenseMap<int, Function *> FindMatchingCatches;
-  // Map of <function signature string, invoke_ wrappers>
-  StringMap<Function *> InvokeWrappers;
-  // Set of whitelisted function names
-  std::set<std::string> WhitelistSet;
+  bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); }
 
 public:
   static char ID;
 
-  WebAssemblyLowerEmscriptenExceptions()
-      : ModulePass(ID), ThrewGV(nullptr), ThrewValueGV(nullptr),
-        TempRet0GV(nullptr) {
-    WhitelistSet.insert(Whitelist.begin(), Whitelist.end());
+  WebAssemblyLowerEmscriptenEHSjLj(bool DoEH = true, bool DoSjLj = true)
+      : ModulePass(ID), DoEH(DoEH), DoSjLj(DoSjLj), ThrewGV(nullptr),
+        ThrewValueGV(nullptr), TempRet0GV(nullptr), ResumeF(nullptr),
+        EHTypeIDF(nullptr) {
+    EHWhitelistSet.insert(EHWhitelist.begin(), EHWhitelist.end());
   }
   bool runOnModule(Module &M) override;
 };
 } // End anonymous namespace
 
-char WebAssemblyLowerEmscriptenExceptions::ID = 0;
-INITIALIZE_PASS(WebAssemblyLowerEmscriptenExceptions, DEBUG_TYPE,
-                "WebAssembly Lower Emscripten Exceptions", false, false)
-
-ModulePass *llvm::createWebAssemblyLowerEmscriptenExceptions() {
-  return new WebAssemblyLowerEmscriptenExceptions();
+const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewGVName = "__THREW__";
+const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewValueGVName = "__threwValue";
+const char *WebAssemblyLowerEmscriptenEHSjLj::TempRet0GVName = "__tempRet0";
+const char *WebAssemblyLowerEmscriptenEHSjLj::ResumeFName = "__resumeException";
+const char *WebAssemblyLowerEmscriptenEHSjLj::EHTypeIDFName =
+    "llvm_eh_typeid_for";
+const char *WebAssemblyLowerEmscriptenEHSjLj::SetThrewFName = "setThrew";
+const char *WebAssemblyLowerEmscriptenEHSjLj::SetTempRet0FName = "setTempRet0";
+const char *WebAssemblyLowerEmscriptenEHSjLj::FindMatchingCatchPrefix =
+    "__cxa_find_matching_catch_";
+const char *WebAssemblyLowerEmscriptenEHSjLj::InvokePrefix = "__invoke_";
+
+char WebAssemblyLowerEmscriptenEHSjLj::ID = 0;
+INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLj, DEBUG_TYPE,
+                "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
+                false, false)
+
+ModulePass *llvm::createWebAssemblyLowerEmscriptenEHSjLj(bool DoEH,
+                                                         bool DoSjLj) {
+  return new WebAssemblyLowerEmscriptenEHSjLj(DoEH, DoSjLj);
 }
 
 static bool canThrow(const Value *V) {
@@ -212,23 +241,23 @@ static std::string getSignature(Function
   return Sig;
 }
 
-Function *WebAssemblyLowerEmscriptenExceptions::getFindMatchingCatch(
-    Module &M, unsigned NumClauses) {
+Function *
+WebAssemblyLowerEmscriptenEHSjLj::getFindMatchingCatch(Module &M,
+                                                       unsigned NumClauses) {
   if (FindMatchingCatches.count(NumClauses))
     return FindMatchingCatches[NumClauses];
   PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext());
   SmallVector<Type *, 16> Args(NumClauses, Int8PtrTy);
   FunctionType *FTy = FunctionType::get(Int8PtrTy, Args, false);
-  Function *F = Function::Create(
-      FTy, GlobalValue::ExternalLinkage,
-      "__cxa_find_matching_catch_" + Twine(NumClauses + 2), &M);
+  Function *F =
+      Function::Create(FTy, GlobalValue::ExternalLinkage,
+                       FindMatchingCatchPrefix + Twine(NumClauses + 2), &M);
   FindMatchingCatches[NumClauses] = F;
   return F;
 }
 
-Function *
-WebAssemblyLowerEmscriptenExceptions::getInvokeWrapper(Module &M,
-                                                       InvokeInst *II) {
+Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(Module &M,
+                                                             InvokeInst *II) {
   SmallVector<Type *, 16> ArgTys;
   Value *Callee = II->getCalledValue();
   FunctionType *CalleeFTy;
@@ -251,58 +280,77 @@ WebAssemblyLowerEmscriptenExceptions::ge
   FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys,
                                         CalleeFTy->isVarArg());
   Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage,
-                                 "__invoke_" + Sig, &M);
+                                 InvokePrefix + Sig, &M);
   InvokeWrappers[Sig] = F;
   return F;
 }
 
-bool WebAssemblyLowerEmscriptenExceptions::runOnModule(Module &M) {
+bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
   LLVMContext &C = M.getContext();
-  IRBuilder<> Builder(C);
-  IntegerType *Int1Ty = Builder.getInt1Ty();
-  PointerType *Int8PtrTy = Builder.getInt8PtrTy();
-  IntegerType *Int32Ty = Builder.getInt32Ty();
-  Type *VoidTy = Builder.getVoidTy();
-
-  // Create global variables __THREW__, threwValue, and tempRet0
-  ThrewGV = new GlobalVariable(M, Int1Ty, false, GlobalValue::ExternalLinkage,
-                               Builder.getFalse(),
-                               createGlobalValueName(M, "__THREW__"));
+  IRBuilder<> IRB(C);
+  IntegerType *Int1Ty = IRB.getInt1Ty();
+  PointerType *Int8PtrTy = IRB.getInt8PtrTy();
+  IntegerType *Int32Ty = IRB.getInt32Ty();
+  Type *VoidTy = IRB.getVoidTy();
+
+  // Create global variables __THREW__, threwValue, and tempRet0, which are
+  // used in common for both exception handling and setjmp/longjmp handling
+  ThrewGV =
+      new GlobalVariable(M, Int1Ty, false, GlobalValue::ExternalLinkage,
+                         IRB.getFalse(), createGlobalValueName(M, ThrewGVName));
   ThrewValueGV = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, Builder.getInt32(0),
-      createGlobalValueName(M, "threwValue"));
-  TempRet0GV = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, Builder.getInt32(0),
-      createGlobalValueName(M, "tempRet0"));
-
-  // Register __resumeException function
-  FunctionType *ResumeFTy = FunctionType::get(VoidTy, Int8PtrTy, false);
-  ResumeF = Function::Create(ResumeFTy, GlobalValue::ExternalLinkage,
-                             "__resumeException", &M);
-
-  // Register llvm_eh_typeid_for function
-  FunctionType *EHTypeIdTy = FunctionType::get(Int32Ty, Int8PtrTy, false);
-  EHTypeIdF = Function::Create(EHTypeIdTy, GlobalValue::ExternalLinkage,
-                               "llvm_eh_typeid_for", &M);
+      M, Int32Ty, false, GlobalValue::ExternalLinkage, IRB.getInt32(0),
+      createGlobalValueName(M, ThrewValueGVName));
+  TempRet0GV = new GlobalVariable(M, Int32Ty, false,
+                                  GlobalValue::ExternalLinkage, IRB.getInt32(0),
+                                  createGlobalValueName(M, TempRet0GVName));
 
   bool Changed = false;
-  for (Function &F : M) {
-    if (F.isDeclaration())
-      continue;
-    Changed |= runOnFunction(F);
+
+  // Exception handling
+  if (DoEH) {
+    // Register __resumeException function
+    FunctionType *ResumeFTy = FunctionType::get(VoidTy, Int8PtrTy, false);
+    ResumeF = Function::Create(ResumeFTy, GlobalValue::ExternalLinkage,
+                               ResumeFName, &M);
+
+    // Register llvm_eh_typeid_for function
+    FunctionType *EHTypeIDTy = FunctionType::get(Int32Ty, Int8PtrTy, false);
+    EHTypeIDF = Function::Create(EHTypeIDTy, GlobalValue::ExternalLinkage,
+                                 EHTypeIDFName, &M);
+
+    for (Function &F : M) {
+      if (F.isDeclaration())
+        continue;
+      Changed |= runEHOnFunction(F);
+    }
+  }
+
+  // TODO: Run CFGSimplify like the emscripten JSBackend?
+
+  // Setjmp/longjmp handling
+  if (DoSjLj) {
+    for (Function &F : M) {
+      if (F.isDeclaration())
+        continue;
+      Changed |= runSjLjOnFunction(F);
+    }
   }
 
   if (!Changed)
     return false;
 
-  assert(!M.getNamedGlobal("setThrew") && "setThrew already exists");
-  assert(!M.getNamedGlobal("setTempRet0") && "setTempRet0 already exists");
+  // If we have made any changes while doing exception handling or
+  // setjmp/longjmp handling, we have to create these functions for JavaScript
+  // to call.
+  assert(!M.getNamedGlobal(SetThrewFName) && "setThrew already exists");
+  assert(!M.getNamedGlobal(SetTempRet0FName) && "setTempRet0 already exists");
 
   // Create setThrew function
   SmallVector<Type *, 2> Params = {Int1Ty, Int32Ty};
   FunctionType *FTy = FunctionType::get(VoidTy, Params, false);
   Function *F =
-      Function::Create(FTy, GlobalValue::ExternalLinkage, "setThrew", &M);
+      Function::Create(FTy, GlobalValue::ExternalLinkage, SetThrewFName, &M);
   Argument *Arg1 = &*(F->arg_begin());
   Argument *Arg2 = &*(++F->arg_begin());
   Arg1->setName("threw");
@@ -311,41 +359,41 @@ bool WebAssemblyLowerEmscriptenException
   BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", F);
   BasicBlock *EndBB = BasicBlock::Create(C, "if.end", F);
 
-  Builder.SetInsertPoint(EntryBB);
-  Value *Threw = Builder.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
-  Value *Cmp = Builder.CreateICmpEQ(Threw, Builder.getFalse(), "cmp");
-  Builder.CreateCondBr(Cmp, ThenBB, EndBB);
-
-  Builder.SetInsertPoint(ThenBB);
-  Builder.CreateStore(Arg1, ThrewGV);
-  Builder.CreateStore(Arg2, ThrewValueGV);
-  Builder.CreateBr(EndBB);
+  IRB.SetInsertPoint(EntryBB);
+  Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
+  Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getFalse(), "cmp");
+  IRB.CreateCondBr(Cmp, ThenBB, EndBB);
+
+  IRB.SetInsertPoint(ThenBB);
+  IRB.CreateStore(Arg1, ThrewGV);
+  IRB.CreateStore(Arg2, ThrewValueGV);
+  IRB.CreateBr(EndBB);
 
-  Builder.SetInsertPoint(EndBB);
-  Builder.CreateRetVoid();
+  IRB.SetInsertPoint(EndBB);
+  IRB.CreateRetVoid();
 
   // Create setTempRet0 function
   Params = {Int32Ty};
   FTy = FunctionType::get(VoidTy, Params, false);
-  F = Function::Create(FTy, GlobalValue::ExternalLinkage, "setTempRet0", &M);
+  F = Function::Create(FTy, GlobalValue::ExternalLinkage, SetTempRet0FName, &M);
   F->arg_begin()->setName("value");
   EntryBB = BasicBlock::Create(C, "entry", F);
-  Builder.SetInsertPoint(EntryBB);
-  Builder.CreateStore(&*F->arg_begin(), TempRet0GV);
-  Builder.CreateRetVoid();
+  IRB.SetInsertPoint(EntryBB);
+  IRB.CreateStore(&*F->arg_begin(), TempRet0GV);
+  IRB.CreateRetVoid();
 
   return true;
 }
 
-bool WebAssemblyLowerEmscriptenExceptions::runOnFunction(Function &F) {
+bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) {
   Module &M = *F.getParent();
   LLVMContext &C = F.getContext();
-  IRBuilder<> Builder(C);
+  IRBuilder<> IRB(C);
   bool Changed = false;
   SmallVector<Instruction *, 64> ToErase;
   SmallPtrSet<LandingPadInst *, 32> LandingPads;
   bool AllowExceptions =
-      areAllExceptionsAllowed() || WhitelistSet.count(F.getName());
+      areAllExceptionsAllowed() || EHWhitelistSet.count(F.getName());
 
   for (BasicBlock &BB : F) {
     auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
@@ -353,7 +401,7 @@ bool WebAssemblyLowerEmscriptenException
       continue;
     Changed = true;
     LandingPads.insert(II->getLandingPadInst());
-    Builder.SetInsertPoint(II);
+    IRB.SetInsertPoint(II);
 
     bool NeedInvoke = AllowExceptions && canThrow(II->getCalledValue());
     if (NeedInvoke) {
@@ -371,7 +419,7 @@ bool WebAssemblyLowerEmscriptenException
 
       // Pre-invoke
       // __THREW__ = 0;
-      Builder.CreateStore(Builder.getFalse(), ThrewGV);
+      IRB.CreateStore(IRB.getFalse(), ThrewGV);
 
       // Invoke function wrapper in JavaScript
       SmallVector<Value *, 16> CallArgs;
@@ -379,7 +427,7 @@ bool WebAssemblyLowerEmscriptenException
       // within the invoke wrapper later
       CallArgs.push_back(II->getCalledValue());
       CallArgs.append(II->arg_begin(), II->arg_end());
-      CallInst *NewCall = Builder.CreateCall(getInvokeWrapper(M, II), CallArgs);
+      CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(M, II), CallArgs);
       NewCall->takeName(II);
       NewCall->setCallingConv(II->getCallingConv());
       NewCall->setDebugLoc(II->getDebugLoc());
@@ -413,17 +461,17 @@ bool WebAssemblyLowerEmscriptenException
 
       // Post-invoke
       // %__THREW__.val = __THREW__; __THREW__ = 0;
-      Value *Threw = Builder.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
-      Builder.CreateStore(Builder.getFalse(), ThrewGV);
+      Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
+      IRB.CreateStore(IRB.getFalse(), ThrewGV);
 
       // Insert a branch based on __THREW__ variable
-      Builder.CreateCondBr(Threw, II->getUnwindDest(), II->getNormalDest());
+      IRB.CreateCondBr(Threw, II->getUnwindDest(), II->getNormalDest());
 
     } else {
       // This can't throw, and we don't need this invoke, just replace it with a
       // call+branch
       SmallVector<Value *, 16> CallArgs(II->arg_begin(), II->arg_end());
-      CallInst *NewCall = Builder.CreateCall(II->getCalledValue(), CallArgs);
+      CallInst *NewCall = IRB.CreateCall(II->getCalledValue(), CallArgs);
       NewCall->takeName(II);
       NewCall->setCallingConv(II->getCallingConv());
       NewCall->setDebugLoc(II->getDebugLoc());
@@ -431,7 +479,7 @@ bool WebAssemblyLowerEmscriptenException
       II->replaceAllUsesWith(NewCall);
       ToErase.push_back(II);
 
-      Builder.CreateBr(II->getNormalDest());
+      IRB.CreateBr(II->getNormalDest());
 
       // Remove any PHI node entries from the exception destination
       II->getUnwindDest()->removePredecessor(&BB);
@@ -448,15 +496,15 @@ bool WebAssemblyLowerEmscriptenException
 
       // Split the input into legal values
       Value *Input = RI->getValue();
-      Builder.SetInsertPoint(RI);
-      Value *Low = Builder.CreateExtractValue(Input, 0, "low");
+      IRB.SetInsertPoint(RI);
+      Value *Low = IRB.CreateExtractValue(Input, 0, "low");
 
       // Create a call to __resumeException function
       Value *Args[] = {Low};
-      Builder.CreateCall(ResumeF, Args);
+      IRB.CreateCall(ResumeF, Args);
 
       // Add a terminator to the block
-      Builder.CreateUnreachable();
+      IRB.CreateUnreachable();
       ToErase.push_back(RI);
     }
   }
@@ -473,9 +521,9 @@ bool WebAssemblyLowerEmscriptenException
       if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
         continue;
 
-      Builder.SetInsertPoint(CI);
+      IRB.SetInsertPoint(CI);
       CallInst *NewCI =
-          Builder.CreateCall(EHTypeIdF, CI->getArgOperand(0), "typeid");
+          IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0), "typeid");
       CI->replaceAllUsesWith(NewCI);
       ToErase.push_back(CI);
     }
@@ -491,7 +539,7 @@ bool WebAssemblyLowerEmscriptenException
   // Handle all the landingpad for this function together, as multiple invokes
   // may share a single lp
   for (LandingPadInst *LPI : LandingPads) {
-    Builder.SetInsertPoint(LPI);
+    IRB.SetInsertPoint(LPI);
     SmallVector<Value *, 16> FMCArgs;
     for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) {
       Constant *Clause = LPI->getClause(i);
@@ -501,8 +549,7 @@ bool WebAssemblyLowerEmscriptenException
       if (LPI->isFilter(i)) {
         ArrayType *ATy = cast<ArrayType>(Clause->getType());
         for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
-          Value *EV =
-              Builder.CreateExtractValue(Clause, makeArrayRef(j), "filter");
+          Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter");
           FMCArgs.push_back(EV);
         }
       } else
@@ -511,12 +558,11 @@ bool WebAssemblyLowerEmscriptenException
 
     // Create a call to __cxa_find_matching_catch_N function
     Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
-    CallInst *FMCI = Builder.CreateCall(FMCF, FMCArgs, "fmc");
+    CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc");
     Value *Undef = UndefValue::get(LPI->getType());
-    Value *Pair0 = Builder.CreateInsertValue(Undef, FMCI, 0, "pair0");
-    Value *TempRet0 =
-        Builder.CreateLoad(TempRet0GV, TempRet0GV->getName() + "val");
-    Value *Pair1 = Builder.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
+    Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0");
+    Value *TempRet0 = IRB.CreateLoad(TempRet0GV, TempRet0GV->getName() + "val");
+    Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
 
     LPI->replaceAllUsesWith(Pair1);
     ToErase.push_back(LPI);
@@ -528,3 +574,8 @@ bool WebAssemblyLowerEmscriptenException
 
   return Changed;
 }
+
+bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
+  // TODO
+  return false;
+}

Removed: llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp?rev=279074&view=auto
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenExceptions.cpp (removed)
@@ -1,530 +0,0 @@
-// WebAssemblyLowerEmscriptenExceptions.cpp - Lower exceptions for Emscripten //
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file lowers exception-related instructions in order to use
-/// Emscripten's JavaScript try and catch mechanism to handle exceptions.
-///
-/// To handle exceptions, this scheme relies on JavaScript's try and catch
-/// syntax and relevant exception-related libraries implemented in JavaScript
-/// glue code that will be produced by Emscripten. This is similar to the
-/// current Emscripten asm.js exception handling in fastcomp.
-/// For fastcomp's EH scheme, see these files in fastcomp LLVM branch:
-/// (Location: https://github.com/kripken/emscripten-fastcomp)
-/// lib/Target/JSBackend/NaCl/LowerEmExceptionsPass.cpp
-/// lib/Target/JSBackend/JSBackend.cpp
-/// lib/Target/JSBackend/CallHandlers.h
-///
-/// This pass does following things:
-///
-/// 1) Create three global variables: __THREW__, threwValue, and tempRet0.
-///    tempRet0 will be set within __cxa_find_matching_catch() function in
-///    JS library, and __THREW__ and threwValue will be set in invoke wrappers
-///    in JS glue code. For what invoke wrappers are, refer to 3).
-///
-/// 2) Create setThrew and setTempRet0 functions.
-///    The global variables created in 1) will exist in wasm address space,
-///    but their values should be set in JS code, so we provide these functions
-///    as interfaces to JS glue code. These functions are equivalent to the
-///    following JS functions, which actually exist in asm.js version of JS
-///    library.
-///
-///    function setThrew(threw, value) {
-///      if (__THREW__ == 0) {
-///        __THREW__ = threw;
-///        threwValue = value;
-///      }
-///    }
-///
-///    function setTempRet0(value) {
-///      tempRet0 = value;
-///    }
-///
-/// 3) Lower
-///      invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad
-///    into
-///      __THREW__ = 0;
-///      call @invoke_SIG(func, arg1, arg2)
-///      %__THREW__.val = __THREW__;
-///      __THREW__ = 0;
-///      br %__THREW__.val, label %lpad, label %invoke.cont
-///    SIG is a mangled string generated based on the LLVM IR-level function
-///    signature. After LLVM IR types are lowered to the target wasm types,
-///    the names for these wrappers will change based on wasm types as well,
-///    as in invoke_vi (function takes an int and returns void). The bodies of
-///    these wrappers will be generated in JS glue code, and inside those
-///    wrappers we use JS try-catch to generate actual exception effects. It
-///    also calls the original callee function. An example wrapper in JS code
-///    would look like this:
-///      function invoke_vi(index,a1) {
-///        try {
-///          Module["dynCall_vi"](index,a1); // This calls original callee
-///        } catch(e) {
-///          if (typeof e !== 'number' && e !== 'longjmp') throw e;
-///          asm["setThrew"](1, 0); // setThrew is called here
-///        }
-///      }
-///    If an exception is thrown, __THREW__ will be set to true in a wrapper,
-///    so we can jump to the right BB based on this value.
-///
-/// 4) Lower
-///      %val = landingpad catch c1 catch c2 catch c3 ...
-///      ... use %val ...
-///    into
-///      %fmc = call @__cxa_find_matching_catch_N(c1, c2, c3, ...)
-///      %val = {%fmc, tempRet0}
-///      ... use %val ...
-///    Here N is a number calculated based on the number of clauses.
-///    Global variable tempRet0 is set within __cxa_find_matching_catch() in
-///    JS glue code.
-///
-/// 5) Lower
-///      resume {%a, %b}
-///    into
-///      call @__resumeException(%a)
-///    where __resumeException() is a function in JS glue code.
-///
-/// 6) Lower
-///      call @llvm.eh.typeid.for(type) (intrinsic)
-///    into
-///      call @llvm_eh_typeid_for(type)
-///    llvm_eh_typeid_for function will be generated in JS glue code.
-///
-///===----------------------------------------------------------------------===//
-
-#include "WebAssembly.h"
-#include "llvm/IR/CallSite.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/raw_ostream.h"
-#include <set>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "wasm-lower-em-exceptions"
-
-static cl::list<std::string>
-    Whitelist("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);
-
-namespace {
-class WebAssemblyLowerEmscriptenExceptions final : public ModulePass {
-  const char *getPassName() const override {
-    return "WebAssembly Lower Emscripten Exceptions";
-  }
-
-  bool runOnFunction(Function &F);
-  // Returns __cxa_find_matching_catch_N function, where N = NumClauses + 2.
-  // This is because a landingpad instruction contains two more arguments,
-  // a personality function and a cleanup bit, and __cxa_find_matching_catch_N
-  // functions are named after the number of arguments in the original
-  // landingpad instruction.
-  Function *getFindMatchingCatch(Module &M, unsigned NumClauses);
-
-  Function *getInvokeWrapper(Module &M, InvokeInst *II);
-  bool areAllExceptionsAllowed() const { return WhitelistSet.empty(); }
-
-  GlobalVariable *ThrewGV;      // __THREW__
-  GlobalVariable *ThrewValueGV; // threwValue
-  GlobalVariable *TempRet0GV;   // tempRet0
-  Function *ResumeF;            // __resumeException
-  Function *EHTypeIdF;          // llvm_eh_typeid_for
-  // __cxa_find_matching_catch_N functions.
-  // Indexed by the number of clauses in an original landingpad instruction.
-  DenseMap<int, Function *> FindMatchingCatches;
-  // Map of <function signature string, invoke_ wrappers>
-  StringMap<Function *> InvokeWrappers;
-  // Set of whitelisted function names
-  std::set<std::string> WhitelistSet;
-
-public:
-  static char ID;
-
-  WebAssemblyLowerEmscriptenExceptions()
-      : ModulePass(ID), ThrewGV(nullptr), ThrewValueGV(nullptr),
-        TempRet0GV(nullptr) {
-    WhitelistSet.insert(Whitelist.begin(), Whitelist.end());
-  }
-  bool runOnModule(Module &M) override;
-};
-} // End anonymous namespace
-
-char WebAssemblyLowerEmscriptenExceptions::ID = 0;
-INITIALIZE_PASS(WebAssemblyLowerEmscriptenExceptions, DEBUG_TYPE,
-                "WebAssembly Lower Emscripten Exceptions", false, false)
-
-ModulePass *llvm::createWebAssemblyLowerEmscriptenExceptions() {
-  return new WebAssemblyLowerEmscriptenExceptions();
-}
-
-static bool canThrow(const Value *V) {
-  if (const auto *F = dyn_cast<const Function>(V)) {
-    // Intrinsics cannot throw
-    if (F->isIntrinsic())
-      return false;
-    StringRef Name = F->getName();
-    // leave setjmp and longjmp (mostly) alone, we process them properly later
-    if (Name == "setjmp" || Name == "longjmp")
-      return false;
-    return true;
-  }
-  return true; // not a function, so an indirect call - can throw, we can't tell
-}
-
-// Returns an available name for a global value.
-// If the proposed name already exists in the module, adds '_' at the end of
-// the name until the name is available.
-static inline std::string createGlobalValueName(const Module &M,
-                                                const std::string &Propose) {
-  std::string Name = Propose;
-  while (M.getNamedGlobal(Name))
-    Name += "_";
-  return Name;
-}
-
-// Simple function name mangler.
-// This function simply takes LLVM's string representation of parameter types
-// and concatenate them with '_'. There are non-alphanumeric characters but llc
-// is ok with it, and we need to postprocess these names after the lowering
-// phase anyway.
-static std::string getSignature(FunctionType *FTy) {
-  std::string Sig;
-  raw_string_ostream OS(Sig);
-  OS << *FTy->getReturnType();
-  for (Type *ParamTy : FTy->params())
-    OS << "_" << *ParamTy;
-  if (FTy->isVarArg())
-    OS << "_...";
-  Sig = OS.str();
-  Sig.erase(remove_if(Sig, isspace), Sig.end());
-  // When s2wasm parses .s file, a comma means the end of an argument. So a
-  // mangled function name can contain any character but a comma.
-  std::replace(Sig.begin(), Sig.end(), ',', '.');
-  return Sig;
-}
-
-Function *WebAssemblyLowerEmscriptenExceptions::getFindMatchingCatch(
-    Module &M, unsigned NumClauses) {
-  if (FindMatchingCatches.count(NumClauses))
-    return FindMatchingCatches[NumClauses];
-  PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext());
-  SmallVector<Type *, 16> Args(NumClauses, Int8PtrTy);
-  FunctionType *FTy = FunctionType::get(Int8PtrTy, Args, false);
-  Function *F = Function::Create(
-      FTy, GlobalValue::ExternalLinkage,
-      "__cxa_find_matching_catch_" + Twine(NumClauses + 2), &M);
-  FindMatchingCatches[NumClauses] = F;
-  return F;
-}
-
-Function *
-WebAssemblyLowerEmscriptenExceptions::getInvokeWrapper(Module &M,
-                                                       InvokeInst *II) {
-  SmallVector<Type *, 16> ArgTys;
-  Value *Callee = II->getCalledValue();
-  FunctionType *CalleeFTy;
-  if (auto *F = dyn_cast<Function>(Callee))
-    CalleeFTy = F->getFunctionType();
-  else {
-    auto *CalleeTy = dyn_cast<PointerType>(Callee->getType())->getElementType();
-    CalleeFTy = dyn_cast<FunctionType>(CalleeTy);
-  }
-
-  std::string Sig = getSignature(CalleeFTy);
-  if (InvokeWrappers.find(Sig) != InvokeWrappers.end())
-    return InvokeWrappers[Sig];
-
-  // Put the pointer to the callee as first argument
-  ArgTys.push_back(PointerType::getUnqual(CalleeFTy));
-  // Add argument types
-  ArgTys.append(CalleeFTy->param_begin(), CalleeFTy->param_end());
-
-  FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys,
-                                        CalleeFTy->isVarArg());
-  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage,
-                                 "__invoke_" + Sig, &M);
-  InvokeWrappers[Sig] = F;
-  return F;
-}
-
-bool WebAssemblyLowerEmscriptenExceptions::runOnModule(Module &M) {
-  LLVMContext &C = M.getContext();
-  IRBuilder<> Builder(C);
-  IntegerType *Int1Ty = Builder.getInt1Ty();
-  PointerType *Int8PtrTy = Builder.getInt8PtrTy();
-  IntegerType *Int32Ty = Builder.getInt32Ty();
-  Type *VoidTy = Builder.getVoidTy();
-
-  // Create global variables __THREW__, threwValue, and tempRet0
-  ThrewGV = new GlobalVariable(M, Int1Ty, false, GlobalValue::ExternalLinkage,
-                               Builder.getFalse(),
-                               createGlobalValueName(M, "__THREW__"));
-  ThrewValueGV = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, Builder.getInt32(0),
-      createGlobalValueName(M, "threwValue"));
-  TempRet0GV = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, Builder.getInt32(0),
-      createGlobalValueName(M, "tempRet0"));
-
-  // Register __resumeException function
-  FunctionType *ResumeFTy = FunctionType::get(VoidTy, Int8PtrTy, false);
-  ResumeF = Function::Create(ResumeFTy, GlobalValue::ExternalLinkage,
-                             "__resumeException", &M);
-
-  // Register llvm_eh_typeid_for function
-  FunctionType *EHTypeIdTy = FunctionType::get(Int32Ty, Int8PtrTy, false);
-  EHTypeIdF = Function::Create(EHTypeIdTy, GlobalValue::ExternalLinkage,
-                               "llvm_eh_typeid_for", &M);
-
-  bool Changed = false;
-  for (Function &F : M) {
-    if (F.isDeclaration())
-      continue;
-    Changed |= runOnFunction(F);
-  }
-
-  if (!Changed)
-    return false;
-
-  assert(!M.getNamedGlobal("setThrew") && "setThrew already exists");
-  assert(!M.getNamedGlobal("setTempRet0") && "setTempRet0 already exists");
-
-  // Create setThrew function
-  SmallVector<Type *, 2> Params = {Int1Ty, Int32Ty};
-  FunctionType *FTy = FunctionType::get(VoidTy, Params, false);
-  Function *F =
-      Function::Create(FTy, GlobalValue::ExternalLinkage, "setThrew", &M);
-  Argument *Arg1 = &*(F->arg_begin());
-  Argument *Arg2 = &*(++F->arg_begin());
-  Arg1->setName("threw");
-  Arg2->setName("value");
-  BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
-  BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", F);
-  BasicBlock *EndBB = BasicBlock::Create(C, "if.end", F);
-
-  Builder.SetInsertPoint(EntryBB);
-  Value *Threw = Builder.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
-  Value *Cmp = Builder.CreateICmpEQ(Threw, Builder.getFalse(), "cmp");
-  Builder.CreateCondBr(Cmp, ThenBB, EndBB);
-
-  Builder.SetInsertPoint(ThenBB);
-  Builder.CreateStore(Arg1, ThrewGV);
-  Builder.CreateStore(Arg2, ThrewValueGV);
-  Builder.CreateBr(EndBB);
-
-  Builder.SetInsertPoint(EndBB);
-  Builder.CreateRetVoid();
-
-  // Create setTempRet0 function
-  Params = {Int32Ty};
-  FTy = FunctionType::get(VoidTy, Params, false);
-  F = Function::Create(FTy, GlobalValue::ExternalLinkage, "setTempRet0", &M);
-  F->arg_begin()->setName("value");
-  EntryBB = BasicBlock::Create(C, "entry", F);
-  Builder.SetInsertPoint(EntryBB);
-  Builder.CreateStore(&*F->arg_begin(), TempRet0GV);
-  Builder.CreateRetVoid();
-
-  return true;
-}
-
-bool WebAssemblyLowerEmscriptenExceptions::runOnFunction(Function &F) {
-  Module &M = *F.getParent();
-  LLVMContext &C = F.getContext();
-  IRBuilder<> Builder(C);
-  bool Changed = false;
-  SmallVector<Instruction *, 64> ToErase;
-  SmallPtrSet<LandingPadInst *, 32> LandingPads;
-  bool AllowExceptions =
-      areAllExceptionsAllowed() || WhitelistSet.count(F.getName());
-
-  for (BasicBlock &BB : F) {
-    auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
-    if (!II)
-      continue;
-    Changed = true;
-    LandingPads.insert(II->getLandingPadInst());
-    Builder.SetInsertPoint(II);
-
-    bool NeedInvoke = AllowExceptions && canThrow(II->getCalledValue());
-    if (NeedInvoke) {
-      // If we are calling a function that is noreturn, we must remove that
-      // attribute. The code we insert here does expect it to return, after we
-      // catch the exception.
-      if (II->doesNotReturn()) {
-        if (auto *F = dyn_cast<Function>(II->getCalledValue()))
-          F->removeFnAttr(Attribute::NoReturn);
-        AttributeSet NewAttrs = II->getAttributes();
-        NewAttrs.removeAttribute(C, AttributeSet::FunctionIndex,
-                                 Attribute::NoReturn);
-        II->setAttributes(NewAttrs);
-      }
-
-      // Pre-invoke
-      // __THREW__ = 0;
-      Builder.CreateStore(Builder.getFalse(), ThrewGV);
-
-      // Invoke function wrapper in JavaScript
-      SmallVector<Value *, 16> CallArgs;
-      // Put the pointer to the callee as first argument, so it can be called
-      // within the invoke wrapper later
-      CallArgs.push_back(II->getCalledValue());
-      CallArgs.append(II->arg_begin(), II->arg_end());
-      CallInst *NewCall = Builder.CreateCall(getInvokeWrapper(M, II), CallArgs);
-      NewCall->takeName(II);
-      NewCall->setCallingConv(II->getCallingConv());
-      NewCall->setDebugLoc(II->getDebugLoc());
-
-      // Because we added the pointer to the callee as first argument, all
-      // argument attribute indices have to be incremented by one.
-      SmallVector<AttributeSet, 8> AttributesVec;
-      const AttributeSet &InvokePAL = II->getAttributes();
-      CallSite::arg_iterator AI = II->arg_begin();
-      unsigned i = 1; // Argument attribute index starts from 1
-      for (unsigned e = II->getNumArgOperands(); i <= e; ++AI, ++i) {
-        if (InvokePAL.hasAttributes(i)) {
-          AttrBuilder B(InvokePAL, i);
-          AttributesVec.push_back(AttributeSet::get(C, i + 1, B));
-        }
-      }
-      // Add any return attributes.
-      if (InvokePAL.hasAttributes(AttributeSet::ReturnIndex))
-        AttributesVec.push_back(
-            AttributeSet::get(C, InvokePAL.getRetAttributes()));
-      // Add any function attributes.
-      if (InvokePAL.hasAttributes(AttributeSet::FunctionIndex))
-        AttributesVec.push_back(
-            AttributeSet::get(C, InvokePAL.getFnAttributes()));
-      // Reconstruct the AttributesList based on the vector we constructed.
-      AttributeSet NewCallPAL = AttributeSet::get(C, AttributesVec);
-      NewCall->setAttributes(NewCallPAL);
-
-      II->replaceAllUsesWith(NewCall);
-      ToErase.push_back(II);
-
-      // Post-invoke
-      // %__THREW__.val = __THREW__; __THREW__ = 0;
-      Value *Threw = Builder.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
-      Builder.CreateStore(Builder.getFalse(), ThrewGV);
-
-      // Insert a branch based on __THREW__ variable
-      Builder.CreateCondBr(Threw, II->getUnwindDest(), II->getNormalDest());
-
-    } else {
-      // This can't throw, and we don't need this invoke, just replace it with a
-      // call+branch
-      SmallVector<Value *, 16> CallArgs(II->arg_begin(), II->arg_end());
-      CallInst *NewCall = Builder.CreateCall(II->getCalledValue(), CallArgs);
-      NewCall->takeName(II);
-      NewCall->setCallingConv(II->getCallingConv());
-      NewCall->setDebugLoc(II->getDebugLoc());
-      NewCall->setAttributes(II->getAttributes());
-      II->replaceAllUsesWith(NewCall);
-      ToErase.push_back(II);
-
-      Builder.CreateBr(II->getNormalDest());
-
-      // Remove any PHI node entries from the exception destination
-      II->getUnwindDest()->removePredecessor(&BB);
-    }
-  }
-
-  // Process resume instructions
-  for (BasicBlock &BB : F) {
-    // Scan the body of the basic block for resumes
-    for (Instruction &I : BB) {
-      auto *RI = dyn_cast<ResumeInst>(&I);
-      if (!RI)
-        continue;
-
-      // Split the input into legal values
-      Value *Input = RI->getValue();
-      Builder.SetInsertPoint(RI);
-      Value *Low = Builder.CreateExtractValue(Input, 0, "low");
-
-      // Create a call to __resumeException function
-      Value *Args[] = {Low};
-      Builder.CreateCall(ResumeF, Args);
-
-      // Add a terminator to the block
-      Builder.CreateUnreachable();
-      ToErase.push_back(RI);
-    }
-  }
-
-  // Process llvm.eh.typeid.for intrinsics
-  for (BasicBlock &BB : F) {
-    for (Instruction &I : BB) {
-      auto *CI = dyn_cast<CallInst>(&I);
-      if (!CI)
-        continue;
-      const Function *Callee = CI->getCalledFunction();
-      if (!Callee)
-        continue;
-      if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
-        continue;
-
-      Builder.SetInsertPoint(CI);
-      CallInst *NewCI =
-          Builder.CreateCall(EHTypeIdF, CI->getArgOperand(0), "typeid");
-      CI->replaceAllUsesWith(NewCI);
-      ToErase.push_back(CI);
-    }
-  }
-
-  // Look for orphan landingpads, can occur in blocks with no predecesors
-  for (BasicBlock &BB : F) {
-    Instruction *I = BB.getFirstNonPHI();
-    if (auto *LPI = dyn_cast<LandingPadInst>(I))
-      LandingPads.insert(LPI);
-  }
-
-  // Handle all the landingpad for this function together, as multiple invokes
-  // may share a single lp
-  for (LandingPadInst *LPI : LandingPads) {
-    Builder.SetInsertPoint(LPI);
-    SmallVector<Value *, 16> FMCArgs;
-    for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) {
-      Constant *Clause = LPI->getClause(i);
-      // As a temporary workaround for the lack of aggregate varargs support
-      // in the interface between JS and wasm, break out filter operands into
-      // their component elements.
-      if (LPI->isFilter(i)) {
-        ArrayType *ATy = cast<ArrayType>(Clause->getType());
-        for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
-          Value *EV =
-              Builder.CreateExtractValue(Clause, makeArrayRef(j), "filter");
-          FMCArgs.push_back(EV);
-        }
-      } else
-        FMCArgs.push_back(Clause);
-    }
-
-    // Create a call to __cxa_find_matching_catch_N function
-    Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
-    CallInst *FMCI = Builder.CreateCall(FMCF, FMCArgs, "fmc");
-    Value *Undef = UndefValue::get(LPI->getType());
-    Value *Pair0 = Builder.CreateInsertValue(Undef, FMCI, 0, "pair0");
-    Value *TempRet0 =
-        Builder.CreateLoad(TempRet0GV, TempRet0GV->getName() + "val");
-    Value *Pair1 = Builder.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
-
-    LPI->replaceAllUsesWith(Pair1);
-    ToErase.push_back(LPI);
-  }
-
-  // Erase everything we no longer need in this function
-  for (Instruction *I : ToErase)
-    I->eraseFromParent();
-
-  return Changed;
-}

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp?rev=279075&r1=279074&r2=279075&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp Thu Aug 18 10:27:25 2016
@@ -30,18 +30,24 @@ using namespace llvm;
 #define DEBUG_TYPE "wasm"
 
 // Emscripten's asm.js-style exception handling
-static cl::opt<bool> EnableEmExceptionHandling(
+static cl::opt<bool> EnableEmException(
     "enable-emscripten-cxx-exceptions",
     cl::desc("WebAssembly Emscripten-style exception handling"),
     cl::init(false));
 
+// Emscripten's asm.js-style setjmp/longjmp handling
+static cl::opt<bool> EnableEmSjLj(
+    "enable-emscripten-sjlj",
+    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
+    cl::init(false));
+
 extern "C" void LLVMInitializeWebAssemblyTarget() {
   // Register the target.
   RegisterTargetMachine<WebAssemblyTargetMachine> X(TheWebAssemblyTarget32);
   RegisterTargetMachine<WebAssemblyTargetMachine> Y(TheWebAssemblyTarget64);
 
   // Register exception handling pass to opt
-  initializeWebAssemblyLowerEmscriptenExceptionsPass(
+  initializeWebAssemblyLowerEmscriptenEHSjLjPass(
       *PassRegistry::getPassRegistry());
 }
 
@@ -160,8 +166,9 @@ void WebAssemblyPassConfig::addIRPasses(
     addPass(createWebAssemblyOptimizeReturned());
 
   // Handle exceptions.
-  if (EnableEmExceptionHandling)
-    addPass(createWebAssemblyLowerEmscriptenExceptions());
+  if (EnableEmException || EnableEmSjLj)
+    addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
+                                                   EnableEmSjLj));
 
   TargetPassConfig::addIRPasses();
 }

Modified: llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions-whitelist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions-whitelist.ll?rev=279075&r1=279074&r2=279075&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions-whitelist.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions-whitelist.ll Thu Aug 18 10:27:25 2016
@@ -1,4 +1,4 @@
-; RUN: opt < %s -wasm-lower-em-exceptions -emscripten-cxx-exceptions-whitelist=do_catch -S | FileCheck %s
+; RUN: opt < %s -wasm-lower-em-ehsjlj -emscripten-cxx-exceptions-whitelist=do_catch -S | FileCheck %s
 
 define void @dont_catch() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 ; CHECK-LABEL: @dont_catch(

Modified: llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions.ll?rev=279075&r1=279074&r2=279075&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/lower-em-exceptions.ll Thu Aug 18 10:27:25 2016
@@ -1,10 +1,10 @@
-; RUN: opt < %s -wasm-lower-em-exceptions -S | FileCheck %s
+; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s
 
 @_ZTIi = external constant i8*
 @_ZTIc = external constant i8*
 ; CHECK: @[[__THREW__:__THREW__.*]] = global i1 false
-; CHECK: @[[THREWVALUE:threwValue.*]] = global i32 0
-; CHECK: @[[TEMPRET0:tempRet0.*]] = global i32 0
+; CHECK: @[[THREWVALUE:__threwValue.*]] = global i32 0
+; CHECK: @[[TEMPRET0:__tempRet0.*]] = global i32 0
 
 ; Test invoke instruction with clauses (try-catch block)
 define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
@@ -170,12 +170,12 @@ declare void @__cxa_call_unexpected(i8*)
 ; setThrew function creation
 ; CHECK-LABEL: define void @setThrew(i1 %threw, i32 %value) {
 ; CHECK: entry:
-; CHECK-NEXT: %__THREW__.val = load i1, i1* @__THREW__
-; CHECK-NEXT: %cmp = icmp eq i1 %__THREW__.val, false
+; CHECK-NEXT: %[[__THREW__]].val = load i1, i1* @[[__THREW__]]
+; CHECK-NEXT: %cmp = icmp eq i1 %[[__THREW__]].val, false
 ; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
 ; CHECK: if.then:
-; CHECK-NEXT: store i1 %threw, i1* @__THREW__
-; CHECK-NEXT: store i32 %value, i32* @threwValue
+; CHECK-NEXT: store i1 %threw, i1* @[[__THREW__]]
+; CHECK-NEXT: store i32 %value, i32* @[[THREWVALUE]]
 ; CHECK-NEXT: br label %if.end
 ; CHECK: if.end:
 ; CHECK-NEXT: ret void
@@ -184,6 +184,6 @@ declare void @__cxa_call_unexpected(i8*)
 ; setTempRet0 function creation
 ; CHECK-LABEL: define void @setTempRet0(i32 %value) {
 ; CHECK: entry:
-; CHECK-NEXT: store i32 %value, i32* @tempRet0
+; CHECK-NEXT: store i32 %value, i32* @[[TEMPRET0]]
 ; CHECK-NEXT: ret void
 ; CHECK: }




More information about the llvm-commits mailing list