Index: lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -50,7 +50,8 @@ /// /// In detail, this pass does following things: /// -/// 1) Create three global variables: __THREW__, __threwValue, and __tempRet0. +/// 1) Assumes the existence of 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). These @@ -65,9 +66,10 @@ /// /// * Exception handling /// -/// 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 +/// 2) We assume the existence of setThrew and setTempRet0 functions at link +/// time. +/// The global variables in 1) will exist in wasm address space, +/// but their values should be set in JS code, so 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. @@ -272,9 +274,6 @@ bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); } bool canLongjmp(Module &M, const Value *Callee) const; - void createSetThrewFunction(Module &M); - void createSetTempRet0Function(Module &M); - void rebuildSSA(Function &F); public: @@ -333,13 +332,15 @@ return true; } -static GlobalVariable *createGlobalVariableI32(Module &M, IRBuilder<> &IRB, - const char *Name) { +// Get a global variable with the given name. If it doesn't exist declare it, +// which will generate an import and asssumes that it will exist at link time. +static GlobalVariable *getGlobalVariableI32(Module &M, IRBuilder<> &IRB, + const char *Name) { if (M.getNamedGlobal(Name)) report_fatal_error(Twine("variable name is reserved: ") + Name); return new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::WeakODRLinkage, IRB.getInt32(0), Name); + GlobalValue::ExternalLinkage, nullptr, Name); } // Simple function name mangler. @@ -590,67 +591,6 @@ LongjmpResult = IRB.CreateLoad(TempRet0GV, "longjmp_result"); } -// Create setThrew function -// function setThrew(threw, value) { -// if (__THREW__ == 0) { -// __THREW__ = threw; -// __threwValue = value; -// } -// } -void WebAssemblyLowerEmscriptenEHSjLj::createSetThrewFunction(Module &M) { - LLVMContext &C = M.getContext(); - IRBuilder<> IRB(C); - - if (M.getNamedGlobal("setThrew")) - report_fatal_error("setThrew already exists"); - - Type *Params[] = {IRB.getInt32Ty(), IRB.getInt32Ty()}; - FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false); - Function *F = - Function::Create(FTy, GlobalValue::WeakODRLinkage, "setThrew", &M); - Argument *Arg1 = &*(F->arg_begin()); - Argument *Arg2 = &*std::next(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); - - IRB.SetInsertPoint(EntryBB); - Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val"); - Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(0), "cmp"); - IRB.CreateCondBr(Cmp, ThenBB, EndBB); - - IRB.SetInsertPoint(ThenBB); - IRB.CreateStore(Arg1, ThrewGV); - IRB.CreateStore(Arg2, ThrewValueGV); - IRB.CreateBr(EndBB); - - IRB.SetInsertPoint(EndBB); - IRB.CreateRetVoid(); -} - -// Create setTempRet0 function -// function setTempRet0(value) { -// __tempRet0 = value; -// } -void WebAssemblyLowerEmscriptenEHSjLj::createSetTempRet0Function(Module &M) { - LLVMContext &C = M.getContext(); - IRBuilder<> IRB(C); - - if (M.getNamedGlobal("setTempRet0")) - report_fatal_error("setTempRet0 already exists"); - Type *Params[] = {IRB.getInt32Ty()}; - FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false); - Function *F = - Function::Create(FTy, GlobalValue::WeakODRLinkage, "setTempRet0", &M); - F->arg_begin()->setName("value"); - BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); - IRB.SetInsertPoint(EntryBB); - IRB.CreateStore(&*F->arg_begin(), TempRet0GV); - IRB.CreateRetVoid(); -} - void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) { DominatorTree &DT = getAnalysis(F).getDomTree(); DT.recalculate(F); // CFG has been changed @@ -688,11 +628,12 @@ bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty(); bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed); - // Create global variables __THREW__, threwValue, and __tempRet0, which are - // used in common for both exception handling and setjmp/longjmp handling - ThrewGV = createGlobalVariableI32(M, IRB, "__THREW__"); - ThrewValueGV = createGlobalVariableI32(M, IRB, "__threwValue"); - TempRet0GV = createGlobalVariableI32(M, IRB, "__tempRet0"); + // Declare (or get) global variables __THREW__, threwValue, and __tempRet0, + // which are used in common for both exception handling and setjmp/longjmp + // handling + ThrewGV = getGlobalVariableI32(M, IRB, "__THREW__"); + ThrewValueGV = getGlobalVariableI32(M, IRB, "__threwValue"); + TempRet0GV = getGlobalVariableI32(M, IRB, "__tempRet0"); bool Changed = false; @@ -764,9 +705,6 @@ if (!Changed) { // Delete unused global variables and functions - ThrewGV->eraseFromParent(); - ThrewValueGV->eraseFromParent(); - TempRet0GV->eraseFromParent(); if (ResumeF) ResumeF->eraseFromParent(); if (EHTypeIDF) @@ -780,12 +718,6 @@ return false; } - // If we have made any changes while doing exception handling or - // setjmp/longjmp handling, we have to create these functions for JavaScript - // to call. - createSetThrewFunction(M); - createSetTempRet0Function(M); - return true; } Index: test/CodeGen/WebAssembly/lower-em-exceptions.ll =================================================================== --- test/CodeGen/WebAssembly/lower-em-exceptions.ll +++ test/CodeGen/WebAssembly/lower-em-exceptions.ll @@ -5,9 +5,9 @@ @_ZTIi = external constant i8* @_ZTIc = external constant i8* -; CHECK-DAG: __THREW__ = weak_odr global i32 0 -; CHECK-DAG: __threwValue = weak_odr global i32 0 -; CHECK-DAG: __tempRet0 = weak_odr global i32 0 +; CHECK-DAG: __THREW__ = external global i32 +; CHECK-DAG: __threwValue = external global i32 +; CHECK-DAG: __tempRet0 = external global i32 ; Test invoke instruction with clauses (try-catch block) define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { @@ -171,24 +171,3 @@ ; CHECK-DAG: declare void @__resumeException(i8*) ; CHECK-DAG: declare void @__invoke_void_i32(void (i32)*, i32) ; CHECK-DAG: declare i8* @__cxa_find_matching_catch_4(i8*, i8*) - -; setThrew function creation -; CHECK-LABEL: define weak_odr void @setThrew(i32 %threw, i32 %value) { -; CHECK: entry: -; CHECK-NEXT: %__THREW__.val = load i32, i32* @__THREW__ -; CHECK-NEXT: %cmp = icmp eq i32 %__THREW__.val, 0 -; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end -; CHECK: if.then: -; CHECK-NEXT: store i32 %threw, i32* @__THREW__ -; CHECK-NEXT: store i32 %value, i32* @__threwValue -; CHECK-NEXT: br label %if.end -; CHECK: if.end: -; CHECK-NEXT: ret void -; CHECK: } - -; setTempRet0 function creation -; CHECK-LABEL: define weak_odr void @setTempRet0(i32 %value) { -; CHECK: entry: -; CHECK-NEXT: store i32 %value, i32* @__tempRet0 -; CHECK-NEXT: ret void -; CHECK: } Index: test/CodeGen/WebAssembly/lower-em-sjlj.ll =================================================================== --- test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -6,9 +6,9 @@ %struct.__jmp_buf_tag = type { [6 x i32], i32, [32 x i32] } @global_var = hidden global i32 0, align 4 -; CHECK-DAG: __THREW__ = weak_odr global i32 0 -; CHECK-DAG: __threwValue = weak_odr global i32 0 -; CHECK-DAG: __tempRet0 = weak_odr global i32 0 +; CHECK-DAG: __THREW__ = external global i32 +; CHECK-DAG: __threwValue = external global i32 +; CHECK-DAG: __tempRet0 = external global i32 ; Test a simple setjmp - longjmp sequence define hidden void @setjmp_longjmp() {