Skip to content

[WebAssembly] Add WebAssembly::Specifier #133116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

MaskRay
Copy link
Member

@MaskRay MaskRay commented Mar 26, 2025

Move wasm-specific members outside of MCSymbolRefExpr::VariantKind (a
legacy interface I am eliminating). Most changes are mechanic and
similar to what I've done for many ELF targets (e.g. X86 #132149)

Notes:

  • fixSymbolsInTLSFixups is replaced with setTLS in
    WebAssemblyWasmObjectWriter::getRelocType, similar to what I've done
    for many ELF targets.
  • SymA->setUsedInGOT() in recordRelocation is moved to
    getRelocType.

While here, rename "Modifier' to "Specifier":

"Relocation modifier", though concise, suggests adjustments happen during the linker's relocation step rather than the assembler's expression evaluation. I landed on "relocation specifier" as the winner. It's clear, aligns with Arm and IBM’s usage, and fits the assembler's role seamlessly.

Created using spr 1.3.5-bogner
@MaskRay MaskRay requested a review from sbc100 March 26, 2025 16:21
@llvmbot llvmbot added backend:WebAssembly mc Machine (object) code labels Mar 26, 2025
@MaskRay MaskRay requested a review from dschuff March 26, 2025 16:21
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2025

@llvm/pr-subscribers-backend-webassembly

@llvm/pr-subscribers-mc

Author: Fangrui Song (MaskRay)

Changes

Move wasm-specific members outside of MCSymbolRefExpr::VariantKind (a
legacy interface I am eliminating). Most changes are mechanic and
similar to what I've done for many ELF targets (e.g. X86 #132149)

Notes:

  • fixSymbolsInTLSFixups is replaced with setTLS in
    WebAssemblyWasmObjectWriter::getRelocType, similar to what I've done
    for many ELF targets.
  • SymA->setUsedInGOT() in recordRelocation is moved to
    getRelocType.

In the future, we should encode expressions with a relocation specifier
as WebAssemblyMCExpr and use MCValue::RefKind to hold the specifier of
the relocatable expression (e.g. AArch64, RISCV).
https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers

While here, rename "Modifier' to "Specifier":

> "Relocation modifier", though concise, suggests adjustments happen during the linker's relocation step rather than the assembler's expression evaluation. I landed on "relocation specifier" as the winner. It's clear, aligns with Arm and IBM’s usage, and fits the assembler's role seamlessly.


Patch is 20.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133116.diff

14 Files Affected:

  • (modified) llvm/include/llvm/MC/MCWasmStreamer.h (-3)
  • (modified) llvm/lib/MC/MCWasmStreamer.cpp (-45)
  • (modified) llvm/lib/MC/WasmObjectWriter.cpp (-9)
  • (modified) llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp (+2-1)
  • (modified) llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp (+4-3)
  • (modified) llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (+2-1)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt (+1)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp (+2-1)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp (+8-7)
  • (added) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.cpp (+34)
  • (added) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.h (+64)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp (+28-27)
  • (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+2-1)
  • (modified) llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp (+9-8)
diff --git a/llvm/include/llvm/MC/MCWasmStreamer.h b/llvm/include/llvm/MC/MCWasmStreamer.h
index 4dffd83b12d0d..71149c0ca3d17 100644
--- a/llvm/include/llvm/MC/MCWasmStreamer.h
+++ b/llvm/include/llvm/MC/MCWasmStreamer.h
@@ -67,11 +67,8 @@ class MCWasmStreamer : public MCObjectStreamer {
   void finishImpl() override;
 
 private:
-  void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
   void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
 
-  void fixSymbolsInTLSFixups(const MCExpr *expr);
-
   bool SeenIdent;
 };
 
diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp
index d4806b3a5ecb6..2d3b5adb58a20 100644
--- a/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/llvm/lib/MC/MCWasmStreamer.cpp
@@ -167,15 +167,6 @@ void MCWasmStreamer::emitIdent(StringRef IdentString) {
   // sections in the object format
 }
 
-void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
-                                        const MCSubtargetInfo &STI) {
-  this->MCObjectStreamer::emitInstToFragment(Inst, STI);
-  MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
-
-  for (auto &Fixup : F.getFixups())
-    fixSymbolsInTLSFixups(Fixup.getValue());
-}
-
 void MCWasmStreamer::emitInstToData(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {
   MCAssembler &Assembler = getAssembler();
@@ -183,9 +174,6 @@ void MCWasmStreamer::emitInstToData(const MCInst &Inst,
   SmallString<256> Code;
   Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
-  for (auto &Fixup : Fixups)
-    fixSymbolsInTLSFixups(Fixup.getValue());
-
   // Append the encoded instruction to the current data fragment (or create a
   // new such fragment if the current fragment is not a data fragment).
   MCDataFragment *DF = getOrCreateDataFragment();
@@ -205,39 +193,6 @@ void MCWasmStreamer::finishImpl() {
   this->MCObjectStreamer::finishImpl();
 }
 
-void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
-  switch (expr->getKind()) {
-  case MCExpr::Target:
-  case MCExpr::Constant:
-    break;
-
-  case MCExpr::Binary: {
-    const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
-    fixSymbolsInTLSFixups(be->getLHS());
-    fixSymbolsInTLSFixups(be->getRHS());
-    break;
-  }
-
-  case MCExpr::SymbolRef: {
-    const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
-    switch (symRef.getKind()) {
-    case MCSymbolRefExpr::VK_WASM_TLSREL:
-    case MCSymbolRefExpr::VK_WASM_GOT_TLS:
-      getAssembler().registerSymbol(symRef.getSymbol());
-      cast<MCSymbolWasm>(symRef.getSymbol()).setTLS();
-      break;
-    default:
-      break;
-    }
-    break;
-  }
-
-  case MCExpr::Unary:
-    fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
-    break;
-  }
-}
-
 void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
   llvm_unreachable("Wasm doesn't support this directive");
 }
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 9c919696a0ac2..b67e2174bd7bc 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -607,15 +607,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
     SymA->setUsedInReloc();
   }
 
-  switch (RefA->getKind()) {
-  case MCSymbolRefExpr::VK_GOT:
-  case MCSymbolRefExpr::VK_WASM_GOT_TLS:
-    SymA->setUsedInGOT();
-    break;
-  default:
-    break;
-  }
-
   WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
   LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
 
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 7f351213308e0..4a8d33297f7cc 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AsmParser/WebAssemblyAsmTypeCheck.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
 #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
@@ -701,7 +702,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       WasmSym->setSignature(Signature);
       WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
       const MCExpr *Expr = MCSymbolRefExpr::create(
-          WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
+          WasmSym, WebAssemblyMCExpr::VK_TYPEINDEX, Ctx);
       Operands.push_back(std::make_unique<WebAssemblyOperand>(
           Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
     }
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
index 9ebc0dfdab9fe..a7b5476b74f6d 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AsmParser/WebAssemblyAsmTypeCheck.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
 #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
@@ -264,9 +265,9 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc,
     break;
   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
   case wasm::WASM_SYMBOL_TYPE_DATA:
-    switch (SymRef->getKind()) {
-    case MCSymbolRefExpr::VK_GOT:
-    case MCSymbolRefExpr::VK_WASM_GOT_TLS:
+    switch (getSpecifier(SymRef)) {
+    case WebAssemblyMCExpr::VK_GOT:
+    case WebAssemblyMCExpr::VK_GOT_TLS:
       Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
       return false;
     default:
diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
index 8d4d2717b8041..a9066614dc7f8 100644
--- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
+++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
@@ -14,6 +14,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
 #include "TargetInfo/WebAssemblyTargetInfo.h"
 #include "llvm/BinaryFormat/Wasm.h"
@@ -238,7 +239,7 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
         auto *WasmSym = cast<MCSymbolWasm>(Sym);
         WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
         const MCExpr *Expr = MCSymbolRefExpr::create(
-            WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, getContext());
+            WasmSym, WebAssemblyMCExpr::VK_TYPEINDEX, getContext());
         MI.addOperand(MCOperand::createExpr(Expr));
       }
       break;
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
index ccecb0c149188..b5d6d233afad0 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMWebAssemblyDesc
   WebAssemblyInstPrinter.cpp
   WebAssemblyMCAsmInfo.cpp
   WebAssemblyMCCodeEmitter.cpp
+  WebAssemblyMCExpr.cpp
   WebAssemblyMCTargetDesc.cpp
   WebAssemblyMCTypeUtilities.cpp
   WebAssemblyTargetStreamer.cpp
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index 51214cfd6f610..5d423d5710bda 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/WebAssemblyInstPrinter.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
 #include "llvm/ADT/APFloat.h"
@@ -339,7 +340,7 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
     // as a signature here, such that the assembler can recover this
     // information.
     auto SRE = static_cast<const MCSymbolRefExpr *>(Op.getExpr());
-    if (SRE->getKind() == MCSymbolRefExpr::VK_WASM_TYPEINDEX) {
+    if (getSpecifier(SRE) == WebAssemblyMCExpr::VK_TYPEINDEX) {
       auto &Sym = static_cast<const MCSymbolWasm &>(SRE->getSymbol());
       O << WebAssembly::signatureToString(Sym.getSignature());
     } else {
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp
index ffa63ed8146ae..e954c3075deb7 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyMCAsmInfo.h"
+#include "WebAssemblyMCExpr.h"
 #include "WebAssemblyMCTargetDesc.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/TargetParser/Triple.h"
@@ -22,13 +23,13 @@ using namespace llvm;
 #define DEBUG_TYPE "wasm-mc-asm-info"
 
 const MCAsmInfo::VariantKindDesc variantKindDescs[] = {
-    {MCSymbolRefExpr::VK_WASM_TYPEINDEX, "TYPEINDEX"},
-    {MCSymbolRefExpr::VK_WASM_TBREL, "TBREL"},
-    {MCSymbolRefExpr::VK_WASM_MBREL, "MBREL"},
-    {MCSymbolRefExpr::VK_WASM_TLSREL, "TLSREL"},
-    {MCSymbolRefExpr::VK_GOT, "GOT"},
-    {MCSymbolRefExpr::VK_WASM_GOT_TLS, "GOT@TLS"},
-    {MCSymbolRefExpr::VK_WASM_FUNCINDEX, "FUNCINDEX"},
+    {WebAssemblyMCExpr::VK_TYPEINDEX, "TYPEINDEX"},
+    {WebAssemblyMCExpr::VK_TBREL, "TBREL"},
+    {WebAssemblyMCExpr::VK_MBREL, "MBREL"},
+    {WebAssemblyMCExpr::VK_TLSREL, "TLSREL"},
+    {WebAssemblyMCExpr::VK_GOT, "GOT"},
+    {WebAssemblyMCExpr::VK_GOT_TLS, "GOT@TLS"},
+    {WebAssemblyMCExpr::VK_FUNCINDEX, "FUNCINDEX"},
 };
 
 WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() = default; // anchor.
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.cpp
new file mode 100644
index 0000000000000..acc621bbcfc33
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.cpp
@@ -0,0 +1,34 @@
+//===- WebAssembly specific MC expression classes ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyMCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCValue.h"
+
+using namespace llvm;
+
+const WebAssemblyMCExpr *
+WebAssemblyMCExpr::create(const MCExpr *Expr, Specifier S, MCContext &Ctx) {
+  return new (Ctx) WebAssemblyMCExpr(Expr, S);
+}
+
+void WebAssemblyMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+}
+
+bool WebAssemblyMCExpr::evaluateAsRelocatableImpl(
+    MCValue &Res, const MCAssembler *Asm) const {
+  if (!getSubExpr()->evaluateAsRelocatable(Res, Asm))
+    return false;
+  Res.setSpecifier(specifier);
+  return !Res.getSubSym();
+}
+
+void WebAssemblyMCExpr::visitUsedExpr(MCStreamer &S) const {
+  S.visitUsedExpr(*Expr);
+}
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.h
new file mode 100644
index 0000000000000..42fbbbe4d0c42
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCExpr.h
@@ -0,0 +1,64 @@
+//===- WebAssembly specific MC expression classes ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The MCTargetExpr subclass describes a relocatable expression with a
+// WebAssembly-specific relocation specifier.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCEXPR_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCEXPR_H
+
+#include "llvm/MC/MCExpr.h"
+
+namespace llvm {
+
+class WebAssemblyMCExpr : public MCTargetExpr {
+public:
+  enum Specifier {
+    VK_None,
+    VK_TYPEINDEX,
+    VK_TBREL,
+    VK_MBREL,
+    VK_TLSREL,
+    VK_GOT,
+    VK_GOT_TLS,
+    VK_FUNCINDEX,
+  };
+
+private:
+  const MCExpr *Expr;
+  const Specifier specifier;
+
+protected:
+  explicit WebAssemblyMCExpr(const MCExpr *Expr, Specifier S)
+      : Expr(Expr), specifier(S) {}
+
+public:
+  static const WebAssemblyMCExpr *create(const MCExpr *, Specifier,
+                                         MCContext &);
+
+  Specifier getSpecifier() const { return specifier; }
+  const MCExpr *getSubExpr() const { return Expr; }
+
+  void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
+  bool evaluateAsRelocatableImpl(MCValue &Res,
+                                 const MCAssembler *Asm) const override;
+  void visitUsedExpr(MCStreamer &Streamer) const override;
+  MCFragment *findAssociatedFragment() const override {
+    return getSubExpr()->findAssociatedFragment();
+  }
+};
+
+static inline WebAssemblyMCExpr::Specifier
+getSpecifier(const MCSymbolRefExpr *SRE) {
+  return WebAssemblyMCExpr::Specifier(SRE->getKind());
+}
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
index 7a5ebe342fccf..51fa98dacec3f 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/WebAssemblyFixupKinds.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/MC/MCAsmBackend.h"
@@ -68,33 +69,33 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(
   const MCSymbolRefExpr *RefA = Target.getSymA();
   assert(RefA);
   auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
-
-  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
-
-  switch (Modifier) {
-    case MCSymbolRefExpr::VK_GOT:
-    case MCSymbolRefExpr::VK_WASM_GOT_TLS:
-      return wasm::R_WASM_GLOBAL_INDEX_LEB;
-    case MCSymbolRefExpr::VK_WASM_TBREL:
-      assert(SymA.isFunction());
-      return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64
-                       : wasm::R_WASM_TABLE_INDEX_REL_SLEB;
-    case MCSymbolRefExpr::VK_WASM_TLSREL:
-      return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
-                       : wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
-    case MCSymbolRefExpr::VK_WASM_MBREL:
-      assert(SymA.isData());
-      return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
-                       : wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
-    case MCSymbolRefExpr::VK_WASM_TYPEINDEX:
-      return wasm::R_WASM_TYPE_INDEX_LEB;
-    case MCSymbolRefExpr::VK_None:
-      break;
-    case MCSymbolRefExpr::VK_WASM_FUNCINDEX:
-      return wasm::R_WASM_FUNCTION_INDEX_I32;
-    default:
-      report_fatal_error("unknown VariantKind");
-      break;
+  auto Spec = WebAssemblyMCExpr::Specifier(Target.getAccessVariant());
+  switch (Spec) {
+  case WebAssemblyMCExpr::VK_GOT:
+    SymA.setUsedInGOT();
+    return wasm::R_WASM_GLOBAL_INDEX_LEB;
+  case WebAssemblyMCExpr::VK_GOT_TLS:
+    SymA.setUsedInGOT();
+    SymA.setTLS();
+    return wasm::R_WASM_GLOBAL_INDEX_LEB;
+  case WebAssemblyMCExpr::VK_TBREL:
+    assert(SymA.isFunction());
+    return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64
+                     : wasm::R_WASM_TABLE_INDEX_REL_SLEB;
+  case WebAssemblyMCExpr::VK_TLSREL:
+    SymA.setTLS();
+    return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
+                     : wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
+  case WebAssemblyMCExpr::VK_MBREL:
+    assert(SymA.isData());
+    return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
+                     : wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
+  case WebAssemblyMCExpr::VK_TYPEINDEX:
+    return wasm::R_WASM_TYPE_INDEX_LEB;
+  case WebAssemblyMCExpr::VK_None:
+    break;
+  case WebAssemblyMCExpr::VK_FUNCINDEX:
+    return wasm::R_WASM_FUNCTION_INDEX_I32;
   }
 
   switch (unsigned(Fixup.getKind())) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index ded7052295ad4..c02bd623db10f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyAsmPrinter.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
 #include "TargetInfo/WebAssemblyTargetInfo.h"
@@ -590,7 +591,7 @@ void WebAssemblyAsmPrinter::EmitFunctionAttributes(Module &M) {
 
     for (auto &Sym : Symbols) {
       OutStreamer->emitValue(
-          MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_WASM_FUNCINDEX,
+          MCSymbolRefExpr::create(Sym, WebAssemblyMCExpr::VK_FUNCINDEX,
                                   OutContext),
           4);
     }
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index d78e755643fb4..7814339ef0bba 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyMCInstLower.h"
+#include "MCTargetDesc/WebAssemblyMCExpr.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "TargetInfo/WebAssemblyTargetInfo.h"
 #include "Utils/WebAssemblyTypeUtilities.h"
@@ -91,32 +92,32 @@ MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
 
 MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
                                                      MCSymbol *Sym) const {
-  MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
+  auto Spec = WebAssemblyMCExpr::VK_None;
   unsigned TargetFlags = MO.getTargetFlags();
 
   switch (TargetFlags) {
     case WebAssemblyII::MO_NO_FLAG:
       break;
     case WebAssemblyII::MO_GOT_TLS:
-      Kind = MCSymbolRefExpr::VK_WASM_GOT_TLS;
+      Spec = WebAssemblyMCExpr::VK_GOT_TLS;
       break;
     case WebAssemblyII::MO_GOT:
-      Kind = MCSymbolRefExpr::VK_GOT;
+      Spec = WebAssemblyMCExpr::VK_GOT;
       break;
     case WebAssemblyII::MO_MEMORY_BASE_REL:
-      Kind = MCSymbolRefExpr::VK_WASM_MBREL;
+      Spec = WebAssemblyMCExpr::VK_MBREL;
       break;
     case WebAssemblyII::MO_TLS_BASE_REL:
-      Kind = MCSymbolRefExpr::VK_WASM_TLSREL;
+      Spec = WebAssemblyMCExpr::VK_TLSREL;
       break;
     case WebAssemblyII::MO_TABLE_BASE_REL:
-      Kind = MCSymbolRefExpr::VK_WASM_TBREL;
+      Spec = WebAssemblyMCExpr::VK_TBREL;
       break;
     default:
       llvm_unreachable("Unknown target flag on GV operand");
   }
 
-  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Kind, Ctx);
+  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Spec, Ctx);
 
   if (MO.getOffset() != 0) {
     const auto *WasmSym = cast<MCSymbolWasm>(Sym);
@@ -149,7 +150,7 @@ MCOperand WebAssemblyMCInstLower::lowerTypeIndexOperand(
   WasmSym->setSignature(Signature);
   WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
   const MCExpr *Expr =
-      MCSymbolRefExpr::create(WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
+      MCSymbolRefExp...
[truncated]

Created using spr 1.3.5-bogner
Copy link

github-actions bot commented Mar 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@MaskRay MaskRay requested a review from aheejin April 1, 2025 03:46
Created using spr 1.3.5-bogner
MaskRay added a commit to MaskRay/llvm-project that referenced this pull request Apr 6, 2025
Move wasm-specific members outside of MCSymbolRefExpr::VariantKind (a
legacy interface I am eliminating). Most changes are mechanic and
similar to what I've done for many ELF targets (e.g. X86 llvm#132149)

Notes:

* `fixSymbolsInTLSFixups` is replaced with `setTLS` in
  `WebAssemblyWasmObjectWriter::getRelocType`, similar to what I've done
  for many ELF targets.
* `SymA->setUsedInGOT()` in `recordRelocation` is moved to
  `getRelocType`.

In the future, we should encode expressions with a relocation specifier
as WebAssemblyMCExpr and use `MCValue::RefKind` to hold the specifier of
the relocatable expression (e.g. AArch64, RISCV).
https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers

While here, rename "Modifier' to "Specifier":

> "Relocation modifier", though concise, suggests adjustments happen during the linker's relocation step rather than the assembler's expression evaluation. I landed on "relocation specifier" as the winner. It's clear, aligns with Arm and IBM’s usage, and fits the assembler's role seamlessly.

Pull Request: llvm#133116
Created using spr 1.3.5-bogner
VK_TLSREL,
VK_GOT,
VK_GOT_TLS,
VK_FUNCINDEX,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should VK_ prefix be changed? As assume the K in is for Kind which is now separate to specifier?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that we don't necessarily use VK_. For AArch64 Mach-O I've used M_.

Renamed these to S_ for (S)pecifier.

@@ -238,7 +239,7 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
auto *WasmSym = cast<MCSymbolWasm>(Sym);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
const MCExpr *Expr = MCSymbolRefExpr::create(
WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, getContext());
WasmSym, WebAssemblyMCExpr::VK_TYPEINDEX, getContext());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the VariantKind in these resulting expressions? i.e. what geKind() now return instead of the old VK_WASM_.. values?

@MaskRay MaskRay changed the title [WebAssembly] Add WebAssemblyMCExpr::Specifier [WebAssembly] Add WebAssembly::Specifier Apr 8, 2025
Created using spr 1.3.5-bogner
@MaskRay
Copy link
Member Author

MaskRay commented Apr 8, 2025

Since wasm doesn't need a MCTargetExpr yet, I think we do not need the extra .cpp file yet.
I've moved the relocation specifier constants to WebAssembly::S_ (The Expr suffix used by other targets doesn't seem useful).

Created using spr 1.3.5-bogner
@MaskRay MaskRay merged commit 50428fb into main Apr 9, 2025
11 checks passed
@MaskRay MaskRay deleted the users/MaskRay/spr/webassembly-add-webassemblymcexprspecifier branch April 9, 2025 02:44
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 9, 2025
Move wasm-specific members outside of MCSymbolRefExpr::VariantKind (a
legacy interface I am eliminating). Most changes are mechanic and
similar to what I've done for many ELF targets (e.g. X86 #132149)

Notes:

* `fixSymbolsInTLSFixups` is replaced with `setTLS` in
  `WebAssemblyWasmObjectWriter::getRelocType`, similar to what I've done
  for many ELF targets.
* `SymA->setUsedInGOT()` in `recordRelocation` is moved to
  `getRelocType`.

While here, rename "Modifier' to "Specifier":

> "Relocation modifier", though concise, suggests adjustments happen during the linker's relocation step rather than the assembler's expression evaluation. I landed on "relocation specifier" as the winner. It's clear, aligns with Arm and IBM’s usage, and fits the assembler's role seamlessly.

Pull Request: llvm/llvm-project#133116
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
Move wasm-specific members outside of MCSymbolRefExpr::VariantKind (a
legacy interface I am eliminating). Most changes are mechanic and
similar to what I've done for many ELF targets (e.g. X86 llvm#132149)

Notes:

* `fixSymbolsInTLSFixups` is replaced with `setTLS` in
  `WebAssemblyWasmObjectWriter::getRelocType`, similar to what I've done
  for many ELF targets.
* `SymA->setUsedInGOT()` in `recordRelocation` is moved to
  `getRelocType`.

While here, rename "Modifier' to "Specifier":

> "Relocation modifier", though concise, suggests adjustments happen during the linker's relocation step rather than the assembler's expression evaluation. I landed on "relocation specifier" as the winner. It's clear, aligns with Arm and IBM’s usage, and fits the assembler's role seamlessly.

Pull Request: llvm#133116
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:WebAssembly mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants