diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -86,6 +86,7 @@ const MachineBasicBlock *MBB); unsigned getDelegateDepth(const SmallVectorImpl &Stack, const MachineBasicBlock *MBB); + unsigned getRethrowDepth(const SmallVectorImpl &Stack); void rewriteDepthImmediates(MachineFunction &MF); void fixEndsAtEndOfFunction(MachineFunction &MF); void cleanupFunctionData(MachineFunction &MF); @@ -1551,6 +1552,20 @@ return Depth; } +unsigned WebAssemblyCFGStackify::getRethrowDepth( + const SmallVectorImpl &Stack) { + unsigned Depth = 0; + // In our current implementation, rethrows always rethrow the exception caught + // by the innermost enclosing catch. So find the nearest end_try marker. + for (auto X : reverse(Stack)) { + if (X.second->getOpcode() == WebAssembly::END_TRY) + break; + ++Depth; + } + assert(Depth < Stack.size() && "Rethrow destination should be in scope"); + return Depth; +} + void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { // Now rewrite references to basic blocks to be depth immediates. SmallVector Stack; @@ -1585,6 +1600,10 @@ Stack.push_back(std::make_pair(EndToBegin[&MI]->getParent(), &MI)); break; + case WebAssembly::RETHROW: + MI.getOperand(0).setImm(getRethrowDepth(Stack)); + break; + default: if (MI.isTerminator()) { // Rewrite MBB operands to be depth immediates. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -133,8 +133,8 @@ "throw \t$tag", "throw \t$tag", 0x08>; defm RETHROW : NRI<(outs), (ins i32imm:$depth), [], "rethrow \t$depth", 0x09>; } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 -// For C++ support, we only rethrow the latest exception, thus always setting -// the depth to 0. +// The depth argument will be computed in CFGStackify. We set it to 0 here for +// now. def : Pat<(int_wasm_rethrow), (RETHROW 0)>; // Region within which an exception is caught: try / end_try diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll --- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -128,7 +128,7 @@ ; CHECK: br 2 # 2: down to label[[L1]] ; CHECK: end_try ; CHECK: end_block # label[[L0]]: -; CHECK: rethrow 0 # to caller +; CHECK: rethrow 1 # to caller ; CHECK: end_block # label[[L1]]: ; CHECK: call __cxa_end_catch ; CHECK: end_try