Skip to content

Commit 4176755

Browse files
committed
[memory64] Add table64 to existing memory64 support
Tests is still very limited. Hopefully we can use the upstream spec tests soon and avoid having to write our own tests for `.set/.set/.fill/etc`. See WebAssembly/memory64#51
1 parent 9975b56 commit 4176755

16 files changed

+375
-179
lines changed

src/parser/context-decls.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,11 @@ Result<> ParseDeclsCtx::addFunc(Name name,
8282
Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
8383
Name name,
8484
ImportNames* importNames,
85-
Limits limits) {
85+
TableType type) {
8686
auto t = std::make_unique<Table>();
87-
t->initial = limits.initial;
88-
t->max = limits.max ? *limits.max : Table::kUnlimitedSize;
87+
t->indexType = type.indexType;
88+
t->initial = type.limits.initial;
89+
t->max = type.limits.max ? *type.limits.max : Table::kUnlimitedSize;
8990
if (name.is()) {
9091
if (wasm.getTableOrNull(name)) {
9192
// TODO: if the existing table is not explicitly named, fix its name and
@@ -105,10 +106,10 @@ Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
105106
Result<> ParseDeclsCtx::addTable(Name name,
106107
const std::vector<Name>& exports,
107108
ImportNames* import,
108-
Limits limits,
109+
TableType type,
109110
Index pos) {
110111
CHECK_ERR(checkImport(pos, import));
111-
auto t = addTableDecl(pos, name, import, limits);
112+
auto t = addTableDecl(pos, name, import, type);
112113
CHECK_ERR(t);
113114
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Table));
114115
// TODO: table annotations
@@ -138,7 +139,7 @@ Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos,
138139
ImportNames* importNames,
139140
MemType type) {
140141
auto m = std::make_unique<Memory>();
141-
m->indexType = type.type;
142+
m->indexType = type.indexType;
142143
m->initial = type.limits.initial;
143144
m->max = type.limits.max ? *type.limits.max : Memory::kUnlimitedSize;
144145
m->shared = type.shared;

src/parser/contexts.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct Limits {
4646
};
4747

4848
struct MemType {
49-
Type type;
49+
Type indexType;
5050
Limits limits;
5151
bool shared;
5252
};
@@ -56,6 +56,11 @@ struct Memarg {
5656
uint32_t align;
5757
};
5858

59+
struct TableType {
60+
Type indexType;
61+
Limits limits;
62+
};
63+
5964
// The location, possible name, and index in the respective module index space
6065
// of a module-level definition in the input.
6166
struct DefPos {
@@ -853,7 +858,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
853858
using LimitsT = Limits;
854859
using ElemListT = Index;
855860
using DataStringT = std::vector<char>;
856-
using TableTypeT = Limits;
861+
using TableTypeT = TableType;
857862
using MemTypeT = MemType;
858863

859864
Lexer in;
@@ -942,7 +947,9 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
942947

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

945-
Limits makeTableType(Limits limits, TypeT) { return limits; }
950+
TableType makeTableType(Type indexType, Limits limits, TypeT) {
951+
return {indexType, limits};
952+
}
946953

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

957-
MemType makeMemType(Type type, Limits limits, bool shared) {
958-
return {type, limits, shared};
964+
MemType makeMemType(Type indexType, Limits limits, bool shared) {
965+
return {indexType, limits, shared};
959966
}
960967

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

978-
Result<Table*>
979-
addTableDecl(Index pos, Name name, ImportNames* importNames, Limits limits);
985+
Result<Table*> addTableDecl(Index pos,
986+
Name name,
987+
ImportNames* importNames,
988+
TableType limits);
980989
Result<>
981-
addTable(Name, const std::vector<Name>&, ImportNames*, Limits, Index);
990+
addTable(Name, const std::vector<Name>&, ImportNames*, TableType, Index);
982991

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

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

1255-
Type makeTableType(LimitsT, Type type) { return type; }
1264+
Type makeTableType(Type indexType, LimitsT, Type type) { return type; }
12561265

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

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

1444-
TableTypeT makeTableType(LimitsT, Type) { return Ok{}; }
1453+
TableTypeT makeTableType(Type, LimitsT, Type) { return Ok{}; }
14451454

14461455
struct CatchInfo {
14471456
Name tag;

src/parser/parsers.h

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ template<typename Ctx> Result<typename Ctx::MemTypeT> memtype(Ctx&);
4444
template<typename Ctx>
4545
Result<typename Ctx::MemTypeT> memtypeContinued(Ctx&, Type indexType);
4646
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx&);
47+
template<typename Ctx>
48+
Result<typename Ctx::TableTypeT> tabletypeContinued(Ctx&, Type indexType);
4749
template<typename Ctx> Result<typename Ctx::GlobalTypeT> globaltype(Ctx&);
4850
template<typename Ctx> Result<uint32_t> tupleArity(Ctx&);
4951

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

818-
// tabletype ::= limits32 reftype
820+
// tabletype ::= (limits32 | 'i32' limits32 | 'i64' limit64) reftype
819821
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx& ctx) {
820-
auto limits = limits32(ctx);
822+
Type indexType = Type::i32;
823+
if (ctx.in.takeKeyword("i64"sv)) {
824+
indexType = Type::i64;
825+
} else {
826+
ctx.in.takeKeyword("i32"sv);
827+
}
828+
return tabletypeContinued(ctx, indexType);
829+
}
830+
831+
template<typename Ctx>
832+
Result<typename Ctx::TableTypeT> tabletypeContinued(Ctx& ctx, Type indexType) {
833+
auto limits = indexType == Type::i32 ? limits32(ctx) : limits64(ctx);
821834
CHECK_ERR(limits);
822835
auto type = reftype(ctx);
823836
CHECK_ERR(type);
837+
824838
if (!type) {
825839
return ctx.in.err("expected reftype");
826840
}
827-
return ctx.makeTableType(*limits, *type);
841+
return ctx.makeTableType(indexType, *limits, *type);
828842
}
829843

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

30513065
// table ::= '(' 'table' id? ('(' 'export' name ')')*
3052-
// '(' 'import' mod:name nm:name ')'? tabletype ')'
3053-
// | '(' 'table' id? ('(' 'export' name ')')*
3066+
// '(' 'import' mod:name nm:name ')'? index_type? tabletype ')'
3067+
// | '(' 'table' id? ('(' 'export' name ')')* index_type?
30543068
// reftype '(' 'elem' (elemexpr* | funcidx*) ')' ')'
30553069
template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
30563070
auto pos = ctx.in.getPos();
@@ -3069,6 +3083,13 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
30693083
auto import = inlineImport(ctx.in);
30703084
CHECK_ERR(import);
30713085

3086+
auto indexType = Type::i32;
3087+
if (ctx.in.takeKeyword("i64"sv)) {
3088+
indexType = Type::i64;
3089+
} else {
3090+
ctx.in.takeKeyword("i32"sv);
3091+
}
3092+
30723093
// Reftype if we have inline elements.
30733094
auto type = reftype(ctx);
30743095
CHECK_ERR(type);
@@ -3103,10 +3124,10 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
31033124
if (!ctx.in.takeRParen()) {
31043125
return ctx.in.err("expected end of inline elems");
31053126
}
3106-
ttype = ctx.makeTableType(ctx.getLimitsFromElems(list), *type);
3127+
ttype = ctx.makeTableType(indexType, ctx.getLimitsFromElems(list), *type);
31073128
elems = std::move(list);
31083129
} else {
3109-
auto tabtype = tabletype(ctx);
3130+
auto tabtype = tabletypeContinued(ctx, indexType);
31103131
CHECK_ERR(tabtype);
31113132
ttype = *tabtype;
31123133
}
@@ -3124,10 +3145,10 @@ template<typename Ctx> MaybeResult<> table(Ctx& ctx) {
31243145
return Ok{};
31253146
}
31263147

3127-
// mem ::= '(' 'memory' id? ('(' 'export' name ')')* index_type?
3128-
// ('(' 'data' b:datastring ')' | memtype) ')'
3129-
// | '(' 'memory' id? ('(' 'export' name ')')*
3130-
// '(' 'import' mod:name nm:name ')' memtype ')'
3148+
// memory ::= '(' 'memory' id? ('(' 'export' name ')')* index_type?
3149+
// ('(' 'data' b:datastring ')' | memtype) ')'
3150+
// | '(' 'memory' id? ('(' 'export' name ')')*
3151+
// '(' 'import' mod:name nm:name ')' index_type? memtype ')'
31313152
template<typename Ctx> MaybeResult<> memory(Ctx& ctx) {
31323153
auto pos = ctx.in.getPos();
31333154
if (!ctx.in.takeSExprStart("memory"sv)) {

src/passes/Print.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3088,6 +3088,9 @@ void PrintSExpression::printTableHeader(Table* curr) {
30883088
o << '(';
30893089
printMedium(o, "table") << ' ';
30903090
curr->name.print(o) << ' ';
3091+
if (curr->is64()) {
3092+
o << "i64 ";
3093+
}
30913094
o << curr->initial;
30923095
if (curr->hasMax()) {
30933096
o << ' ' << curr->max;

src/tools/wasm-shell.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,11 @@ class Shell {
378378
spectest->addExport(
379379
builder.makeExport("table", Name::fromInt(0), ExternalKind::Table));
380380

381+
spectest->addTable(builder.makeTable(
382+
Name::fromInt(1), Type(HeapType::func, Nullable), 10, 20, Type::i64));
383+
spectest->addExport(
384+
builder.makeExport("table64", Name::fromInt(1), ExternalKind::Table));
385+
381386
Memory* memory =
382387
spectest->addMemory(builder.makeMemory(Name::fromInt(0), 1, 2));
383388
spectest->addExport(

src/wasm-binary.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,8 @@ class WasmBinaryReader {
15521552

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

15561558
void getResizableLimits(Address& initial,
15571559
Address& max,

src/wasm-builder.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ class Builder {
8686
Type type = Type(HeapType::func,
8787
Nullable),
8888
Address initial = 0,
89-
Address max = Table::kMaxSize) {
89+
Address max = Table::kMaxSize,
90+
Type indexType = Type::i32) {
9091
auto table = std::make_unique<Table>();
9192
table->name = name;
9293
table->type = type;
94+
table->indexType = indexType;
9395
table->initial = initial;
9496
table->max = max;
9597
return table;
@@ -658,6 +660,8 @@ class Builder {
658660
wasm.getMemory(memoryName)->is64());
659661
}
660662

663+
bool isTable64(Name tableName) { return wasm.getTable(tableName)->is64(); }
664+
661665
MemorySize* makeMemorySize(Name memoryName,
662666
MemoryInfo info = MemoryInfo::Unspecified) {
663667
auto* ret = wasm.allocator.alloc<MemorySize>();
@@ -729,6 +733,9 @@ class Builder {
729733
TableSize* makeTableSize(Name table) {
730734
auto* ret = wasm.allocator.alloc<TableSize>();
731735
ret->table = table;
736+
if (isTable64(table)) {
737+
ret->type = Type::i64;
738+
}
732739
ret->finalize();
733740
return ret;
734741
}
@@ -737,6 +744,9 @@ class Builder {
737744
ret->table = table;
738745
ret->value = value;
739746
ret->delta = delta;
747+
if (isTable64(table)) {
748+
ret->type = Type::i64;
749+
}
740750
ret->finalize();
741751
return ret;
742752
}

src/wasm-interpreter.h

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,8 +3086,11 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
30863086
return index;
30873087
}
30883088
auto info = getTableInterfaceInfo(curr->table);
3089-
return info.interface->tableLoad(info.name,
3090-
index.getSingleValue().geti32());
3089+
auto* table = wasm.getTable(info.name);
3090+
auto address = table->indexType == Type::i64
3091+
? index.getSingleValue().geti64()
3092+
: index.getSingleValue().geti32();
3093+
return info.interface->tableLoad(info.name, address);
30913094
}
30923095
Flow visitTableSet(TableSet* curr) {
30933096
NOTE_ENTER("TableSet");
@@ -3100,17 +3103,20 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
31003103
return valueFlow;
31013104
}
31023105
auto info = getTableInterfaceInfo(curr->table);
3103-
info.interface->tableStore(info.name,
3104-
indexFlow.getSingleValue().geti32(),
3105-
valueFlow.getSingleValue());
3106+
auto* table = wasm.getTable(info.name);
3107+
auto address = table->indexType == Type::i64
3108+
? indexFlow.getSingleValue().geti64()
3109+
: indexFlow.getSingleValue().geti32();
3110+
info.interface->tableStore(info.name, address, valueFlow.getSingleValue());
31063111
return Flow();
31073112
}
31083113

31093114
Flow visitTableSize(TableSize* curr) {
31103115
NOTE_ENTER("TableSize");
31113116
auto info = getTableInterfaceInfo(curr->table);
3117+
auto* table = wasm.getTable(info.name);
31123118
Index tableSize = info.interface->tableSize(curr->table);
3113-
return Literal::makeFromInt32(tableSize, Type::i32);
3119+
return Literal::makeFromInt64(tableSize, table->indexType);
31143120
}
31153121

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

3129-
Index tableSize = info.interface->tableSize(tableName);
3130-
Flow ret = Literal::makeFromInt32(tableSize, Type::i32);
3131-
Flow fail = Literal::makeFromInt32(-1, Type::i32);
3135+
Index tableSize = info.interface->tableSize(info.name);
3136+
auto* table = self()->wasm.getTable(info.name);
3137+
Flow ret = Literal::makeFromInt64(tableSize, table->indexType);
3138+
Flow fail = Literal::makeFromInt64(-1, table->indexType);
31323139
Index delta = deltaFlow.getSingleValue().geti32();
31333140

31343141
if (tableSize >= uint32_t(-1) - delta) {
31353142
return fail;
31363143
}
3137-
auto maxTableSize = self()->wasm.getTable(tableName)->max;
3138-
if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(maxTableSize)) {
3144+
if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(table->max)) {
31393145
return fail;
31403146
}
31413147
Index newSize = tableSize + delta;
@@ -3168,9 +3174,14 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
31683174
Name tableName = curr->table;
31693175
auto info = getTableInterfaceInfo(tableName);
31703176

3171-
Index dest = destFlow.getSingleValue().geti32();
3177+
auto* table = self()->wasm.getTable(info.name);
3178+
Index dest = table->indexType == Type::i64
3179+
? destFlow.getSingleValue().geti64()
3180+
: destFlow.getSingleValue().geti32();
31723181
Literal value = valueFlow.getSingleValue();
3173-
Index size = sizeFlow.getSingleValue().geti32();
3182+
Index size = table->indexType == Type::i64
3183+
? sizeFlow.getSingleValue().geti64()
3184+
: sizeFlow.getSingleValue().geti32();
31743185

31753186
Index tableSize = info.interface->tableSize(tableName);
31763187
if (dest + size > tableSize) {

src/wasm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,9 +2276,11 @@ class Table : public Importable {
22762276

22772277
Address initial = 0;
22782278
Address max = kMaxSize;
2279+
Type indexType = Type::i32;
22792280
Type type = Type(HeapType::func, Nullable);
22802281

22812282
bool hasMax() { return max != kUnlimitedSize; }
2283+
bool is64() { return indexType == Type::i64; }
22822284
void clear() {
22832285
name = "";
22842286
initial = 0;

0 commit comments

Comments
 (0)