forked from OSchip/llvm-project
[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
d905c10353
commit
c9801db2eb
|
@ -26,7 +26,7 @@ class MCSymbolWasm : public MCSymbol {
|
||||||
Optional<StringRef> ExportName;
|
Optional<StringRef> ExportName;
|
||||||
wasm::WasmSignature *Signature = nullptr;
|
wasm::WasmSignature *Signature = nullptr;
|
||||||
Optional<wasm::WasmGlobalType> GlobalType;
|
Optional<wasm::WasmGlobalType> GlobalType;
|
||||||
Optional<wasm::ValType> TableType;
|
Optional<wasm::WasmTableType> TableType;
|
||||||
Optional<wasm::WasmEventType> EventType;
|
Optional<wasm::WasmEventType> EventType;
|
||||||
|
|
||||||
/// An expression describing how to calculate the size of a symbol. If a
|
/// An expression describing how to calculate the size of a symbol. If a
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
bool isFunctionTable() const {
|
bool isFunctionTable() const {
|
||||||
return isTable() && hasTableType() &&
|
return isTable() && hasTableType() &&
|
||||||
getTableType() == wasm::ValType::FUNCREF;
|
getTableType().ElemType == wasm::WASM_TYPE_FUNCREF;
|
||||||
}
|
}
|
||||||
void setFunctionTable() {
|
void setFunctionTable() {
|
||||||
setType(wasm::WASM_SYMBOL_TYPE_TABLE);
|
setType(wasm::WASM_SYMBOL_TYPE_TABLE);
|
||||||
|
@ -131,11 +131,17 @@ public:
|
||||||
void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
|
void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
|
||||||
|
|
||||||
bool hasTableType() const { return TableType.hasValue(); }
|
bool hasTableType() const { return TableType.hasValue(); }
|
||||||
wasm::ValType getTableType() const {
|
const wasm::WasmTableType &getTableType() const {
|
||||||
assert(hasTableType());
|
assert(hasTableType());
|
||||||
return TableType.getValue();
|
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 {
|
const wasm::WasmEventType &getEventType() const {
|
||||||
assert(EventType.hasValue());
|
assert(EventType.hasValue());
|
||||||
|
|
|
@ -1338,12 +1338,7 @@ void WasmObjectWriter::prepareImports(
|
||||||
Import.Module = WS.getImportModule();
|
Import.Module = WS.getImportModule();
|
||||||
Import.Field = WS.getImportName();
|
Import.Field = WS.getImportName();
|
||||||
Import.Kind = wasm::WASM_EXTERNAL_TABLE;
|
Import.Kind = wasm::WASM_EXTERNAL_TABLE;
|
||||||
wasm::ValType ElemType = WS.getTableType();
|
Import.Table = 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};
|
|
||||||
Imports.push_back(Import);
|
Imports.push_back(Import);
|
||||||
assert(WasmIndices.count(&WS) == 0);
|
assert(WasmIndices.count(&WS) == 0);
|
||||||
WasmIndices[&WS] = NumTableImports++;
|
WasmIndices[&WS] = NumTableImports++;
|
||||||
|
@ -1626,9 +1621,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
||||||
if (WS.isDefined()) {
|
if (WS.isDefined()) {
|
||||||
wasm::WasmTable Table;
|
wasm::WasmTable Table;
|
||||||
Table.Index = NumTableImports + Tables.size();
|
Table.Index = NumTableImports + Tables.size();
|
||||||
Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
|
Table.Type = WS.getTableType();
|
||||||
// FIXME: Work on custom limits is ongoing
|
|
||||||
Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
|
||||||
assert(WasmIndices.count(&WS) == 0);
|
assert(WasmIndices.count(&WS) == 0);
|
||||||
WasmIndices[&WS] = Table.Index;
|
WasmIndices[&WS] = Table.Index;
|
||||||
Tables.push_back(Table);
|
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,
|
static MCSymbolWasm *GetOrCreateFunctionTableSymbol(MCContext &Ctx,
|
||||||
const StringRef &Name) {
|
const StringRef &Name) {
|
||||||
MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
|
MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
|
||||||
|
@ -487,6 +492,28 @@ public:
|
||||||
WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
|
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) {
|
bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
|
||||||
if (STI->checkFeatures("+reference-types")) {
|
if (STI->checkFeatures("+reference-types")) {
|
||||||
// If the reference-types feature is enabled, there is an explicit table
|
// If the reference-types feature is enabled, there is an explicit table
|
||||||
|
@ -819,24 +846,31 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DirectiveID.getString() == ".tabletype") {
|
if (DirectiveID.getString() == ".tabletype") {
|
||||||
|
// .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
|
||||||
auto SymName = expectIdent();
|
auto SymName = expectIdent();
|
||||||
if (SymName.empty())
|
if (SymName.empty())
|
||||||
return true;
|
return true;
|
||||||
if (expect(AsmToken::Comma, ","))
|
if (expect(AsmToken::Comma, ","))
|
||||||
return true;
|
return true;
|
||||||
auto TypeTok = Lexer.getTok();
|
|
||||||
auto TypeName = expectIdent();
|
auto ElemTypeTok = Lexer.getTok();
|
||||||
if (TypeName.empty())
|
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;
|
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
|
// Now that we have the name and table type, we can actually create the
|
||||||
// symbol
|
// symbol
|
||||||
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
|
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
|
||||||
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
|
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);
|
TOut.emitTableType(WasmSym);
|
||||||
return expect(AsmToken::EndOfStatement, "EOL");
|
return expect(AsmToken::EndOfStatement, "EOL");
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,15 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
|
||||||
|
|
||||||
void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
|
void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
|
||||||
assert(Sym->isTable());
|
assert(Sym->isTable());
|
||||||
|
const wasm::WasmTableType &Type = Sym->getTableType();
|
||||||
OS << "\t.tabletype\t" << Sym->getName() << ", "
|
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';
|
OS << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ bar:
|
||||||
.tabletype bar, funcref
|
.tabletype bar, funcref
|
||||||
|
|
||||||
table1:
|
table1:
|
||||||
.tabletype table1, funcref
|
.tabletype table1, funcref, 42
|
||||||
table2:
|
table2:
|
||||||
.tabletype table2, funcref
|
.tabletype table2, funcref, 42, 100
|
||||||
|
|
||||||
# Table instructions
|
# Table instructions
|
||||||
|
|
||||||
|
@ -132,11 +132,13 @@ table_fill:
|
||||||
# BIN-NEXT: - Index: 2
|
# BIN-NEXT: - Index: 2
|
||||||
# BIN-NEXT: ElemType: FUNCREF
|
# BIN-NEXT: ElemType: FUNCREF
|
||||||
# BIN-NEXT: Limits:
|
# BIN-NEXT: Limits:
|
||||||
# BIN-NEXT: Minimum: 0x0
|
# BIN-NEXT: Minimum: 0x2A
|
||||||
# BIN-NEXT: - Index: 3
|
# BIN-NEXT: - Index: 3
|
||||||
# BIN-NEXT: ElemType: FUNCREF
|
# BIN-NEXT: ElemType: FUNCREF
|
||||||
# BIN-NEXT: Limits:
|
# BIN-NEXT: Limits:
|
||||||
# BIN-NEXT: Minimum: 0x0
|
# BIN-NEXT: Flags: [ HAS_MAX ]
|
||||||
|
# BIN-NEXT: Minimum: 0x2A
|
||||||
|
# BIN-NEXT: Maximum: 0x64
|
||||||
|
|
||||||
# BIN: - Type: CODE
|
# BIN: - Type: CODE
|
||||||
# BIN-NEXT: Relocations:
|
# BIN-NEXT: Relocations:
|
||||||
|
|
Loading…
Reference in New Issue