Skip to content

Commit 0d9c1b2

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. 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. 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.
1 parent 1940d78 commit 0d9c1b2

13 files changed

+155
-97
lines changed

llvm/include/llvm/MC/MCWasmStreamer.h

-3
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

-45
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/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp

+2-1
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

+4-3
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

+2-1
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

+1
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

+2-1
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

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

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

+26-27
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"
@@ -68,33 +69,31 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(
6869
const MCSymbolRefExpr *RefA = Target.getSymA();
6970
assert(RefA);
7071
auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
71-
72-
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
73-
74-
switch (Modifier) {
75-
case MCSymbolRefExpr::VK_GOT:
76-
case MCSymbolRefExpr::VK_WASM_GOT_TLS:
77-
return wasm::R_WASM_GLOBAL_INDEX_LEB;
78-
case MCSymbolRefExpr::VK_WASM_TBREL:
79-
assert(SymA.isFunction());
80-
return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64
81-
: wasm::R_WASM_TABLE_INDEX_REL_SLEB;
82-
case MCSymbolRefExpr::VK_WASM_TLSREL:
83-
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
84-
: wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
85-
case MCSymbolRefExpr::VK_WASM_MBREL:
86-
assert(SymA.isData());
87-
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
88-
: wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
89-
case MCSymbolRefExpr::VK_WASM_TYPEINDEX:
90-
return wasm::R_WASM_TYPE_INDEX_LEB;
91-
case MCSymbolRefExpr::VK_None:
92-
break;
93-
case MCSymbolRefExpr::VK_WASM_FUNCINDEX:
94-
return wasm::R_WASM_FUNCTION_INDEX_I32;
95-
default:
96-
report_fatal_error("unknown VariantKind");
97-
break;
72+
auto Spec = WebAssemblyMCExpr::Specifier(Target.getAccessVariant());
73+
switch (Spec) {
74+
case WebAssemblyMCExpr::VK_GOT:
75+
return wasm::R_WASM_GLOBAL_INDEX_LEB;
76+
case WebAssemblyMCExpr::VK_GOT_TLS:
77+
SymA.setTLS();
78+
return wasm::R_WASM_GLOBAL_INDEX_LEB;
79+
case WebAssemblyMCExpr::VK_TBREL:
80+
assert(SymA.isFunction());
81+
return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64
82+
: wasm::R_WASM_TABLE_INDEX_REL_SLEB;
83+
case WebAssemblyMCExpr::VK_TLSREL:
84+
SymA.setTLS();
85+
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64
86+
: wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
87+
case WebAssemblyMCExpr::VK_MBREL:
88+
assert(SymA.isData());
89+
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
90+
: wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
91+
case WebAssemblyMCExpr::VK_TYPEINDEX:
92+
return wasm::R_WASM_TYPE_INDEX_LEB;
93+
case WebAssemblyMCExpr::VK_None:
94+
break;
95+
case WebAssemblyMCExpr::VK_FUNCINDEX:
96+
return wasm::R_WASM_FUNCTION_INDEX_I32;
9897
}
9998

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

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

+2-1
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)