[llvm] [WebAssembly] Add assembly support for final EH proposal (PR #107917)
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 10 14:21:51 PDT 2024
================
@@ -259,14 +269,74 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
return Changed;
}
-// Remove unnecessary unreachables after a throw or rethrow.
+// Add CATCH_REF and CATCH_ALL_REF pseudo instructions to EH pads, and convert
+// RETHROWs to THROW_REFs.
+bool WebAssemblyLateEHPrepare::addCatchRefsAndThrowRefs(MachineFunction &MF) {
+ bool Changed = false;
+ const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+ auto &MRI = MF.getRegInfo();
+ DenseMap<MachineBasicBlock *, SmallVector<MachineInstr *, 2>> EHPadToRethrows;
+
+ // Create a map of <EH pad, a vector of RETHROWs rethrowing its exception>
+ for (auto &MBB : MF) {
+ for (auto &MI : MBB) {
+ if (MI.getOpcode() == WebAssembly::RETHROW) {
+ Changed = true;
+ auto *EHPad = getMatchingEHPad(&MI);
+ EHPadToRethrows[EHPad].push_back(&MI);
+ }
+ }
+ }
+
+ // Convert CATCH into CATCH_REF and CATCH_ALL into CATCH_ALL_REF, when the
+ // caught exception is rethrown. And convert RETHROWs to THROW_REFs.
+ for (auto &[EHPad, Rethrows] : EHPadToRethrows) {
+ auto *Catch = WebAssembly::findCatch(EHPad);
+ auto *InsertPos = Catch->getIterator()->getNextNode();
+ auto ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
+ if (Catch->getOpcode() == WebAssembly::CATCH) {
+ MachineInstrBuilder MIB = BuildMI(*EHPad, InsertPos, Catch->getDebugLoc(),
+ TII.get(WebAssembly::CATCH_REF));
+ // Copy defs (= extracted values) from the old CATCH to the new CATCH_REF
+ for (const auto &Def : Catch->defs())
+ MIB.addDef(Def.getReg());
+ MIB.addDef(ExnReg); // Attach the exnref def after extracted values
+ // Copy the tag symbol (The only use operand a CATCH can have is the tag
+ // symbol)
+ for (const auto &Use : Catch->uses()) {
+ MIB.addExternalSymbol(Use.getSymbolName());
+ break;
+ }
+ } else if (Catch->getOpcode() == WebAssembly::CATCH_ALL) {
+ BuildMI(*EHPad, InsertPos, Catch->getDebugLoc(),
+ TII.get(WebAssembly::CATCH_ALL_REF))
+ .addDef(ExnReg);
+ } else {
+ assert(false);
+ }
+ Catch->eraseFromParent();
+
+ for (auto *Rethrow : Rethrows) {
+ auto InsertPos = Rethrow->getIterator()++;
----------------
aheejin wrote:
`getNextNode` does not work here because it is very likely that there is no next node, because `RETHROW` is a terminator. But I can't just do `Rethrow->getParent()->end()` because there can be other non-functional instructions like `DBG_VALUE` after that.
Switched to `std::next(Rethrow->getIterator())`, given that this seems safer and also frequently used in the codebase.
https://github.com/llvm/llvm-project/pull/107917
More information about the llvm-commits
mailing list