Skip to content

[memory64] Add table64 to existing memory64 support #6577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/parser/context-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ Result<> ParseDeclsCtx::addFunc(Name name,
Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
Name name,
ImportNames* importNames,
Limits limits) {
TableType type) {
auto t = std::make_unique<Table>();
t->initial = limits.initial;
t->max = limits.max ? *limits.max : Table::kUnlimitedSize;
t->indexType = type.indexType;
t->initial = type.limits.initial;
t->max = type.limits.max ? *type.limits.max : Table::kUnlimitedSize;
if (name.is()) {
if (wasm.getTableOrNull(name)) {
// TODO: if the existing table is not explicitly named, fix its name and
Expand All @@ -105,10 +106,10 @@ Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
Result<> ParseDeclsCtx::addTable(Name name,
const std::vector<Name>& exports,
ImportNames* import,
Limits limits,
TableType type,
Index pos) {
CHECK_ERR(checkImport(pos, import));
auto t = addTableDecl(pos, name, import, limits);
auto t = addTableDecl(pos, name, import, type);
CHECK_ERR(t);
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Table));
// TODO: table annotations
Expand Down Expand Up @@ -138,7 +139,7 @@ Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos,
ImportNames* importNames,
MemType type) {
auto m = std::make_unique<Memory>();
m->indexType = type.type;
m->indexType = type.indexType;
m->initial = type.limits.initial;
m->max = type.limits.max ? *type.limits.max : Memory::kUnlimitedSize;
m->shared = type.shared;
Expand Down
29 changes: 19 additions & 10 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct Limits {
};

struct MemType {
Type type;
Type indexType;
Limits limits;
bool shared;
};
Expand All @@ -56,6 +56,11 @@ struct Memarg {
uint32_t align;
};

struct TableType {
Type indexType;
Limits limits;
};

// The location, possible name, and index in the respective module index space
// of a module-level definition in the input.
struct DefPos {
Expand Down Expand Up @@ -853,7 +858,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
using LimitsT = Limits;
using ElemListT = Index;
using DataStringT = std::vector<char>;
using TableTypeT = Limits;
using TableTypeT = TableType;
using MemTypeT = MemType;

Lexer in;
Expand Down Expand Up @@ -942,7 +947,9 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {

Limits getLimitsFromElems(Index elems) { return {elems, elems}; }

Limits makeTableType(Limits limits, TypeT) { return limits; }
TableType makeTableType(Type indexType, Limits limits, TypeT) {
return {indexType, limits};
}

std::vector<char> makeDataString() { return {}; }
void appendDataString(std::vector<char>& data, std::string_view str) {
Expand All @@ -954,8 +961,8 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
return {size, size};
}

MemType makeMemType(Type type, Limits limits, bool shared) {
return {type, limits, shared};
MemType makeMemType(Type indexType, Limits limits, bool shared) {
return {indexType, limits, shared};
}

Result<TypeUseT>
Expand All @@ -975,10 +982,12 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
std::vector<Annotation>&&,
Index pos);

Result<Table*>
addTableDecl(Index pos, Name name, ImportNames* importNames, Limits limits);
Result<Table*> addTableDecl(Index pos,
Name name,
ImportNames* importNames,
TableType limits);
Result<>
addTable(Name, const std::vector<Name>&, ImportNames*, Limits, Index);
addTable(Name, const std::vector<Name>&, ImportNames*, TableType, Index);

// TODO: Record index of implicit elem for use when parsing types and instrs.
Result<> addImplicitElems(TypeT, ElemListT&& elems);
Expand Down Expand Up @@ -1252,7 +1261,7 @@ struct ParseModuleTypesCtx : TypeParserCtx<ParseModuleTypesCtx>,

LimitsT getLimitsFromElems(ElemListT) { return Ok{}; }

Type makeTableType(LimitsT, Type type) { return type; }
Type makeTableType(Type indexType, LimitsT, Type type) { return type; }

LimitsT getLimitsFromData(DataStringT) { return Ok{}; }
MemTypeT makeMemType(Type, LimitsT, bool) { return Ok{}; }
Expand Down Expand Up @@ -1441,7 +1450,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {

LimitsT getLimitsFromElems(std::vector<Expression*>& elems) { return Ok{}; }

TableTypeT makeTableType(LimitsT, Type) { return Ok{}; }
TableTypeT makeTableType(Type, LimitsT, Type) { return Ok{}; }

struct CatchInfo {
Name tag;
Expand Down
43 changes: 32 additions & 11 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ template<typename Ctx> Result<typename Ctx::MemTypeT> memtype(Ctx&);
template<typename Ctx>
Result<typename Ctx::MemTypeT> memtypeContinued(Ctx&, Type indexType);
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx&);
template<typename Ctx>
Result<typename Ctx::TableTypeT> tabletypeContinued(Ctx&, Type indexType);
template<typename Ctx> Result<typename Ctx::GlobalTypeT> globaltype(Ctx&);
template<typename Ctx> Result<uint32_t> tupleArity(Ctx&);

Expand Down Expand Up @@ -815,16 +817,28 @@ Result<typename Ctx::MemTypeT> memtypeContinued(Ctx& ctx, Type indexType) {
return ctx.makeMemType(indexType, *limits, shared);
}

// tabletype ::= limits32 reftype
// tabletype ::= (limits32 | 'i32' limits32 | 'i64' limit64) reftype
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx& ctx) {
auto limits = limits32(ctx);
Type indexType = Type::i32;
if (ctx.in.takeKeyword("i64"sv)) {
indexType = Type::i64;
} else {
ctx.in.takeKeyword("i32"sv);
}
return tabletypeContinued(ctx, indexType);
}

template<typename Ctx>
Result<typename Ctx::TableTypeT> tabletypeContinued(Ctx& ctx, Type indexType) {
auto limits = indexType == Type::i32 ? limits32(ctx) : limits64(ctx);
CHECK_ERR(limits);
auto type = reftype(ctx);
CHECK_ERR(type);

if (!type) {
return ctx.in.err("expected reftype");
}
return ctx.makeTableType(*limits, *type);
return ctx.makeTableType(indexType, *limits, *type);
}

// globaltype ::= t:valtype => const t
Expand Down Expand Up @@ -3049,8 +3063,8 @@ template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
}

// table ::= '(' 'table' id? ('(' 'export' name ')')*
// '(' 'import' mod:name nm:name ')'? tabletype ')'
// | '(' 'table' id? ('(' 'export' name ')')*
// '(' 'import' mod:name nm:name ')'? index_type? tabletype ')'
// | '(' 'table' id? ('(' 'export' name ')')* index_type?
// reftype '(' 'elem' (elemexpr* | funcidx*) ')' ')'
template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
auto pos = ctx.in.getPos();
Expand All @@ -3069,6 +3083,13 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
auto import = inlineImport(ctx.in);
CHECK_ERR(import);

auto indexType = Type::i32;
if (ctx.in.takeKeyword("i64"sv)) {
indexType = Type::i64;
} else {
ctx.in.takeKeyword("i32"sv);
}

// Reftype if we have inline elements.
auto type = reftype(ctx);
CHECK_ERR(type);
Expand Down Expand Up @@ -3103,10 +3124,10 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
if (!ctx.in.takeRParen()) {
return ctx.in.err("expected end of inline elems");
}
ttype = ctx.makeTableType(ctx.getLimitsFromElems(list), *type);
ttype = ctx.makeTableType(indexType, ctx.getLimitsFromElems(list), *type);
elems = std::move(list);
} else {
auto tabtype = tabletype(ctx);
auto tabtype = tabletypeContinued(ctx, indexType);
CHECK_ERR(tabtype);
ttype = *tabtype;
}
Expand All @@ -3124,10 +3145,10 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
return Ok{};
}

// mem ::= '(' 'memory' id? ('(' 'export' name ')')* index_type?
// ('(' 'data' b:datastring ')' | memtype) ')'
// | '(' 'memory' id? ('(' 'export' name ')')*
// '(' 'import' mod:name nm:name ')' memtype ')'
// memory ::= '(' 'memory' id? ('(' 'export' name ')')* index_type?
// ('(' 'data' b:datastring ')' | memtype) ')'
// | '(' 'memory' id? ('(' 'export' name ')')*
// '(' 'import' mod:name nm:name ')' index_type? memtype ')'
template<typename Ctx> MaybeResult<> memory(Ctx& ctx) {
auto pos = ctx.in.getPos();
if (!ctx.in.takeSExprStart("memory"sv)) {
Expand Down
3 changes: 3 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3088,6 +3088,9 @@ void PrintSExpression::printTableHeader(Table* curr) {
o << '(';
printMedium(o, "table") << ' ';
curr->name.print(o) << ' ';
if (curr->is64()) {
o << "i64 ";
}
o << curr->initial;
if (curr->hasMax()) {
o << ' ' << curr->max;
Expand Down
5 changes: 5 additions & 0 deletions src/tools/wasm-shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@ class Shell {
spectest->addExport(
builder.makeExport("table", Name::fromInt(0), ExternalKind::Table));

spectest->addTable(builder.makeTable(
Name::fromInt(1), Type(HeapType::func, Nullable), 10, 20, Type::i64));
spectest->addExport(
builder.makeExport("table64", Name::fromInt(1), ExternalKind::Table));

Memory* memory =
spectest->addMemory(builder.makeMemory(Name::fromInt(0), 1, 2));
spectest->addExport(
Expand Down
2 changes: 2 additions & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,8 @@ class WasmBinaryReader {

// gets a memory in the combined import+defined space
Memory* getMemory(Index index);
// gets a table in the combined import+defined space
Table* getTable(Index index);

void getResizableLimits(Address& initial,
Address& max,
Expand Down
12 changes: 11 additions & 1 deletion src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ class Builder {
Type type = Type(HeapType::func,
Nullable),
Address initial = 0,
Address max = Table::kMaxSize) {
Address max = Table::kMaxSize,
Type indexType = Type::i32) {
auto table = std::make_unique<Table>();
table->name = name;
table->type = type;
table->indexType = indexType;
table->initial = initial;
table->max = max;
return table;
Expand Down Expand Up @@ -658,6 +660,8 @@ class Builder {
wasm.getMemory(memoryName)->is64());
}

bool isTable64(Name tableName) { return wasm.getTable(tableName)->is64(); }

MemorySize* makeMemorySize(Name memoryName,
MemoryInfo info = MemoryInfo::Unspecified) {
auto* ret = wasm.allocator.alloc<MemorySize>();
Expand Down Expand Up @@ -729,6 +733,9 @@ class Builder {
TableSize* makeTableSize(Name table) {
auto* ret = wasm.allocator.alloc<TableSize>();
ret->table = table;
if (isTable64(table)) {
ret->type = Type::i64;
}
ret->finalize();
return ret;
}
Expand All @@ -737,6 +744,9 @@ class Builder {
ret->table = table;
ret->value = value;
ret->delta = delta;
if (isTable64(table)) {
ret->type = Type::i64;
}
ret->finalize();
return ret;
}
Expand Down
37 changes: 24 additions & 13 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3086,8 +3086,11 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
return index;
}
auto info = getTableInterfaceInfo(curr->table);
return info.interface->tableLoad(info.name,
index.getSingleValue().geti32());
auto* table = wasm.getTable(info.name);
auto address = table->indexType == Type::i64
? index.getSingleValue().geti64()
: index.getSingleValue().geti32();
return info.interface->tableLoad(info.name, address);
}
Flow visitTableSet(TableSet* curr) {
NOTE_ENTER("TableSet");
Expand All @@ -3100,17 +3103,20 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
return valueFlow;
}
auto info = getTableInterfaceInfo(curr->table);
info.interface->tableStore(info.name,
indexFlow.getSingleValue().geti32(),
valueFlow.getSingleValue());
auto* table = wasm.getTable(info.name);
auto address = table->indexType == Type::i64
? indexFlow.getSingleValue().geti64()
: indexFlow.getSingleValue().geti32();
info.interface->tableStore(info.name, address, valueFlow.getSingleValue());
return Flow();
}

Flow visitTableSize(TableSize* curr) {
NOTE_ENTER("TableSize");
auto info = getTableInterfaceInfo(curr->table);
auto* table = wasm.getTable(info.name);
Index tableSize = info.interface->tableSize(curr->table);
return Literal::makeFromInt32(tableSize, Type::i32);
return Literal::makeFromInt64(tableSize, table->indexType);
}

Flow visitTableGrow(TableGrow* curr) {
Expand All @@ -3126,16 +3132,16 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
Name tableName = curr->table;
auto info = getTableInterfaceInfo(tableName);

Index tableSize = info.interface->tableSize(tableName);
Flow ret = Literal::makeFromInt32(tableSize, Type::i32);
Flow fail = Literal::makeFromInt32(-1, Type::i32);
Index tableSize = info.interface->tableSize(info.name);
auto* table = self()->wasm.getTable(info.name);
Flow ret = Literal::makeFromInt64(tableSize, table->indexType);
Flow fail = Literal::makeFromInt64(-1, table->indexType);
Index delta = deltaFlow.getSingleValue().geti32();

if (tableSize >= uint32_t(-1) - delta) {
return fail;
}
auto maxTableSize = self()->wasm.getTable(tableName)->max;
if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(maxTableSize)) {
if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(table->max)) {
return fail;
}
Index newSize = tableSize + delta;
Expand Down Expand Up @@ -3168,9 +3174,14 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
Name tableName = curr->table;
auto info = getTableInterfaceInfo(tableName);

Index dest = destFlow.getSingleValue().geti32();
auto* table = self()->wasm.getTable(info.name);
Index dest = table->indexType == Type::i64
? destFlow.getSingleValue().geti64()
: destFlow.getSingleValue().geti32();
Literal value = valueFlow.getSingleValue();
Index size = sizeFlow.getSingleValue().geti32();
Index size = table->indexType == Type::i64
? sizeFlow.getSingleValue().geti64()
: sizeFlow.getSingleValue().geti32();

Index tableSize = info.interface->tableSize(tableName);
if (dest + size > tableSize) {
Expand Down
2 changes: 2 additions & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2276,9 +2276,11 @@ class Table : public Importable {

Address initial = 0;
Address max = kMaxSize;
Type indexType = Type::i32;
Type type = Type(HeapType::func, Nullable);

bool hasMax() { return max != kUnlimitedSize; }
bool is64() { return indexType == Type::i64; }
void clear() {
name = "";
initial = 0;
Expand Down
Loading
Loading