diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -47,7 +47,7 @@ /// These variables are used for both exceptions and setjmp/longjmps. /// __THREW__ indicates whether an exception or a longjmp occurred or not. 0 /// means nothing occurred, 1 means an exception occurred, and other numbers -/// mean a longjmp occurred. In the case of longjmp, __threwValue variable +/// mean a longjmp occurred. In the case of longjmp, __THREW__ variable /// indicates the corresponding setjmp buffer the longjmp corresponds to. /// /// * Exception handling @@ -55,7 +55,7 @@ /// 2) We assume the existence of setThrew and setTempRet0/getTempRet0 functions /// at link time. setThrew exists in Emscripten's compiler-rt: /// -/// void setThrew(int threw, int value) { +/// void setThrew(uintptr_t threw, int value) { /// if (__THREW__ == 0) { /// __THREW__ = threw; /// __threwValue = value; @@ -292,13 +292,12 @@ return true; } -// 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, - WebAssemblyTargetMachine &TM, - const char *Name) { - auto Int32Ty = IRB.getInt32Ty(); - auto *GV = dyn_cast(M.getOrInsertGlobal(Name, Int32Ty)); +// Get a global variable with the given name. If it doesn't exist declare it, +// which will generate an import and assume that it will exist at link time. +static GlobalVariable *getGlobalVariable(Module &M, Type *Ty, + WebAssemblyTargetMachine &TM, + const char *Name) { + auto *GV = dyn_cast(M.getOrInsertGlobal(Name, Ty)); if (!GV) report_fatal_error(Twine("unable to create global: ") + Name); @@ -354,6 +353,28 @@ return F; } +// Returns an integer type for the target architecture's address space. +// i32 for wasm32 and i64 for wasm64. +static Type *getAddrIntType(Module *M) { + IRBuilder<> IRB(M->getContext()); + return IRB.getIntNTy(M->getDataLayout().getPointerSizeInBits()); +} + +// Returns an integer pointer type for the target architecture's address space. +// i32* for wasm32 and i64* for wasm64. +static Type *getAddrPtrType(Module *M) { + return Type::getIntNPtrTy(M->getContext(), + M->getDataLayout().getPointerSizeInBits()); +} + +// Returns an integer whose type is the integer type for the target's address +// space. Returns (i32 C) for wasm32 and (i64 C) for wasm64, when C is the +// integer. +static Value *getAddrSizeInt(Module *M, uint64_t C) { + IRBuilder<> IRB(M->getContext()); + return IRB.getIntN(M->getDataLayout().getPointerSizeInBits(), C); +} + // 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 @@ -381,7 +402,8 @@ // Returns %__THREW__.val, which indicates whether an exception is thrown (or // whether longjmp occurred), for future use. Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) { - LLVMContext &C = CI->getModule()->getContext(); + Module *M = CI->getModule(); + LLVMContext &C = M->getContext(); // 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 @@ -397,7 +419,7 @@ // Pre-invoke // __THREW__ = 0; - IRB.CreateStore(IRB.getInt32(0), ThrewGV); + IRB.CreateStore(getAddrSizeInt(M, 0), ThrewGV); // Invoke function wrapper in JavaScript SmallVector Args; @@ -445,8 +467,8 @@ // Post-invoke // %__THREW__.val = __THREW__; __THREW__ = 0; Value *Threw = - IRB.CreateLoad(IRB.getInt32Ty(), ThrewGV, ThrewGV->getName() + ".val"); - IRB.CreateStore(IRB.getInt32(0), ThrewGV); + IRB.CreateLoad(getAddrIntType(M), ThrewGV, ThrewGV->getName() + ".val"); + IRB.CreateStore(getAddrSizeInt(M, 0), ThrewGV); return Threw; } @@ -541,7 +563,8 @@ Value *SetjmpTableSize, Value *&Label, Value *&LongjmpResult, BasicBlock *&EndBB) { Function *F = BB->getParent(); - LLVMContext &C = BB->getModule()->getContext(); + Module *M = F->getParent(); + LLVMContext &C = M->getContext(); IRBuilder<> IRB(C); IRB.SetCurrentDebugLocation(DL); @@ -550,7 +573,7 @@ BasicBlock *ThenBB1 = BasicBlock::Create(C, "if.then1", F); BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F); BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F); - Value *ThrewCmp = IRB.CreateICmpNE(Threw, IRB.getInt32(0)); + Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0)); Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV, ThrewValueGV->getName() + ".val"); Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0)); @@ -562,10 +585,10 @@ IRB.SetInsertPoint(ThenBB1); BasicBlock *ThenBB2 = BasicBlock::Create(C, "if.then2", F); BasicBlock *EndBB2 = BasicBlock::Create(C, "if.end2", F); - Value *ThrewInt = IRB.CreateIntToPtr(Threw, Type::getInt32PtrTy(C), - Threw->getName() + ".i32p"); - Value *LoadedThrew = IRB.CreateLoad(IRB.getInt32Ty(), ThrewInt, - ThrewInt->getName() + ".loaded"); + Value *ThrewPtr = + IRB.CreateIntToPtr(Threw, getAddrPtrType(M), Threw->getName() + ".p"); + Value *LoadedThrew = IRB.CreateLoad(getAddrIntType(M), ThrewPtr, + ThrewPtr->getName() + ".loaded"); Value *ThenLabel = IRB.CreateCall( TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize}, "label"); Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0)); @@ -622,11 +645,12 @@ } // Replace uses of longjmp with emscripten_longjmp. emscripten_longjmp takes -// arguments of type {i32, i32} and longjmp takes {jmp_buf*, i32}, so we need a -// ptrtoint instruction here to make the type match. jmp_buf* will eventually be -// lowered to i32 in the wasm backend. +// arguments of type {i32, i32} (wasm32) / {i64, i32} (wasm64) and longjmp takes +// {jmp_buf*, i32}, so we need a ptrtoint instruction here to make the type +// match. jmp_buf* will eventually be lowered to i32 in the wasm backend. static void replaceLongjmpWithEmscriptenLongjmp(Function *LongjmpF, Function *EmLongjmpF) { + Module *M = LongjmpF->getParent(); SmallVector ToErase; LLVMContext &C = LongjmpF->getParent()->getContext(); IRBuilder<> IRB(C); @@ -638,7 +662,7 @@ if (CI && CI->getCalledFunction() == LongjmpF) { IRB.SetInsertPoint(CI); Value *Jmpbuf = - IRB.CreatePtrToInt(CI->getArgOperand(0), IRB.getInt32Ty(), "jmpbuf"); + IRB.CreatePtrToInt(CI->getArgOperand(0), getAddrIntType(M), "jmpbuf"); IRB.CreateCall(EmLongjmpF, {Jmpbuf, CI->getArgOperand(1)}); ToErase.push_back(CI); } @@ -671,9 +695,6 @@ assert(TPC && "Expected a TargetPassConfig"); auto &TM = TPC->getTM(); - if ((EnableEH || DoSjLj) && - Triple(M.getTargetTriple()).getArch() == Triple::wasm64) - report_fatal_error("Emscripten EH/SjLj is not supported with wasm64 yet"); if (EnableEH && TM.Options.ExceptionModel == ExceptionHandling::Wasm) report_fatal_error("-exception-model=wasm not allowed with " "-enable-emscripten-cxx-exceptions"); @@ -681,8 +702,8 @@ // Declare (or get) global variables __THREW__, __threwValue, and // getTempRet0/setTempRet0 function which are used in common for both // exception handling and setjmp/longjmp handling - ThrewGV = getGlobalVariableI32(M, IRB, TM, "__THREW__"); - ThrewValueGV = getGlobalVariableI32(M, IRB, TM, "__threwValue"); + ThrewGV = getGlobalVariable(M, getAddrIntType(&M), TM, "__THREW__"); + ThrewValueGV = getGlobalVariable(M, IRB.getInt32Ty(), TM, "__threwValue"); GetTempRet0Func = getEmscriptenFunction( FunctionType::get(IRB.getInt32Ty(), false), "getTempRet0", &M); SetTempRet0Func = getEmscriptenFunction( @@ -718,7 +739,7 @@ // Register emscripten_longjmp function FunctionType *FTy = FunctionType::get( - IRB.getVoidTy(), {IRB.getInt32Ty(), IRB.getInt32Ty()}, false); + IRB.getVoidTy(), {getAddrIntType(&M), IRB.getInt32Ty()}, false); EmLongjmpF = getEmscriptenFunction(FTy, "emscripten_longjmp", &M); if (LongjmpF) @@ -736,7 +757,8 @@ // Register testSetjmp function FTy = FunctionType::get( IRB.getInt32Ty(), - {IRB.getInt32Ty(), Type::getInt32PtrTy(C), IRB.getInt32Ty()}, false); + {getAddrIntType(&M), Type::getInt32PtrTy(C), IRB.getInt32Ty()}, + false); TestSetjmpF = getEmscriptenFunction(FTy, "testSetjmp", &M); // Only traverse functions that uses setjmp in order not to insert @@ -794,7 +816,7 @@ ToErase.push_back(II); // Insert a branch based on __THREW__ variable - Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(1), "cmp"); + Value *Cmp = IRB.CreateICmpEQ(Threw, getAddrSizeInt(&M, 1), "cmp"); IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest()); } else { @@ -1060,12 +1082,15 @@ // __THREW__ = 0; for (auto I = std::next(BasicBlock::iterator(ThrewLI)), IE = BB->end(); I != IE; ++I) { - if (auto *SI = dyn_cast(I)) - if (auto *GV = dyn_cast(SI->getPointerOperand())) - if (GV == ThrewGV && SI->getValueOperand() == IRB.getInt32(0)) { + if (auto *SI = dyn_cast(I)) { + if (auto *GV = dyn_cast(SI->getPointerOperand())) { + if (GV == ThrewGV && + SI->getValueOperand() == getAddrSizeInt(&M, 0)) { ThrewResetSI = SI; break; } + } + } } assert(Threw && ThrewLI && "Cannot find __THREW__ load after invoke"); assert(ThrewResetSI && "Cannot find __THREW__ store after invoke"); diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll @@ -1,8 +1,6 @@ ; RUN: llc < %s -enable-emscripten-cxx-exceptions | FileCheck %s --check-prefix=EH ; RUN: llc < %s -enable-emscripten-sjlj | FileCheck %s --check-prefix=SJLJ ; RUN: llc < %s | FileCheck %s --check-prefix=NONE -; RUN: not --crash llc < %s -enable-emscripten-cxx-exceptions -mtriple=wasm64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=WASM64-EH -; RUN: not --crash llc < %s -enable-emscripten-sjlj -mtriple=wasm64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=WASM64-SJLJ ; RUN: not --crash llc < %s -enable-emscripten-cxx-exceptions -exception-model=wasm 2>&1 | FileCheck %s --check-prefix=WASM-EH-EM-EH target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" @@ -103,6 +101,4 @@ ; SJLJ-NOT: .import_module emscripten_longjmp_jmpbuf ; SJLJ-NOT: .import_name emscripten_longjmp_jmpbuf -; WASM64-EH: LLVM ERROR: Emscripten EH/SjLj is not supported with wasm64 yet -; WASM64-SJLJ: LLVM ERROR: Emscripten EH/SjLj is not supported with wasm64 yet ; WASM-EH-EM-EH: LLVM ERROR: -exception-model=wasm not allowed with -enable-emscripten-cxx-exceptions diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll @@ -1,14 +1,15 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS +; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @_ZTIi = external constant i8* @_ZTIc = external constant i8* -; NO-TLS-DAG: __THREW__ = external global i32 +; NO-TLS-DAG: __THREW__ = external global [[PTR]] ; NO-TLS-DAG: __threwValue = external global i32 -; TLS-DAG: __THREW__ = external thread_local(localexec) global i32 +; TLS-DAG: __THREW__ = external thread_local(localexec) global [[PTR]] ; TLS-DAG: __threwValue = external thread_local(localexec) global i32 ; Test invoke instruction with clauses (try-catch block) @@ -18,11 +19,11 @@ invoke void @foo(i32 3) to label %invoke.cont unwind label %lpad ; CHECK: entry: -; CHECK-NEXT: store i32 0, i32* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ ; CHECK-NEXT: call cc{{.*}} void @__invoke_void_i32(void (i32)* @foo, i32 3) -; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__ -; CHECK-NEXT: store i32 0, i32* @__THREW__ -; CHECK-NEXT: %cmp = icmp eq i32 %[[__THREW__VAL]], 1 +; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], [[PTR]]* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ +; CHECK-NEXT: %cmp = icmp eq [[PTR]] %[[__THREW__VAL]], 1 ; CHECK-NEXT: br i1 %cmp, label %lpad, label %invoke.cont invoke.cont: ; preds = %entry @@ -74,11 +75,11 @@ invoke void @foo(i32 3) to label %invoke.cont unwind label %lpad ; CHECK: entry: -; CHECK-NEXT: store i32 0, i32* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ ; CHECK-NEXT: call cc{{.*}} void @__invoke_void_i32(void (i32)* @foo, i32 3) -; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__ -; CHECK-NEXT: store i32 0, i32* @__THREW__ -; CHECK-NEXT: %cmp = icmp eq i32 %[[__THREW__VAL]], 1 +; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], [[PTR]]* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ +; CHECK-NEXT: %cmp = icmp eq [[PTR]] %[[__THREW__VAL]], 1 ; CHECK-NEXT: br i1 %cmp, label %lpad, label %invoke.cont invoke.cont: ; preds = %entry @@ -125,7 +126,7 @@ %0 = invoke noalias i8* @bar(i8 signext 1, i8 zeroext 2) to label %invoke.cont unwind label %lpad ; CHECK: entry: -; CHECK-NEXT: store i32 0, i32* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ ; CHECK-NEXT: %0 = call cc{{.*}} noalias i8* @"__invoke_i8*_i8_i8"(i8* (i8, i8)* @bar, i8 signext 1, i8 zeroext 2) invoke.cont: ; preds = %entry diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -1,5 +1,6 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS +; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -7,12 +8,12 @@ %struct.__jmp_buf_tag = type { [6 x i32], i32, [32 x i32] } @global_var = global i32 0, align 4 -; NO-TLS-DAG: __THREW__ = external global i32 -; NO-TLS-DAG: __threwValue = external global i32 +; NO-TLS-DAG: __THREW__ = external global [[PTR]] +; NO-TLS-DAG: __threwValue = external global [[PTR]] ; TLS-DAG: __THREW__ = external thread_local(localexec) global i32 ; TLS-DAG: __threwValue = external thread_local(localexec) global i32 @global_longjmp_ptr = global void (%struct.__jmp_buf_tag*, i32)* @longjmp, align 4 -; CHECK-DAG: @global_longjmp_ptr = global void (%struct.__jmp_buf_tag*, i32)* bitcast (void (i32, i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*) +; CHECK-DAG: @global_longjmp_ptr = global void (%struct.__jmp_buf_tag*, i32)* bitcast (void ([[PTR]], i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*) ; Test a simple setjmp - longjmp sequence define void @setjmp_longjmp() { @@ -38,12 +39,12 @@ ; CHECK: entry.split: ; CHECK-NEXT: phi i32 [ 0, %entry ], [ %[[LONGJMP_RESULT:.*]], %if.end ] ; CHECK-NEXT: %[[ARRAYDECAY1:.*]] = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %[[BUF]], i32 0, i32 0 -; CHECK-NEXT: %[[JMPBUF:.*]] = ptrtoint %struct.__jmp_buf_tag* %[[ARRAYDECAY1]] to i32 -; CHECK-NEXT: store i32 0, i32* @__THREW__ -; CHECK-NEXT: call cc{{.*}} void @__invoke_void_i32_i32(void (i32, i32)* @emscripten_longjmp, i32 %[[JMPBUF]], i32 1) -; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__ -; CHECK-NEXT: store i32 0, i32* @__THREW__ -; CHECK-NEXT: %[[CMP0:.*]] = icmp ne i32 %__THREW__.val, 0 +; CHECK-NEXT: %[[JMPBUF:.*]] = ptrtoint %struct.__jmp_buf_tag* %[[ARRAYDECAY1]] to [[PTR]] +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ +; CHECK-NEXT: call cc{{.*}} void @__invoke_void_[[PTR]]_i32(void ([[PTR]], i32)* @emscripten_longjmp, [[PTR]] %[[JMPBUF]], i32 1) +; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], [[PTR]]* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ +; CHECK-NEXT: %[[CMP0:.*]] = icmp ne [[PTR]] %__THREW__.val, 0 ; CHECK-NEXT: %[[THREWVALUE_VAL:.*]] = load i32, i32* @__threwValue ; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %[[THREWVALUE_VAL]], 0 ; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] @@ -53,9 +54,9 @@ ; CHECK-NEXT: unreachable ; CHECK: if.then1: -; CHECK-NEXT: %[[__THREW__VAL_I32P:.*]] = inttoptr i32 %[[__THREW__VAL]] to i32* -; CHECK-NEXT: %[[__THREW__VAL_I32P_LOADED:.*]] = load i32, i32* %[[__THREW__VAL_I32P]] -; CHECK-NEXT: %[[LABEL:.*]] = call i32 @testSetjmp(i32 %[[__THREW__VAL_I32P_LOADED]], i32* %[[SETJMP_TABLE1]], i32 %[[SETJMP_TABLE_SIZE1]]) +; CHECK-NEXT: %[[__THREW__VAL_P:.*]] = inttoptr [[PTR]] %[[__THREW__VAL]] to [[PTR]]* +; CHECK-NEXT: %[[__THREW__VAL_P_LOADED:.*]] = load [[PTR]], [[PTR]]* %[[__THREW__VAL_P]] +; CHECK-NEXT: %[[LABEL:.*]] = call i32 @testSetjmp([[PTR]] %[[__THREW__VAL_P_LOADED]], i32* %[[SETJMP_TABLE1]], i32 %[[SETJMP_TABLE_SIZE1]]) ; CHECK-NEXT: %[[CMP:.*]] = icmp eq i32 %[[LABEL]], 0 ; CHECK-NEXT: br i1 %[[CMP]], label %if.then2, label %if.end2 @@ -70,7 +71,7 @@ ; CHECK-NEXT: ] ; CHECK: if.then2: -; CHECK-NEXT: call void @emscripten_longjmp(i32 %[[__THREW__VAL]], i32 %[[THREWVALUE_VAL]]) +; CHECK-NEXT: call void @emscripten_longjmp([[PTR]] %[[__THREW__VAL]], i32 %[[THREWVALUE_VAL]]) ; CHECK-NEXT: unreachable ; CHECK: if.end2: @@ -110,18 +111,18 @@ to label %try.cont unwind label %lpad ; CHECK: entry.split: -; CHECK: store i32 0, i32* @__THREW__ +; CHECK: store [[PTR]] 0, [[PTR]]* @__THREW__ ; CHECK-NEXT: call cc{{.*}} void @__invoke_void(void ()* @foo) -; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i32, i32* @__THREW__ -; CHECK-NEXT: store i32 0, i32* @__THREW__ -; CHECK-NEXT: %[[CMP0:.*]] = icmp ne i32 %[[__THREW__VAL]], 0 +; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], [[PTR]]* @__THREW__ +; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__ +; CHECK-NEXT: %[[CMP0:.*]] = icmp ne [[PTR]] %[[__THREW__VAL]], 0 ; CHECK-NEXT: %[[THREWVALUE_VAL:.*]] = load i32, i32* @__threwValue ; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %[[THREWVALUE_VAL]], 0 ; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1 ; CHECK: entry.split.split: -; CHECK-NEXT: %[[CMP:.*]] = icmp eq i32 %[[__THREW__VAL]], 1 +; CHECK-NEXT: %[[CMP:.*]] = icmp eq [[PTR]] %[[__THREW__VAL]], 1 ; CHECK-NEXT: br i1 %[[CMP]], label %lpad, label %try.cont lpad: ; preds = %entry @@ -191,7 +192,7 @@ call void @longjmp(%struct.__jmp_buf_tag* %arraydecay, i32 5) #1 unreachable ; CHECK: %[[JMPBUF:.*]] = ptrtoint -; CHECK-NEXT: call void @emscripten_longjmp(i32 %[[JMPBUF]], i32 5) +; CHECK-NEXT: call void @emscripten_longjmp([[PTR]] %[[JMPBUF]], i32 5) } ; Test inline asm handling @@ -265,7 +266,7 @@ ; Store longjmp in a local variable, load it, and call it store void (%struct.__jmp_buf_tag*, i32)* @longjmp, void (%struct.__jmp_buf_tag*, i32)** %local_longjmp_ptr, align 4 - ; CHECK: store void (%struct.__jmp_buf_tag*, i32)* bitcast (void (i32, i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*), void (%struct.__jmp_buf_tag*, i32)** %local_longjmp_ptr, align 4 + ; CHECK: store void (%struct.__jmp_buf_tag*, i32)* bitcast (void ([[PTR]], i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*), void (%struct.__jmp_buf_tag*, i32)** %local_longjmp_ptr, align 4 %longjmp_from_local_ptr = load void (%struct.__jmp_buf_tag*, i32)*, void (%struct.__jmp_buf_tag*, i32)** %local_longjmp_ptr, align 4 %arraydecay = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf0, i32 0, i32 0 call void %longjmp_from_local_ptr(%struct.__jmp_buf_tag* %arraydecay, i32 0) @@ -278,7 +279,7 @@ ; Pass longjmp as a function argument. This is a call but longjmp is not a ; callee but an argument. call void @take_longjmp(void (%struct.__jmp_buf_tag*, i32)* @longjmp) - ; CHECK: call void @take_longjmp(void (%struct.__jmp_buf_tag*, i32)* bitcast (void (i32, i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*)) + ; CHECK: call void @take_longjmp(void (%struct.__jmp_buf_tag*, i32)* bitcast (void ([[PTR]], i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*)) ret void } @@ -297,8 +298,8 @@ ; CHECK-DAG: declare i32 @getTempRet0() ; CHECK-DAG: declare void @setTempRet0(i32) ; CHECK-DAG: declare i32* @saveSetjmp(%struct.__jmp_buf_tag*, i32, i32*, i32) -; CHECK-DAG: declare i32 @testSetjmp(i32, i32*, i32) -; CHECK-DAG: declare void @emscripten_longjmp(i32, i32) +; CHECK-DAG: declare i32 @testSetjmp([[PTR]], i32*, i32) +; CHECK-DAG: declare void @emscripten_longjmp([[PTR]], i32) ; CHECK-DAG: declare void @__invoke_void(void ()*) attributes #0 = { returns_twice }