summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parser/context-decls.cpp13
-rw-r--r--src/parser/contexts.h29
-rw-r--r--src/parser/parsers.h43
-rw-r--r--src/passes/Print.cpp3
-rw-r--r--src/tools/wasm-shell.cpp5
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-builder.h12
-rw-r--r--src/wasm-interpreter.h37
-rw-r--r--src/wasm.h2
-rw-r--r--src/wasm/wasm-binary.cpp33
-rw-r--r--src/wasm/wasm-validator.cpp72
11 files changed, 172 insertions, 79 deletions
diff --git a/src/parser/context-decls.cpp b/src/parser/context-decls.cpp
index c78c47d60..c5b212038 100644
--- a/src/parser/context-decls.cpp
+++ b/src/parser/context-decls.cpp
@@ -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
@@ -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
@@ -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;
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index cead35f60..8f0c6cdff 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -46,7 +46,7 @@ struct Limits {
};
struct MemType {
- Type type;
+ Type indexType;
Limits limits;
bool shared;
};
@@ -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 {
@@ -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;
@@ -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) {
@@ -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>
@@ -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);
@@ -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{}; }
@@ -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;
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 4d54b3655..30a828822 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -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&);
@@ -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
@@ -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();
@@ -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);
@@ -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;
}
@@ -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)) {
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 99c86cec4..02eaea21c 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -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;
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index 625914cbc..e2709b8ae 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -378,6 +378,11 @@ protected:
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(
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index b5aa83960..9610aed9f 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1552,6 +1552,8 @@ public:
// 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,
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 463faa04f..fbc680d17 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -86,10 +86,12 @@ public:
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;
@@ -658,6 +660,8 @@ public:
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>();
@@ -729,6 +733,9 @@ public:
TableSize* makeTableSize(Name table) {
auto* ret = wasm.allocator.alloc<TableSize>();
ret->table = table;
+ if (isTable64(table)) {
+ ret->type = Type::i64;
+ }
ret->finalize();
return ret;
}
@@ -737,6 +744,9 @@ public:
ret->table = table;
ret->value = value;
ret->delta = delta;
+ if (isTable64(table)) {
+ ret->type = Type::i64;
+ }
ret->finalize();
return ret;
}
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index a9bba774b..bfc1a27c5 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -3086,8 +3086,11 @@ public:
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");
@@ -3100,17 +3103,20 @@ public:
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) {
@@ -3126,16 +3132,16 @@ public:
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;
@@ -3168,9 +3174,14 @@ public:
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) {
diff --git a/src/wasm.h b/src/wasm.h
index ebc7b908d..2f3f09ad5 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -2276,9 +2276,11 @@ public:
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;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 7e90dfde4..c1e506c8e 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -746,7 +746,7 @@ void WasmBinaryWriter::writeTableDeclarations() {
table->max,
table->hasMax(),
/*shared=*/false,
- /*is64*/ false);
+ table->is64());
});
finishSection(start);
}
@@ -2462,6 +2462,13 @@ Name WasmBinaryReader::getGlobalName(Index index) {
return wasm.globals[index]->name;
}
+Table* WasmBinaryReader::getTable(Index index) {
+ if (index < wasm.tables.size()) {
+ return wasm.tables[index].get();
+ }
+ throwError("Table index out of range.");
+}
+
Name WasmBinaryReader::getTagName(Index index) {
if (index >= wasm.tags.size()) {
throwError("invalid tag index");
@@ -2555,18 +2562,14 @@ void WasmBinaryReader::readImports() {
table->type = getType();
bool is_shared;
- Type indexType;
getResizableLimits(table->initial,
table->max,
is_shared,
- indexType,
+ table->indexType,
Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
- if (indexType == Type::i64) {
- throwError("Tables may not be 64-bit");
- }
wasm.addTable(std::move(table));
break;
@@ -3355,16 +3358,14 @@ void WasmBinaryReader::readTableDeclarations() {
}
auto table = Builder::makeTable(Name::fromInt(i), elemType);
bool is_shared;
- Type indexType;
- getResizableLimits(
- table->initial, table->max, is_shared, indexType, Table::kUnlimitedSize);
+ getResizableLimits(table->initial,
+ table->max,
+ is_shared,
+ table->indexType,
+ Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
- if (indexType == Type::i64) {
- throwError("Tables may not be 64-bit");
- }
-
wasm.addTable(std::move(table));
}
}
@@ -5511,6 +5512,9 @@ bool WasmBinaryReader::maybeVisitTableSize(Expression*& out, uint32_t code) {
throwError("bad table index");
}
auto* curr = allocator.alloc<TableSize>();
+ if (getTable(tableIdx)->is64()) {
+ curr->type = Type::i64;
+ }
curr->finalize();
// Defer setting the table name for later, when we know it.
tableRefs[tableIdx].push_back(&curr->table);
@@ -5529,6 +5533,9 @@ bool WasmBinaryReader::maybeVisitTableGrow(Expression*& out, uint32_t code) {
auto* curr = allocator.alloc<TableGrow>();
curr->delta = popNonVoidExpression();
curr->value = popNonVoidExpression();
+ if (getTable(tableIdx)->is64()) {
+ curr->type = Type::i64;
+ }
curr->finalize();
// Defer setting the table name for later, when we know it.
tableRefs[tableIdx].push_back(&curr->table);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index aad9a0582..8f3082b41 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -947,15 +947,16 @@ void FunctionValidator::visitCall(Call* curr) {
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
validateReturnCall(curr);
- shouldBeEqualOrFirstIsUnreachable(curr->target->type,
- Type(Type::i32),
- curr,
- "indirect call target must be an i32");
if (curr->target->type != Type::unreachable) {
auto* table = getModule()->getTableOrNull(curr->table);
- shouldBeTrue(!!table, curr, "call-indirect table must exist");
- if (table) {
+ if (shouldBeTrue(!!table, curr, "call-indirect table must exist")) {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->target->type,
+ table->indexType,
+ curr,
+ "call-indirect call target must match the table index type");
+ shouldBeTrue(!!table, curr, "call-indirect table must exist");
shouldBeTrue(table->type.isFunction(),
curr,
"call-indirect table must be of function type.");
@@ -2267,13 +2268,19 @@ void FunctionValidator::visitTableGet(TableGet* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
"table.get requires reference types [--enable-reference-types]");
- shouldBeEqualOrFirstIsUnreachable(
- curr->index->type, Type(Type::i32), curr, "table.get index must be an i32");
auto* table = getModule()->getTableOrNull(curr->table);
- if (shouldBeTrue(!!table, curr, "table.get table must exist") &&
- curr->type != Type::unreachable) {
- shouldBeEqual(
- curr->type, table->type, curr, "table.get must have same type as table.");
+ if (shouldBeTrue(!!table, curr, "table.get table must exist")) {
+ if (curr->type != Type::unreachable) {
+ shouldBeEqual(curr->type,
+ table->type,
+ curr,
+ "table.get must have same type as table.");
+ }
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->index->type,
+ table->indexType,
+ curr,
+ "table.get index must match the table index type.");
}
}
@@ -2281,15 +2288,19 @@ void FunctionValidator::visitTableSet(TableSet* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
"table.set requires reference types [--enable-reference-types]");
- shouldBeEqualOrFirstIsUnreachable(
- curr->index->type, Type(Type::i32), curr, "table.set index must be an i32");
auto* table = getModule()->getTableOrNull(curr->table);
- if (shouldBeTrue(!!table, curr, "table.set table must exist") &&
- curr->type != Type::unreachable) {
- shouldBeSubType(curr->value->type,
- table->type,
- curr,
- "table.set value must have right type");
+ if (shouldBeTrue(!!table, curr, "table.set table must exist")) {
+ if (curr->type != Type::unreachable) {
+ shouldBeSubType(curr->value->type,
+ table->type,
+ curr,
+ "table.set value must have right type");
+ }
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->index->type,
+ table->indexType,
+ curr,
+ "table.set index must match the table index type.");
}
}
@@ -2315,7 +2326,7 @@ void FunctionValidator::visitTableGrow(TableGrow* curr) {
curr,
"table.grow value must have right type");
shouldBeEqual(curr->delta->type,
- Type(Type::i32),
+ table->indexType,
curr,
"table.grow must match table index type");
}
@@ -2331,11 +2342,17 @@ void FunctionValidator::visitTableFill(TableFill* curr) {
table->type,
curr,
"table.fill value must have right type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->dest->type,
+ table->indexType,
+ curr,
+ "table.fill dest must match table index type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->size->type,
+ table->indexType,
+ curr,
+ "table.fill size must match table index type");
}
- shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "table.fill dest must be i32");
- shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "table.fill size must be i32");
}
void FunctionValidator::visitTableCopy(TableCopy* curr) {
@@ -3841,6 +3858,11 @@ static void validateTables(Module& module, ValidationInfo& info) {
"Only funcref and externref are valid for table type "
"(when gc is disabled)");
}
+ if (table->is64()) {
+ info.shouldBeTrue(module.features.hasMemory64(),
+ "memory",
+ "64-bit tables require memory64 [--enable-memory64]");
+ }
}
for (auto& segment : module.elementSegments) {