[llvm] [WebAssembly] Add assembly support for final EH proposal (PR #107917)

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 10 13:34:08 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()++;
----------------
dschuff wrote:

The use of post-increment on the getter seems a little bit confusing to me (since it seems like it's being used on an rvalue rather than on a variable that is still live after the statement). Is this equivalent  to `getIterator()->getNextNode()` like you used above?

https://github.com/llvm/llvm-project/pull/107917


More information about the llvm-commits mailing list