Skip to content

Commit 20ff8b3

Browse files
committed
[WebAssembly] Add WebAssemblyMCExpr::Specifier
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
1 parent d5893fc commit 20ff8b3

15 files changed

+143
-97
lines changed

llvm/include/llvm/MC/MCExpr.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,6 @@ class MCSymbolRefExpr : public MCExpr {
208208

209209
VK_COFF_IMGREL32, // symbol@imgrel (image-relative)
210210

211-
VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature)
212-
VK_WASM_TLSREL, // Memory address relative to __tls_base
213-
VK_WASM_MBREL, // Memory address relative to __memory_base
214-
VK_WASM_TBREL, // Table index relative to __table_base
215-
VK_WASM_GOT_TLS, // Wasm global index of TLS symbol.
216-
VK_WASM_FUNCINDEX, // Wasm function index.
217211

218212
FirstTargetSpecifier,
219213
};

llvm/include/llvm/MC/MCWasmStreamer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,8 @@ class MCWasmStreamer : public MCObjectStreamer {
6767
void finishImpl() override;
6868

6969
private:
70-
void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
7170
void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
7271

73-
void fixSymbolsInTLSFixups(const MCExpr *expr);
74-
7572
bool SeenIdent;
7673
};
7774

llvm/lib/MC/MCWasmStreamer.cpp

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -167,25 +167,13 @@ void MCWasmStreamer::emitIdent(StringRef IdentString) {
167167
// sections in the object format
168168
}
169169

170-
void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
171-
const MCSubtargetInfo &STI) {
172-
this->MCObjectStreamer::emitInstToFragment(Inst, STI);
173-
MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
174-
175-
for (auto &Fixup : F.getFixups())
176-
fixSymbolsInTLSFixups(Fixup.getValue());
177-
}
178-
179170
void MCWasmStreamer::emitInstToData(const MCInst &Inst,
180171
const MCSubtargetInfo &STI) {
181172
MCAssembler &Assembler = getAssembler();
182173
SmallVector<MCFixup, 4> Fixups;
183174
SmallString<256> Code;
184175
Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
185176

186-
for (auto &Fixup : Fixups)
187-
fixSymbolsInTLSFixups(Fixup.getValue());
188-
189177
// Append the encoded instruction to the current data fragment (or create a
190178
// new such fragment if the current fragment is not a data fragment).
191179
MCDataFragment *DF = getOrCreateDataFragment();
@@ -205,39 +193,6 @@ void MCWasmStreamer::finishImpl() {
205193
this->MCObjectStreamer::finishImpl();
206194
}
207195

208-
void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
209-
switch (expr->getKind()) {
210-
case MCExpr::Target:
211-
case MCExpr::Constant:
212-
break;
213-
214-
case MCExpr::Binary: {
215-
const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
216-
fixSymbolsInTLSFixups(be->getLHS());
217-
fixSymbolsInTLSFixups(be->getRHS());
218-
break;
219-
}
220-
221-
case MCExpr::SymbolRef: {
222-
const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
223-
switch (symRef.getKind()) {
224-
case MCSymbolRefExpr::VK_WASM_TLSREL:
225-
case MCSymbolRefExpr::VK_WASM_GOT_TLS:
226-
getAssembler().registerSymbol(symRef.getSymbol());
227-
cast<MCSymbolWasm>(symRef.getSymbol()).setTLS();
228-
break;
229-
default:
230-
break;
231-
}
232-
break;
233-
}
234-
235-
case MCExpr::Unary:
236-
fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
237-
break;
238-
}
239-
}
240-
241196
void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
242197
llvm_unreachable("Wasm doesn't support this directive");
243198
}

llvm/lib/MC/WasmObjectWriter.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -606,15 +606,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
606606
SymA->setUsedInReloc();
607607
}
608608

609-
switch (Target.getSymSpecifier()) {
610-
case MCSymbolRefExpr::VK_GOT:
611-
case MCSymbolRefExpr::VK_WASM_GOT_TLS:
612-
SymA->setUsedInGOT();
613-
break;
614-
default:
615-
break;
616-
}
617-
618609
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
619610
LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
620611

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//===----------------------------------------------------------------------===//
1515

1616
#include "AsmParser/WebAssemblyAsmTypeCheck.h"
17+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1718
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1819
#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
1920
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
@@ -701,7 +702,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
701702
WasmSym->setSignature(Signature);
702703
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
703704
const MCExpr *Expr = MCSymbolRefExpr::create(
704-
WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
705+
WasmSym, WebAssemblyMCExpr::VK_TYPEINDEX, Ctx);
705706
Operands.push_back(std::make_unique<WebAssemblyOperand>(
706707
Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
707708
}

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//===----------------------------------------------------------------------===//
1515

1616
#include "AsmParser/WebAssemblyAsmTypeCheck.h"
17+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1718
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1819
#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
1920
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
@@ -264,9 +265,9 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc,
264265
break;
265266
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
266267
case wasm::WASM_SYMBOL_TYPE_DATA:
267-
switch (SymRef->getKind()) {
268-
case MCSymbolRefExpr::VK_GOT:
269-
case MCSymbolRefExpr::VK_WASM_GOT_TLS:
268+
switch (getSpecifier(SymRef)) {
269+
case WebAssemblyMCExpr::VK_GOT:
270+
case WebAssemblyMCExpr::VK_GOT_TLS:
270271
Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
271272
return false;
272273
default:

llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
///
1515
//===----------------------------------------------------------------------===//
1616

17+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1718
#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
1819
#include "TargetInfo/WebAssemblyTargetInfo.h"
1920
#include "llvm/BinaryFormat/Wasm.h"
@@ -238,7 +239,7 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
238239
auto *WasmSym = cast<MCSymbolWasm>(Sym);
239240
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
240241
const MCExpr *Expr = MCSymbolRefExpr::create(
241-
WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, getContext());
242+
WasmSym, WebAssemblyMCExpr::VK_TYPEINDEX, getContext());
242243
MI.addOperand(MCOperand::createExpr(Expr));
243244
}
244245
break;

llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMWebAssemblyDesc
33
WebAssemblyInstPrinter.cpp
44
WebAssemblyMCAsmInfo.cpp
55
WebAssemblyMCCodeEmitter.cpp
6+
WebAssemblyMCExpr.cpp
67
WebAssemblyMCTargetDesc.cpp
78
WebAssemblyMCTypeUtilities.cpp
89
WebAssemblyTargetStreamer.cpp

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "MCTargetDesc/WebAssemblyInstPrinter.h"
15+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1516
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1617
#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
1718
#include "llvm/ADT/APFloat.h"
@@ -339,7 +340,7 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
339340
// as a signature here, such that the assembler can recover this
340341
// information.
341342
auto SRE = static_cast<const MCSymbolRefExpr *>(Op.getExpr());
342-
if (SRE->getKind() == MCSymbolRefExpr::VK_WASM_TYPEINDEX) {
343+
if (getSpecifier(SRE) == WebAssemblyMCExpr::VK_TYPEINDEX) {
343344
auto &Sym = static_cast<const MCSymbolWasm &>(SRE->getSymbol());
344345
O << WebAssembly::signatureToString(Sym.getSignature());
345346
} else {

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "WebAssemblyMCAsmInfo.h"
16+
#include "WebAssemblyMCExpr.h"
1617
#include "WebAssemblyMCTargetDesc.h"
1718
#include "llvm/MC/MCExpr.h"
1819
#include "llvm/TargetParser/Triple.h"
@@ -22,13 +23,13 @@ using namespace llvm;
2223
#define DEBUG_TYPE "wasm-mc-asm-info"
2324

2425
const MCAsmInfo::VariantKindDesc variantKindDescs[] = {
25-
{MCSymbolRefExpr::VK_WASM_TYPEINDEX, "TYPEINDEX"},
26-
{MCSymbolRefExpr::VK_WASM_TBREL, "TBREL"},
27-
{MCSymbolRefExpr::VK_WASM_MBREL, "MBREL"},
28-
{MCSymbolRefExpr::VK_WASM_TLSREL, "TLSREL"},
29-
{MCSymbolRefExpr::VK_GOT, "GOT"},
30-
{MCSymbolRefExpr::VK_WASM_GOT_TLS, "GOT@TLS"},
31-
{MCSymbolRefExpr::VK_WASM_FUNCINDEX, "FUNCINDEX"},
26+
{WebAssemblyMCExpr::VK_TYPEINDEX, "TYPEINDEX"},
27+
{WebAssemblyMCExpr::VK_TBREL, "TBREL"},
28+
{WebAssemblyMCExpr::VK_MBREL, "MBREL"},
29+
{WebAssemblyMCExpr::VK_TLSREL, "TLSREL"},
30+
{WebAssemblyMCExpr::VK_GOT, "GOT"},
31+
{WebAssemblyMCExpr::VK_GOT_TLS, "GOT@TLS"},
32+
{WebAssemblyMCExpr::VK_FUNCINDEX, "FUNCINDEX"},
3233
};
3334

3435
WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() = default; // anchor.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===- WebAssembly specific MC expression classes ---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "WebAssemblyMCExpr.h"
10+
#include "llvm/MC/MCContext.h"
11+
#include "llvm/MC/MCStreamer.h"
12+
#include "llvm/MC/MCValue.h"
13+
14+
using namespace llvm;
15+
16+
const WebAssemblyMCExpr *
17+
WebAssemblyMCExpr::create(const MCExpr *Expr, Specifier S, MCContext &Ctx) {
18+
return new (Ctx) WebAssemblyMCExpr(Expr, S);
19+
}
20+
21+
void WebAssemblyMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
22+
}
23+
24+
bool WebAssemblyMCExpr::evaluateAsRelocatableImpl(
25+
MCValue &Res, const MCAssembler *Asm) const {
26+
if (!getSubExpr()->evaluateAsRelocatable(Res, Asm))
27+
return false;
28+
Res.setSpecifier(specifier);
29+
return !Res.getSubSym();
30+
}
31+
32+
void WebAssemblyMCExpr::visitUsedExpr(MCStreamer &S) const {
33+
S.visitUsedExpr(*Expr);
34+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===- WebAssembly specific MC expression classes ---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// The MCTargetExpr subclass describes a relocatable expression with a
10+
// WebAssembly-specific relocation specifier.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCEXPR_H
15+
#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCEXPR_H
16+
17+
#include "llvm/MC/MCExpr.h"
18+
19+
namespace llvm {
20+
21+
class WebAssemblyMCExpr : public MCTargetExpr {
22+
public:
23+
enum Specifier {
24+
VK_None,
25+
VK_TYPEINDEX,
26+
VK_TBREL,
27+
VK_MBREL,
28+
VK_TLSREL,
29+
VK_GOT,
30+
VK_GOT_TLS,
31+
VK_FUNCINDEX,
32+
};
33+
34+
private:
35+
const MCExpr *Expr;
36+
const Specifier specifier;
37+
38+
protected:
39+
explicit WebAssemblyMCExpr(const MCExpr *Expr, Specifier S)
40+
: Expr(Expr), specifier(S) {}
41+
42+
public:
43+
static const WebAssemblyMCExpr *create(const MCExpr *, Specifier,
44+
MCContext &);
45+
46+
Specifier getSpecifier() const { return specifier; }
47+
const MCExpr *getSubExpr() const { return Expr; }
48+
49+
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
50+
bool evaluateAsRelocatableImpl(MCValue &Res,
51+
const MCAssembler *Asm) const override;
52+
void visitUsedExpr(MCStreamer &Streamer) const override;
53+
MCFragment *findAssociatedFragment() const override {
54+
return getSubExpr()->findAssociatedFragment();
55+
}
56+
};
57+
58+
static inline WebAssemblyMCExpr::Specifier
59+
getSpecifier(const MCSymbolRefExpr *SRE) {
60+
return WebAssemblyMCExpr::Specifier(SRE->getKind());
61+
}
62+
} // namespace llvm
63+
64+
#endif

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "MCTargetDesc/WebAssemblyFixupKinds.h"
16+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1617
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1718
#include "llvm/BinaryFormat/Wasm.h"
1819
#include "llvm/MC/MCAsmBackend.h"
@@ -66,31 +67,33 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(
6667
const MCValue &Target, const MCFixup &Fixup,
6768
const MCSectionWasm &FixupSection, bool IsLocRel) const {
6869
auto &SymA = cast<MCSymbolWasm>(*Target.getAddSym());
69-
auto Spec = Target.getSymSpecifier();
70+
auto Spec = WebAssemblyMCExpr::Specifier(Target.getSpecifier());
7071
switch (Spec) {
71-
case MCSymbolRefExpr::VK_GOT:
72-
case MCSymbolRefExpr::VK_WASM_GOT_TLS:
72+
case WebAssemblyMCExpr::VK_GOT:
73+
SymA.setUsedInGOT();
7374
return wasm::R_WASM_GLOBAL_INDEX_LEB;
74-
case MCSymbolRefExpr::VK_WASM_TBREL:
75+
case WebAssemblyMCExpr::VK_GOT_TLS:
76+
SymA.setUsedInGOT();
77+
SymA.setTLS();
78+
return wasm::R_WASM_GLOBAL_INDEX_LEB;
79+
case WebAssemblyMCExpr::VK_TBREL:
7580
assert(SymA.isFunction());
7681
return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64
7782
: wasm::R_WASM_TABLE_INDEX_REL_SLEB;
78-
case MCSymbolRefExpr::VK_WASM_TLSREL:
83+
case WebAssemblyMCExpr::VK_TLSREL:
84+
SymA.setTLS();
7985
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
8086
: wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
81-
case MCSymbolRefExpr::VK_WASM_MBREL:
87+
case WebAssemblyMCExpr::VK_MBREL:
8288
assert(SymA.isData());
8389
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
8490
: wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
85-
case MCSymbolRefExpr::VK_WASM_TYPEINDEX:
91+
case WebAssemblyMCExpr::VK_TYPEINDEX:
8692
return wasm::R_WASM_TYPE_INDEX_LEB;
87-
case MCSymbolRefExpr::VK_None:
93+
case WebAssemblyMCExpr::VK_None:
8894
break;
89-
case MCSymbolRefExpr::VK_WASM_FUNCINDEX:
95+
case WebAssemblyMCExpr::VK_FUNCINDEX:
9096
return wasm::R_WASM_FUNCTION_INDEX_I32;
91-
default:
92-
report_fatal_error("unknown VariantKind");
93-
break;
9497
}
9598

9699
switch (unsigned(Fixup.getKind())) {

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//===----------------------------------------------------------------------===//
1515

1616
#include "WebAssemblyAsmPrinter.h"
17+
#include "MCTargetDesc/WebAssemblyMCExpr.h"
1718
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1819
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
1920
#include "TargetInfo/WebAssemblyTargetInfo.h"
@@ -590,7 +591,7 @@ void WebAssemblyAsmPrinter::EmitFunctionAttributes(Module &M) {
590591

591592
for (auto &Sym : Symbols) {
592593
OutStreamer->emitValue(
593-
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_WASM_FUNCINDEX,
594+
MCSymbolRefExpr::create(Sym, WebAssemblyMCExpr::VK_FUNCINDEX,
594595
OutContext),
595596
4);
596597
}

0 commit comments

Comments
 (0)