1
0
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:
Andy Wingo 2021-03-23 16:13:54 +01:00
parent 0ac187d2cf
commit 87799a4429
5 changed files with 67 additions and 25 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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");
}

View File

@ -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';
}

View File

@ -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: