[lld] [llvm] [WebAssembly] Require tags for Wasm EH and Wasm SJLJ to be defined externally (PR #159143)

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 17 14:52:42 PDT 2025


https://github.com/sbc100 updated https://github.com/llvm/llvm-project/pull/159143

>From ae501eb8865488feac0a70a706781d5dcd99711b Mon Sep 17 00:00:00 2001
From: Sam Clegg <sbc at chromium.org>
Date: Mon, 15 Sep 2025 17:13:02 -0700
Subject: [PATCH] [WebAssembly] Require tags for Wasm EH and Wasm SJLJ to be
 defined by compiler-rt

Rather then defining these tags in each object file that requires them
we can can declare them as undefined and require that they defined
externally in, for example, compiler-rt.
---
 lld/test/wasm/Inputs/tags.s                   |  7 ++++++
 lld/test/wasm/tag-section.ll                  | 16 +++++++------
 llvm/lib/CodeGen/AsmPrinter/WasmException.cpp | 23 -------------------
 llvm/lib/CodeGen/AsmPrinter/WasmException.h   |  2 +-
 .../WebAssembly/WebAssemblyAsmPrinter.cpp     |  7 ------
 .../CodeGen/WebAssembly/exception-legacy.ll   |  3 ++-
 llvm/test/CodeGen/WebAssembly/exception.ll    |  3 ++-
 7 files changed, 21 insertions(+), 40 deletions(-)
 create mode 100644 lld/test/wasm/Inputs/tags.s

diff --git a/lld/test/wasm/Inputs/tags.s b/lld/test/wasm/Inputs/tags.s
new file mode 100644
index 0000000000000..e59b31b25626d
--- /dev/null
+++ b/lld/test/wasm/Inputs/tags.s
@@ -0,0 +1,7 @@
+.globl __cpp_exception
+.tagtype  __cpp_exception i32
+__cpp_exception:
+
+.globl __c_longjmp
+.tagtype  __c_longjmp i32
+__c_longjmp:
diff --git a/lld/test/wasm/tag-section.ll b/lld/test/wasm/tag-section.ll
index 20823c72c6511..45a578fb12f4f 100644
--- a/lld/test/wasm/tag-section.ll
+++ b/lld/test/wasm/tag-section.ll
@@ -1,18 +1,20 @@
-; Static code
+; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_tags.o %p/Inputs/tags.s
+
+; Static code, with tags defined in tags.s
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling %p/Inputs/tag-section1.ll -o %t1.o
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling %p/Inputs/tag-section2.ll -o %t2.o
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling %s -o %t.o
-; RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o
-; RUN: wasm-ld --export-all -o %t-export-all.wasm %t.o %t1.o %t2.o
+; RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o %t_tags.o
+; RUN: wasm-ld --export-all -o %t-export-all.wasm %t.o %t1.o %t2.o %t_tags.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefix=NOPIC
 ; RUN: obj2yaml %t-export-all.wasm | FileCheck %s --check-prefix=NOPIC-EXPORT-ALL
 
-; PIC code
+; PIC code with tags imported
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %p/Inputs/tag-section1.ll -o %t1.o
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %p/Inputs/tag-section2.ll -o %t2.o
 ; RUN: llc -filetype=obj -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -relocation-model=pic %s -o %t.o
-; RUN: wasm-ld --import-undefined --experimental-pic --unresolved-symbols=import-dynamic -pie -o %t.wasm %t.o %t1.o %t2.o
-; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefix=PIC
+; RUN: wasm-ld --import-undefined --experimental-pic --unresolved-symbols=import-dynamic -pie -o %t_pic.wasm %t.o %t1.o %t2.o
+; RUN: obj2yaml %t_pic.wasm | FileCheck %s --check-prefix=PIC
 
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-emscripten"
@@ -49,7 +51,7 @@ define void @_start() {
 ; NOPIC-EXPORT-ALL:         Kind:            TAG
 ; NOPIC-EXPORT-ALL:         Index:           0
 
-; In PIC mode, tags are undefined and imported from JS.
+; In PIC mode, we leave the tags as undefined and they should be imported
 ; PIC:        Sections:
 ; PIC:         - Type:            TYPE
 ; PIC-NEXT:      Signatures:
diff --git a/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp b/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
index bf65e525dde14..0309c65c7fb9d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
@@ -19,29 +19,6 @@
 #include "llvm/MC/MCStreamer.h"
 using namespace llvm;
 
-void WasmException::endModule() {
-  // These are symbols used to throw/catch C++ exceptions and C longjmps. These
-  // symbols have to be emitted somewhere once in the module. Check if each of
-  // the symbols has already been created, i.e., we have at least one 'throw' or
-  // 'catch' instruction with the symbol in the module, and emit the symbol only
-  // if so.
-  //
-  // But in dynamic linking, it is in general not possible to come up with a
-  // module instantiating order in which tag-defining modules are loaded before
-  // the importing modules. So we make them undefined symbols here, define tags
-  // in the JS side, and feed them to each importing module.
-  if (!Asm->isPositionIndependent()) {
-    for (const char *SymName : {"__cpp_exception", "__c_longjmp"}) {
-      SmallString<60> NameStr;
-      Mangler::getNameWithPrefix(NameStr, SymName, Asm->getDataLayout());
-      if (Asm->OutContext.lookupSymbol(NameStr)) {
-        MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol(SymName);
-        Asm->OutStreamer->emitLabel(ExceptionSym);
-      }
-    }
-  }
-}
-
 void WasmException::endFunction(const MachineFunction *MF) {
   bool ShouldEmitExceptionTable = false;
   for (const LandingPadInfo &Info : MF->getLandingPads()) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/WasmException.h b/llvm/lib/CodeGen/AsmPrinter/WasmException.h
index 86cc37dfde079..9b545dfc98857 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WasmException.h
+++ b/llvm/lib/CodeGen/AsmPrinter/WasmException.h
@@ -26,7 +26,7 @@ class LLVM_LIBRARY_VISIBILITY WasmException : public EHStreamer {
 public:
   WasmException(AsmPrinter *A) : EHStreamer(A) {}
 
-  void endModule() override;
+  void endModule() override {}
   void beginFunction(const MachineFunction *MF) override {}
   void endFunction(const MachineFunction *MF) override;
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index db832bc91ddb5..6bb064a53eabd 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -249,13 +249,6 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
   SmallVector<wasm::ValType, 4> Params;
   if (Name == "__cpp_exception" || Name == "__c_longjmp") {
     WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
-    // In static linking we define tag symbols in WasmException::endModule().
-    // But we may have multiple objects to be linked together, each of which
-    // defines the tag symbols. To resolve them, we declare them as weak. In
-    // dynamic linking we make tag symbols undefined in the backend, define it
-    // in JS, and feed them to each importing module.
-    if (!isPositionIndependent())
-      WasmSym->setWeak(true);
     WasmSym->setExternal(true);
 
     // Currently both C++ exceptions and C longjmps have a single pointer type
diff --git a/llvm/test/CodeGen/WebAssembly/exception-legacy.ll b/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
index 149e443903a88..b96a664166f42 100644
--- a/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception-legacy.ll
@@ -573,4 +573,5 @@ attributes #0 = { nounwind }
 attributes #1 = { noreturn }
 attributes #2 = { noreturn nounwind }
 
-; CHECK: __cpp_exception:
+;; The exception tag should not be defined locally
+; CHECK-NOT: __cpp_exception:
diff --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll
index fc42f050a687e..873386b3dcc6d 100644
--- a/llvm/test/CodeGen/WebAssembly/exception.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception.ll
@@ -670,4 +670,5 @@ attributes #0 = { nounwind }
 attributes #1 = { noreturn }
 attributes #2 = { noreturn nounwind }
 
-; CHECK: __cpp_exception:
+;; The exception tag should not be defined locally
+; CHECK-NOT: __cpp_exception:



More information about the llvm-commits mailing list