mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[WebAssembly][MC] Record limit constraints for table sizes
This commit adds a full WasmTableType to MCSymbolWasm, differing from the current situation (just an ElemType) in that it additionally records a WasmLimits. We add support for specifying the limits in .S files also, via the following syntax variations: .tabletype SYM, ELEMTYPE .tabletype SYM, ELEMTYPE, MINSIZE .tabletype SYM, ELEMTYPE, MINSIZE, MAXSIZE Depends on D99186. Differential Revision: https://reviews.llvm.org/D99191
This commit is contained in:
parent
0ac187d2cf
commit
87799a4429
@ -26,7 +26,7 @@ class MCSymbolWasm : public MCSymbol {
|
||||
Optional<StringRef> ExportName;
|
||||
wasm::WasmSignature *Signature = nullptr;
|
||||
Optional<wasm::WasmGlobalType> GlobalType;
|
||||
Optional<wasm::ValType> TableType;
|
||||
Optional<wasm::WasmTableType> TableType;
|
||||
Optional<wasm::WasmEventType> EventType;
|
||||
|
||||
/// An expression describing how to calculate the size of a symbol. If a
|
||||
@ -108,7 +108,7 @@ public:
|
||||
|
||||
bool isFunctionTable() const {
|
||||
return isTable() && hasTableType() &&
|
||||
getTableType() == wasm::ValType::FUNCREF;
|
||||
getTableType().ElemType == wasm::WASM_TYPE_FUNCREF;
|
||||
}
|
||||
void setFunctionTable() {
|
||||
setType(wasm::WASM_SYMBOL_TYPE_TABLE);
|
||||
@ -131,11 +131,17 @@ public:
|
||||
void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
|
||||
|
||||
bool hasTableType() const { return TableType.hasValue(); }
|
||||
wasm::ValType getTableType() const {
|
||||
const wasm::WasmTableType &getTableType() const {
|
||||
assert(hasTableType());
|
||||
return TableType.getValue();
|
||||
}
|
||||
void setTableType(wasm::ValType TT) { TableType = TT; }
|
||||
void setTableType(wasm::WasmTableType TT) { TableType = TT; }
|
||||
void setTableType(wasm::ValType VT) {
|
||||
// Declare a table with element type VT and no limits (min size 0, no max
|
||||
// size).
|
||||
wasm::WasmLimits Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
setTableType({uint8_t(VT), Limits});
|
||||
}
|
||||
|
||||
const wasm::WasmEventType &getEventType() const {
|
||||
assert(EventType.hasValue());
|
||||
|
@ -1338,12 +1338,7 @@ void WasmObjectWriter::prepareImports(
|
||||
Import.Module = WS.getImportModule();
|
||||
Import.Field = WS.getImportName();
|
||||
Import.Kind = wasm::WASM_EXTERNAL_TABLE;
|
||||
wasm::ValType ElemType = WS.getTableType();
|
||||
Import.Table.ElemType = uint8_t(ElemType);
|
||||
// FIXME: Extend table type to include limits? For now we don't specify
|
||||
// a min or max which does not place any restrictions on the size of the
|
||||
// imported table.
|
||||
Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
Import.Table = WS.getTableType();
|
||||
Imports.push_back(Import);
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = NumTableImports++;
|
||||
@ -1626,9 +1621,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
||||
if (WS.isDefined()) {
|
||||
wasm::WasmTable Table;
|
||||
Table.Index = NumTableImports + Tables.size();
|
||||
Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
|
||||
// FIXME: Work on custom limits is ongoing
|
||||
Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
Table.Type = WS.getTableType();
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = Table.Index;
|
||||
Tables.push_back(Table);
|
||||
|
@ -169,6 +169,11 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
|
||||
}
|
||||
};
|
||||
|
||||
// Perhaps this should go somewhere common.
|
||||
static wasm::WasmLimits DefaultLimits() {
|
||||
return {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
}
|
||||
|
||||
static MCSymbolWasm *GetOrCreateFunctionTableSymbol(MCContext &Ctx,
|
||||
const StringRef &Name) {
|
||||
MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
|
||||
@ -487,6 +492,28 @@ public:
|
||||
WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
|
||||
}
|
||||
|
||||
bool parseLimits(wasm::WasmLimits *Limits) {
|
||||
auto Tok = Lexer.getTok();
|
||||
if (!Tok.is(AsmToken::Integer))
|
||||
return error("Expected integer constant, instead got: ", Tok);
|
||||
int64_t Val = Tok.getIntVal();
|
||||
assert(Val >= 0);
|
||||
Limits->Minimum = Val;
|
||||
Parser.Lex();
|
||||
|
||||
if (isNext(AsmToken::Comma)) {
|
||||
Limits->Flags |= wasm::WASM_LIMITS_FLAG_HAS_MAX;
|
||||
auto Tok = Lexer.getTok();
|
||||
if (!Tok.is(AsmToken::Integer))
|
||||
return error("Expected integer constant, instead got: ", Tok);
|
||||
int64_t Val = Tok.getIntVal();
|
||||
assert(Val >= 0);
|
||||
Limits->Maximum = Val;
|
||||
Parser.Lex();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
|
||||
if (STI->checkFeatures("+reference-types")) {
|
||||
// If the reference-types feature is enabled, there is an explicit table
|
||||
@ -819,24 +846,31 @@ public:
|
||||
}
|
||||
|
||||
if (DirectiveID.getString() == ".tabletype") {
|
||||
// .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
|
||||
auto SymName = expectIdent();
|
||||
if (SymName.empty())
|
||||
return true;
|
||||
if (expect(AsmToken::Comma, ","))
|
||||
return true;
|
||||
auto TypeTok = Lexer.getTok();
|
||||
auto TypeName = expectIdent();
|
||||
if (TypeName.empty())
|
||||
|
||||
auto ElemTypeTok = Lexer.getTok();
|
||||
auto ElemTypeName = expectIdent();
|
||||
if (ElemTypeName.empty())
|
||||
return true;
|
||||
Optional<wasm::ValType> ElemType = parseType(ElemTypeName);
|
||||
if (!ElemType)
|
||||
return error("Unknown type in .tabletype directive: ", ElemTypeTok);
|
||||
|
||||
wasm::WasmLimits Limits = DefaultLimits();
|
||||
if (isNext(AsmToken::Comma) && parseLimits(&Limits))
|
||||
return true;
|
||||
auto Type = parseType(TypeName);
|
||||
if (!Type)
|
||||
return error("Unknown type in .tabletype directive: ", TypeTok);
|
||||
|
||||
// Now that we have the name and table type, we can actually create the
|
||||
// symbol
|
||||
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
|
||||
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
|
||||
WasmSym->setTableType(Type.getValue());
|
||||
wasm::WasmTableType Type = {uint8_t(ElemType.getValue()), Limits};
|
||||
WasmSym->setTableType(Type);
|
||||
TOut.emitTableType(WasmSym);
|
||||
return expect(AsmToken::EndOfStatement, "EOL");
|
||||
}
|
||||
|
@ -79,8 +79,15 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
|
||||
assert(Sym->isTable());
|
||||
const wasm::WasmTableType &Type = Sym->getTableType();
|
||||
OS << "\t.tabletype\t" << Sym->getName() << ", "
|
||||
<< WebAssembly::typeToString(Sym->getTableType());
|
||||
<< WebAssembly::typeToString(static_cast<wasm::ValType>(Type.ElemType));
|
||||
bool HasMaximum = Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX;
|
||||
if (Type.Limits.Minimum != 0 || HasMaximum) {
|
||||
OS << ", " << Type.Limits.Minimum;
|
||||
if (HasMaximum)
|
||||
OS << ", " << Type.Limits.Maximum;
|
||||
}
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,9 @@ bar:
|
||||
.tabletype bar, funcref
|
||||
|
||||
table1:
|
||||
.tabletype table1, funcref
|
||||
.tabletype table1, funcref, 42
|
||||
table2:
|
||||
.tabletype table2, funcref
|
||||
.tabletype table2, funcref, 42, 100
|
||||
|
||||
# Table instructions
|
||||
|
||||
@ -132,11 +132,13 @@ table_fill:
|
||||
# BIN-NEXT: - Index: 2
|
||||
# BIN-NEXT: ElemType: FUNCREF
|
||||
# BIN-NEXT: Limits:
|
||||
# BIN-NEXT: Minimum: 0x0
|
||||
# BIN-NEXT: Minimum: 0x2A
|
||||
# BIN-NEXT: - Index: 3
|
||||
# BIN-NEXT: ElemType: FUNCREF
|
||||
# BIN-NEXT: Limits:
|
||||
# BIN-NEXT: Minimum: 0x0
|
||||
# BIN-NEXT: Flags: [ HAS_MAX ]
|
||||
# BIN-NEXT: Minimum: 0x2A
|
||||
# BIN-NEXT: Maximum: 0x64
|
||||
|
||||
# BIN: - Type: CODE
|
||||
# BIN-NEXT: Relocations:
|
||||
|
Loading…
Reference in New Issue
Block a user