Index: lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -225,13 +225,8 @@ namespace { 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 *EmLongjmpFName; static const char *EmLongjmpJmpbufFName; static const char *SaveSetjmpFName; @@ -300,14 +295,9 @@ }; } // End anonymous namespace -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::EmLongjmpFName = "emscripten_longjmp"; const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpJmpbufFName = @@ -343,15 +333,13 @@ return true; } -// 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; +static GlobalVariable *createGlobalVariableI32(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); } // Simple function name mangler. @@ -613,11 +601,13 @@ LLVMContext &C = M.getContext(); IRBuilder<> IRB(C); - assert(!M.getNamedGlobal(SetThrewFName) && "setThrew already exists"); + 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::ExternalLinkage, SetThrewFName, &M); + Function::Create(FTy, GlobalValue::WeakODRLinkage, "setThrew", &M); Argument *Arg1 = &*(F->arg_begin()); Argument *Arg2 = &*std::next(F->arg_begin()); Arg1->setName("threw"); @@ -648,11 +638,12 @@ LLVMContext &C = M.getContext(); IRBuilder<> IRB(C); - assert(!M.getNamedGlobal(SetTempRet0FName) && "setTempRet0 already exists"); + 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::ExternalLinkage, SetTempRet0FName, &M); + Function::Create(FTy, GlobalValue::WeakODRLinkage, "setTempRet0", &M); F->arg_begin()->setName("value"); BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); IRB.SetInsertPoint(EntryBB); @@ -699,15 +690,9 @@ // Create global variables __THREW__, threwValue, and __tempRet0, which are // used in common for both exception handling and setjmp/longjmp handling - ThrewGV = new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, ThrewGVName)); - ThrewValueGV = new GlobalVariable( - M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, ThrewValueGVName)); - TempRet0GV = new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, TempRet0GVName)); + ThrewGV = createGlobalVariableI32(M, IRB, "__THREW__"); + ThrewValueGV = createGlobalVariableI32(M, IRB, "__threwValue"); + TempRet0GV = createGlobalVariableI32(M, IRB, "__tempRet0"); bool Changed = false; @@ -736,12 +721,6 @@ if (DoSjLj) { Changed = true; // We have setjmp or longjmp somewhere - Function *MallocF = M.getFunction("malloc"); - Function *FreeF = M.getFunction("free"); - if (!MallocF || !FreeF) - report_fatal_error( - "malloc and free must be linked into the module if setjmp is used"); - // Register saveSetjmp function FunctionType *SetjmpFTy = SetjmpF->getFunctionType(); SmallVector Params = {SetjmpFTy->getParamType(0), 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__:__THREW__.*]] = global i32 0 -; CHECK-DAG: @[[THREWVALUE:__threwValue.*]] = global i32 0 -; CHECK-DAG: @[[TEMPRET0:__tempRet0.*]] = global i32 0 +; CHECK-DAG: @[[__THREW__:__THREW__.*]] = weak_odr global i32 0 +; CHECK-DAG: @[[THREWVALUE:__threwValue.*]] = weak_odr global i32 0 +; CHECK-DAG: @[[TEMPRET0:__tempRet0.*]] = weak_odr global i32 0 ; Test invoke instruction with clauses (try-catch block) define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { @@ -173,7 +173,7 @@ ; CHECK-DAG: declare i8* @__cxa_find_matching_catch_4(i8*, i8*) ; setThrew function creation -; CHECK-LABEL: define void @setThrew(i32 %threw, i32 %value) { +; 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 @@ -187,7 +187,7 @@ ; CHECK: } ; setTempRet0 function creation -; CHECK-LABEL: define void @setTempRet0(i32 %value) { +; CHECK-LABEL: define weak_odr void @setTempRet0(i32 %value) { ; CHECK: entry: ; CHECK-NEXT: store i32 %value, i32* @[[TEMPRET0]] ; CHECK-NEXT: ret void 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__:__THREW__.*]] = global i32 0 -; CHECK-DAG: @[[THREWVALUE:__threwValue.*]] = global i32 0 -; CHECK-DAG: @[[TEMPRET0:__tempRet0.*]] = global i32 0 +; CHECK-DAG: @[[__THREW__:__THREW__.*]] = weak_odr global i32 0 +; CHECK-DAG: @[[THREWVALUE:__threwValue.*]] = weak_odr global i32 0 +; CHECK-DAG: @[[TEMPRET0:__tempRet0.*]] = weak_odr global i32 0 ; Test a simple setjmp - longjmp sequence define hidden void @setjmp_longjmp() {