[llvm] [MC][WebAssembly] Add parameter to set table address type (PR #173063)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 19 09:56:39 PST 2025
https://github.com/daxpedda created https://github.com/llvm/llvm-project/pull/173063
This adds an extra optional parameters to `.tabletype` to set the tables address type.
Unfortunately, to not break any existing code, I had to add an optional parameter that can be skipped in favor of subsequent optional parameters. This is a bit messed up, so I'm all ears for alternatives.
Fixes: https://github.com/llvm/llvm-project/issues/172907
>From e34b30a6438ba1937f8c4dc03c159bffef23fc5e Mon Sep 17 00:00:00 2001
From: daxpedda <daxpedda at gmail.com>
Date: Fri, 19 Dec 2025 18:48:27 +0100
Subject: [PATCH] [MC][WebAssembly] Add parameter to set table address type
---
.../AsmParser/WebAssemblyAsmParser.cpp | 27 ++++++-
.../AsmParser/WebAssemblyAsmTypeCheck.cpp | 48 ++++++++----
.../AsmParser/WebAssemblyAsmTypeCheck.h | 3 +-
.../WebAssemblyTargetStreamer.cpp | 4 +
llvm/test/MC/WebAssembly/wasm64.s | 75 +++++++++++++++----
5 files changed, 122 insertions(+), 35 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 9175b2731dac0..28ea6e5ed5155 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -958,7 +958,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
}
if (DirectiveID.getString() == ".tabletype") {
- // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
+ // .tabletype SYM, ELEMTYPE[, ADDR_TYPE[, MINSIZE[, MAXSIZE]]]
auto SymName = expectIdent();
if (SymName.empty())
return ParseStatus::Failure;
@@ -975,6 +975,28 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
return error("Unknown type in .tabletype directive: ", ElemTypeTok);
wasm::WasmLimits Limits = defaultLimits();
+
+ if (Is64) {
+ Limits.Flags |= wasm::WASM_LIMITS_FLAG_IS_64;
+ }
+
+ auto NextTok = Lexer.peekTok();
+
+ if (Lexer.is(AsmToken::Comma) && !NextTok.is(AsmToken::Integer)) {
+ auto AddrType = Lexer.Lex().getString();
+ Parser.Lex();
+
+ if (AddrType == "i32")
+ Limits.Flags &= ~wasm::WASM_LIMITS_FLAG_IS_64;
+ else if (AddrType == "i64")
+ Limits.Flags |= wasm::WASM_LIMITS_FLAG_IS_64;
+ else
+ return error(std::string(
+ "Expected address type or integer constant, instead got: ",
+ Lexer.getTok()));
+ ;
+ }
+
if (isNext(AsmToken::Comma) && parseLimits(&Limits))
return ParseStatus::Failure;
@@ -983,9 +1005,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
auto *WasmSym =
static_cast<MCSymbolWasm *>(Ctx.getOrCreateSymbol(SymName));
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
- if (Is64) {
- Limits.Flags |= wasm::WASM_LIMITS_FLAG_IS_64;
- }
wasm::WasmTableType Type = {*ElemType, Limits};
WasmSym->setTableType(Type);
TOut.emitTableType(WasmSym);
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
index 694388869040a..e8899ee8ee000 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
@@ -282,7 +282,8 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc,
}
bool WebAssemblyAsmTypeCheck::getTable(SMLoc ErrorLoc, const MCOperand &TableOp,
- wasm::ValType &Type) {
+ wasm::ValType &Type,
+ wasm::ValType &AddrType) {
const MCSymbolRefExpr *SymRef;
if (getSymRef(ErrorLoc, TableOp, SymRef))
return true;
@@ -291,7 +292,12 @@ bool WebAssemblyAsmTypeCheck::getTable(SMLoc ErrorLoc, const MCOperand &TableOp,
wasm::WASM_SYMBOL_TYPE_TABLE)
return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
": missing .tabletype");
- Type = static_cast<wasm::ValType>(WasmSym->getTableType().ElemType);
+ auto Table = WasmSym->getTableType();
+ Type = static_cast<wasm::ValType>(Table.ElemType);
+ if (Table.Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
+ AddrType = wasm::ValType::I64;
+ else
+ AddrType = wasm::ValType::I32;
return false;
}
@@ -396,6 +402,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
auto Name = getMnemonic(Opc);
dumpTypeStack("typechecking " + Name + ": ");
wasm::ValType Type;
+ wasm::ValType AddrType;
if (Name == "local.get") {
if (!getLocal(Operands[1]->getStartLoc(), Inst.getOperand(0), Type)) {
@@ -441,61 +448,70 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
}
if (Name == "table.get") {
- bool Error = popType(ErrorLoc, wasm::ValType::I32);
- if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type)) {
+ if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type,
+ AddrType)) {
+ bool Error = popType(ErrorLoc, AddrType);
pushType(Type);
return Error;
+ } else {
+ popType(ErrorLoc, Any{});
+ pushType(Any{});
+ return true;
}
- pushType(Any{});
- return true;
}
if (Name == "table.set") {
bool Error = false;
SmallVector<StackType, 2> PopTypes;
- PopTypes.push_back(wasm::ValType::I32);
- if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type)) {
+ if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type,
+ AddrType)) {
+ PopTypes.push_back(AddrType);
PopTypes.push_back(Type);
} else {
Error = true;
PopTypes.push_back(Any{});
+ PopTypes.push_back(Any{});
}
Error |= popTypes(ErrorLoc, PopTypes);
return Error;
}
if (Name == "table.size") {
- bool Error = getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type);
- pushType(wasm::ValType::I32);
+ bool Error = getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type,
+ AddrType);
+ pushType(AddrType);
return Error;
}
if (Name == "table.grow") {
bool Error = false;
SmallVector<StackType, 2> PopTypes;
- if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type)) {
+ if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type,
+ AddrType)) {
PopTypes.push_back(Type);
} else {
Error = true;
PopTypes.push_back(Any{});
}
- PopTypes.push_back(wasm::ValType::I32);
+ PopTypes.push_back(AddrType);
Error |= popTypes(ErrorLoc, PopTypes);
- pushType(wasm::ValType::I32);
+ pushType(AddrType);
return Error;
}
if (Name == "table.fill") {
bool Error = false;
SmallVector<StackType, 2> PopTypes;
- PopTypes.push_back(wasm::ValType::I32);
- if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type)) {
+ if (!getTable(Operands[1]->getStartLoc(), Inst.getOperand(0), Type,
+ AddrType)) {
+ PopTypes.push_back(AddrType);
PopTypes.push_back(Type);
} else {
Error = true;
PopTypes.push_back(Any{});
+ PopTypes.push_back(Any{});
}
- PopTypes.push_back(wasm::ValType::I32);
+ PopTypes.push_back(AddrType);
Error |= popTypes(ErrorLoc, PopTypes);
return Error;
}
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
index e6fddf9806026..22b6ea14d4a39 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
@@ -79,7 +79,8 @@ class WebAssemblyAsmTypeCheck final {
const MCSymbolRefExpr *&SymRef);
bool getGlobal(SMLoc ErrorLoc, const MCOperand &GlobalOp,
wasm::ValType &Type);
- bool getTable(SMLoc ErrorLoc, const MCOperand &TableOp, wasm::ValType &Type);
+ bool getTable(SMLoc ErrorLoc, const MCOperand &TableOp, wasm::ValType &Type,
+ wasm::ValType &AddrType);
bool getSignature(SMLoc ErrorLoc, const MCOperand &SigOp,
wasm::WasmSymbolType Type, const wasm::WasmSignature *&Sig);
bool checkTryTable(SMLoc ErrorLoc, const MCInst &Inst);
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
index c18de5fc1939e..9f9ffca4eddf9 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
@@ -78,6 +78,10 @@ void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
const wasm::WasmTableType &Type = Sym->getTableType();
OS << "\t.tabletype\t" << Sym->getName() << ", "
<< WebAssembly::typeToString(static_cast<wasm::ValType>(Type.ElemType));
+ if (Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
+ OS << ", i64";
+ else
+ OS << ", i32";
bool HasMaximum = Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX;
if (Type.Limits.Minimum != 0 || HasMaximum) {
OS << ", " << Type.Limits.Minimum;
diff --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s
index 0c939b47db4f2..2617043f0a764 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -1,11 +1,16 @@
-# RUN: llvm-mc -triple=wasm64-unknown-unknown -mattr=+atomics,+simd128,+nontrapping-fptoint,+exception-handling < %s | FileCheck %s
-# RUN: llvm-mc -triple=wasm64-unknown-unknown -filetype=obj -mattr=+atomics,+simd128,+nontrapping-fptoint,+exception-handling -o - < %s | obj2yaml | FileCheck %s -check-prefix=BIN
+# RUN: llvm-mc -triple=wasm64-unknown-unknown -mattr=+atomics,+reference-types,+simd128,+nontrapping-fptoint,+exception-handling < %s | FileCheck %s -dump-input=always
+# RUN: llvm-mc -triple=wasm64-unknown-unknown -filetype=obj -mattr=+atomics,+reference-types,+simd128,+nontrapping-fptoint,+exception-handling -o - < %s | obj2yaml | FileCheck %s -check-prefix=BIN -dump-input=always
# Most of our other tests are for wasm32, this one adds some wasm64 specific tests.
.globaltype myglob64, i64
.globaltype __stack_pointer, i64
+table1:
+ .tabletype table1, funcref, i32
+table2:
+ .tabletype table2, funcref, i64
+
test:
.functype test (i64) -> ()
.local i64
@@ -59,6 +64,18 @@ test:
global.get __stack_pointer
drop
+ ### table address type
+
+ ref.null_func
+ i32.const 0
+ table.grow table1
+ drop
+
+ ref.null_func
+ i64.const 0
+ table.grow table2
+ drop
+
end_function
.section .rodata..L.str,"",@
@@ -72,6 +89,9 @@ test:
# CHECK: .globaltype myglob64, i64
+# CHECK: .tabletype table1, funcref, i32
+# CHECK: .tabletype table2, funcref, i64
+
# CHECK: .functype test (i64) -> ()
# CHECK-NEXT: .local i64
@@ -159,41 +179,58 @@ test:
# BIN-NEXT: GlobalMutable: true
# BIN-NEXT: - Type: FUNCTION
# BIN-NEXT: FunctionTypes: [ 0 ]
+# BIN-NEXT: - Type: TABLE
+# BIN-NEXT: Tables:
+# BIN-NEXT: - Index: 0
+# BIN-NEXT: ElemType: FUNCREF
+# BIN-NEXT: Limits:
+# BIN-NEXT: Minimum: 0x0
+# BIN-NEXT: - Index: 1
+# BIN-NEXT: ElemType: FUNCREF
+# BIN-NEXT: Limits:
+# BIN-NEXT: Flags: [ IS_64 ]
+# BIN-NEXT: Minimum: 0x0
# BIN-NEXT: - Type: DATACOUNT
# BIN-NEXT: Count: 1
# BIN-NEXT: - Type: CODE
# BIN-NEXT: Relocations:
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB64
-# BIN-NEXT: Index: 1
+# BIN-NEXT: Index: 3
# BIN-NEXT: Offset: 0x13
# BIN-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
-# BIN-NEXT: Index: 2
+# BIN-NEXT: Index: 4
# BIN-NEXT: Offset: 0x22
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB64
-# BIN-NEXT: Index: 1
+# BIN-NEXT: Index: 3
# BIN-NEXT: Offset: 0x2F
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB64
-# BIN-NEXT: Index: 1
+# BIN-NEXT: Index: 3
# BIN-NEXT: Offset: 0x4F
# BIN-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
-# BIN-NEXT: Index: 2
+# BIN-NEXT: Index: 4
# BIN-NEXT: Offset: 0x62
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB64
-# BIN-NEXT: Index: 1
+# BIN-NEXT: Index: 3
# BIN-NEXT: Offset: 0x78
# BIN-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
-# BIN-NEXT: Index: 3
+# BIN-NEXT: Index: 5
# BIN-NEXT: Offset: 0x83
+# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB
+# BIN-NEXT: Index: 0
+# BIN-NEXT: Offset: 0x8F
+# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB
+# BIN-NEXT: Index: 1
+# BIN-NEXT: Offset: 0x9B
# BIN-NEXT: Functions:
# BIN-NEXT: - Index: 0
# BIN-NEXT: Locals:
# BIN-NEXT: - Type: I64
# BIN-NEXT: Count: 1
-# BIN-NEXT: Body: 42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4200430000000038020020004300000000380200428080808080808080800043000000003802002380808080004300000000380200420043000000003802808080808080808080002381808080001A0B
+# BIN-NEXT: Body: 42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4200430000000038020020004300000000380200428080808080808080800043000000003802002380808080004300000000380200420043000000003802808080808080808080002381808080001AD0704100FC0F80808080001AD0704200FC0F81808080001A0B
# BIN-NEXT: - Type: DATA
# BIN-NEXT: Relocations:
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_I64
-# BIN-NEXT: Index: 1
+# BIN-NEXT: Index: 3
# BIN-NEXT: Offset: 0x16
# BIN-NEXT: Segments:
# BIN-NEXT: - SectionOffset: 6
@@ -207,22 +244,32 @@ test:
# BIN-NEXT: Version: 2
# BIN-NEXT: SymbolTable:
# BIN-NEXT: - Index: 0
+# BIN-NEXT: Kind: TABLE
+# BIN-NEXT: Name: table1
+# BIN-NEXT: Flags: [ BINDING_LOCAL ]
+# BIN-NEXT: Table: 0
+# BIN-NEXT: - Index: 1
+# BIN-NEXT: Kind: TABLE
+# BIN-NEXT: Name: table2
+# BIN-NEXT: Flags: [ BINDING_LOCAL ]
+# BIN-NEXT: Table: 1
+# BIN-NEXT: - Index: 2
# BIN-NEXT: Kind: FUNCTION
# BIN-NEXT: Name: test
# BIN-NEXT: Flags: [ BINDING_LOCAL ]
# BIN-NEXT: Function: 0
-# BIN-NEXT: - Index: 1
+# BIN-NEXT: - Index: 3
# BIN-NEXT: Kind: DATA
# BIN-NEXT: Name: .L.str
# BIN-NEXT: Flags: [ BINDING_LOCAL, VISIBILITY_HIDDEN ]
# BIN-NEXT: Segment: 0
# BIN-NEXT: Size: 24
-# BIN-NEXT: - Index: 2
+# BIN-NEXT: - Index: 4
# BIN-NEXT: Kind: GLOBAL
# BIN-NEXT: Name: myglob64
# BIN-NEXT: Flags: [ UNDEFINED ]
# BIN-NEXT: Global: 0
-# BIN-NEXT: - Index: 3
+# BIN-NEXT: - Index: 5
# BIN-NEXT: Kind: GLOBAL
# BIN-NEXT: Name: __stack_pointer
# BIN-NEXT: Flags: [ UNDEFINED ]
More information about the llvm-commits
mailing list