Skip to content

Commit 22e82a5

Browse files
committed
Update testsuite and implement table64
See WebAssembly/memory64#51
1 parent c24a216 commit 22e82a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+4131
-344
lines changed

include/wabt/interp/interp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,9 @@ class Thread {
11231123
T WABT_VECTORCALL Pop();
11241124
Value Pop();
11251125
u64 PopPtr(const Memory::Ptr& memory);
1126+
u64 PopPtr(const Table::Ptr& table);
1127+
void PushPtr(const Memory::Ptr& memory, u64 value);
1128+
void PushPtr(const Table::Ptr& table, u64 value);
11261129

11271130
template <typename T>
11281131
void WABT_VECTORCALL Push(T);

include/wabt/type-checker.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ class TypeChecker {
7777
Result EndBrTable();
7878
Result OnCall(const TypeVector& param_types, const TypeVector& result_types);
7979
Result OnCallIndirect(const TypeVector& param_types,
80-
const TypeVector& result_types);
80+
const TypeVector& result_types,
81+
const Limits& table_limits);
8182
Result OnIndexedFuncRef(Index* out_index);
8283
Result OnReturnCall(const TypeVector& param_types,
8384
const TypeVector& result_types);
@@ -99,20 +100,20 @@ class TypeChecker {
99100
Result OnLocalSet(Type);
100101
Result OnLocalTee(Type);
101102
Result OnLoop(const TypeVector& param_types, const TypeVector& result_types);
102-
Result OnMemoryCopy(const Limits& dstlimits, const Limits& srclimits);
103+
Result OnMemoryCopy(const Limits& dst_limits, const Limits& src_limits);
103104
Result OnDataDrop(Index);
104105
Result OnMemoryFill(const Limits& limits);
105106
Result OnMemoryGrow(const Limits& limits);
106107
Result OnMemoryInit(Index, const Limits& limits);
107108
Result OnMemorySize(const Limits& limits);
108-
Result OnTableCopy();
109+
Result OnTableCopy(const Limits& dst_limits, const Limits& src_limits);
109110
Result OnElemDrop(Index);
110-
Result OnTableInit(Index, Index);
111-
Result OnTableGet(Type elem_type);
112-
Result OnTableSet(Type elem_type);
113-
Result OnTableGrow(Type elem_type);
114-
Result OnTableSize();
115-
Result OnTableFill(Type elem_type);
111+
Result OnTableInit(Index, const Limits& limits);
112+
Result OnTableGet(Type elem_type, const Limits& limits);
113+
Result OnTableSet(Type elem_type, const Limits& limits);
114+
Result OnTableGrow(Type elem_type, const Limits& limits);
115+
Result OnTableSize(const Limits& limits);
116+
Result OnTableFill(Type elem_type, const Limits& limits);
116117
Result OnRefFuncExpr(Index func_type, bool force_generic_funcref);
117118
Result OnRefNullExpr(Type type);
118119
Result OnRefIsNullExpr();

src/binary-reader.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,14 +582,16 @@ Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
582582
bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG;
583583
const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_FLAGS;
584584
ERROR_IF(is_shared, "tables may not be shared");
585-
ERROR_IF(is_64, "tables may not be 64-bit");
585+
ERROR_IF(is_64 && !options_.features.memory64_enabled(),
586+
"memory64 not allowed");
586587
ERROR_UNLESS(unknown_flags == 0, "malformed table limits flag: %d", flags);
587588
CHECK_RESULT(ReadU32Leb128(&initial, "table initial elem count"));
588589
if (has_max) {
589590
CHECK_RESULT(ReadU32Leb128(&max, "table max elem count"));
590591
}
591592

592593
out_elem_limits->has_max = has_max;
594+
out_elem_limits->is_64 = is_64;
593595
out_elem_limits->initial = initial;
594596
out_elem_limits->max = max;
595597
return Result::Ok;

src/interp/binary-reader-interp.cc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
306306
Index keep_extra,
307307
Index* out_drop_count,
308308
Index* out_keep_count);
309-
Result BeginInitExpr(Type type, FuncDesc* init_func);
309+
Result BeginInitExpr(FuncDesc* init_func);
310310
Result EndInitExpr();
311311

312312
void EmitBr(Index depth,
@@ -631,7 +631,7 @@ Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) {
631631

632632
Result BinaryReaderInterp::BeginGlobalInitExpr(Index index) {
633633
GlobalDesc& global = module_.globals.back();
634-
return BeginInitExpr(global.type.type, &global.init_func);
634+
return BeginInitExpr(&global.init_func);
635635
}
636636

637637
Result BinaryReaderInterp::EndInitExpr() {
@@ -642,10 +642,11 @@ Result BinaryReaderInterp::EndInitExpr() {
642642
return Result::Ok;
643643
}
644644

645-
Result BinaryReaderInterp::BeginInitExpr(Type type, FuncDesc* func) {
645+
Result BinaryReaderInterp::BeginInitExpr(FuncDesc* func) {
646646
label_stack_.clear();
647647
func_ = func;
648648
func_->code_offset = istream_.end();
649+
Type type = func->type.results[0];
649650
CHECK_RESULT(validator_.BeginInitExpr(GetLocation(), type));
650651
// Push implicit init func label (equivalent to return).
651652
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset);
@@ -709,16 +710,21 @@ Result BinaryReaderInterp::BeginElemSegment(Index index,
709710
CHECK_RESULT(validator_.OnElemSegment(GetLocation(),
710711
Var(table_index, GetLocation()), mode));
711712

713+
ValueType offset_type = ValueType::I32;
714+
if (table_index < table_types_.size() &&
715+
table_types_[table_index].limits.is_64) {
716+
offset_type = ValueType::I64;
717+
}
712718
FuncDesc init_func{
713-
FuncType{{}, {ValueType::I32}}, {}, Istream::kInvalidOffset, {}};
719+
FuncType{{}, {offset_type}}, {}, Istream::kInvalidOffset, {}};
714720
ElemDesc desc{{}, ValueType::Void, mode, table_index, init_func};
715721
module_.elems.push_back(desc);
716722
return Result::Ok;
717723
}
718724

719725
Result BinaryReaderInterp::BeginElemSegmentInitExpr(Index index) {
720726
ElemDesc& elem = module_.elems.back();
721-
return BeginInitExpr(Type::I32, &elem.init_func);
727+
return BeginInitExpr(&elem.init_func);
722728
}
723729

724730
Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) {
@@ -744,7 +750,7 @@ Result BinaryReaderInterp::BeginElemExpr(Index elem_index, Index expr_index) {
744750
elem.elements.push_back(
745751
{FuncType{{}, {elem.type}}, {}, Istream::kInvalidOffset, {}});
746752
assert(expr_index == elem.elements.size() - 1);
747-
return BeginInitExpr(elem.type, &elem.elements.back());
753+
return BeginInitExpr(&elem.elements.back());
748754
}
749755

750756
Result BinaryReaderInterp::EndElemExpr(Index elem_index, Index expr_index) {
@@ -758,9 +764,8 @@ Result BinaryReaderInterp::OnDataCount(Index count) {
758764
}
759765

760766
Result BinaryReaderInterp::BeginDataSegmentInitExpr(Index index) {
761-
MemoryType t = memory_types_[0];
762767
DataDesc& data = module_.datas.back();
763-
return BeginInitExpr(t.limits.is_64 ? Type::I64 : Type::I32, &data.init_func);
768+
return BeginInitExpr(&data.init_func);
764769
}
765770

766771
Result BinaryReaderInterp::EndDataSegmentInitExpr(Index index) {
@@ -774,8 +779,13 @@ Result BinaryReaderInterp::BeginDataSegment(Index index,
774779
CHECK_RESULT(validator_.OnDataSegment(
775780
GetLocation(), Var(memory_index, GetLocation()), mode));
776781

782+
ValueType offset_type = ValueType::I32;
783+
if (memory_index < memory_types_.size() &&
784+
memory_types_[memory_index].limits.is_64) {
785+
offset_type = ValueType::I64;
786+
}
777787
FuncDesc init_func{
778-
FuncType{{}, {ValueType::I32}}, {}, Istream::kInvalidOffset, {}};
788+
FuncType{{}, {offset_type}}, {}, Istream::kInvalidOffset, {}};
779789
DataDesc desc{{}, mode, memory_index, init_func};
780790
module_.datas.push_back(desc);
781791
return Result::Ok;

src/interp/interp.cc

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,14 @@ Instance::Ptr Instance::Instantiate(Store& store,
873873
if (Failed(inst->CallInitFunc(store, func_ref, &value, out_trap))) {
874874
return {};
875875
}
876-
u32 offset = value.Get<u32>();
876+
877+
u64 offset;
878+
if (table->type().limits.is_64) {
879+
offset = value.Get<u64>();
880+
} else {
881+
offset = value.Get<u32>();
882+
}
883+
877884
if (pass == Check) {
878885
result = table->IsValidRange(offset, segment.size()) ? Result::Ok
879886
: Result::Error;
@@ -888,8 +895,8 @@ Instance::Ptr Instance::Instantiate(Store& store,
888895
*out_trap = Trap::New(
889896
store, StringPrintf(
890897
"out of bounds table access: elem segment is "
891-
"out of bounds: [%u, %" PRIu64 ") >= max value %u",
892-
offset, u64{offset} + segment.size(), table->size()));
898+
"out of bounds: [%" PRIu64 ", %" PRIu64 ") >= max value %u",
899+
offset, offset + segment.size(), table->size()));
893900
return {};
894901
}
895902
} else if (desc.mode == SegmentMode::Declared) {
@@ -1119,6 +1126,26 @@ u64 Thread::PopPtr(const Memory::Ptr& memory) {
11191126
return memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
11201127
}
11211128

1129+
u64 Thread::PopPtr(const Table::Ptr& table) {
1130+
return table->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
1131+
}
1132+
1133+
void Thread::PushPtr(const Memory::Ptr& memory, u64 value) {
1134+
if (memory->type().limits.is_64) {
1135+
Push<u64>(value);
1136+
} else {
1137+
Push<u32>(value);
1138+
}
1139+
}
1140+
1141+
void Thread::PushPtr(const Table::Ptr& table, u64 value) {
1142+
if (table->type().limits.is_64) {
1143+
Push<u64>(value);
1144+
} else {
1145+
Push<u32>(value);
1146+
}
1147+
}
1148+
11221149
template <typename T>
11231150
void WABT_VECTORCALL Thread::Push(T value) {
11241151
Push(Value::Make(value));
@@ -1190,7 +1217,7 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
11901217
case O::ReturnCallIndirect: {
11911218
Table::Ptr table{store_, inst_->tables()[instr.imm_u32x2.fst]};
11921219
auto&& func_type = mod_->desc().func_types[instr.imm_u32x2.snd];
1193-
auto entry = Pop<u32>();
1220+
u64 entry = PopPtr(table);
11941221
TRAP_IF(entry >= table->elements().size(), "undefined table index");
11951222
auto new_func_ref = table->elements()[entry];
11961223
TRAP_IF(new_func_ref == Ref::Null, "uninitialized table element");
@@ -1273,29 +1300,17 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
12731300

12741301
case O::MemorySize: {
12751302
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
1276-
if (memory->type().limits.is_64) {
1277-
Push<u64>(memory->PageSize());
1278-
} else {
1279-
Push<u32>(static_cast<u32>(memory->PageSize()));
1280-
}
1303+
PushPtr(memory, memory->PageSize());
12811304
break;
12821305
}
12831306

12841307
case O::MemoryGrow: {
12851308
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
12861309
u64 old_size = memory->PageSize();
1287-
if (memory->type().limits.is_64) {
1288-
if (Failed(memory->Grow(Pop<u64>()))) {
1289-
Push<s64>(-1);
1290-
} else {
1291-
Push<u64>(old_size);
1292-
}
1310+
if (Failed(memory->Grow(PopPtr(memory)))) {
1311+
PushPtr(memory, -1);
12931312
} else {
1294-
if (Failed(memory->Grow(Pop<u32>()))) {
1295-
Push<s32>(-1);
1296-
} else {
1297-
Push<u32>(old_size);
1298-
}
1313+
PushPtr(memory, old_size);
12991314
}
13001315
break;
13011316
}
@@ -2071,7 +2086,7 @@ RunResult Thread::DoMemoryInit(Instr instr, Trap::Ptr* out_trap) {
20712086
auto&& data = inst_->datas()[instr.imm_u32x2.snd];
20722087
auto size = Pop<u32>();
20732088
auto src = Pop<u32>();
2074-
auto dst = PopPtr(memory);
2089+
u64 dst = PopPtr(memory);
20752090
TRAP_IF(Failed(memory->Init(dst, data, src, size)),
20762091
"out of bounds memory access: memory.init out of bounds");
20772092
return RunResult::Ok;
@@ -2085,9 +2100,9 @@ RunResult Thread::DoDataDrop(Instr instr) {
20852100
RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
20862101
Memory::Ptr mem_dst{store_, inst_->memories()[instr.imm_u32x2.fst]};
20872102
Memory::Ptr mem_src{store_, inst_->memories()[instr.imm_u32x2.snd]};
2088-
auto size = PopPtr(mem_src);
2089-
auto src = PopPtr(mem_src);
2090-
auto dst = PopPtr(mem_dst);
2103+
u64 size = PopPtr(mem_src);
2104+
u64 src = PopPtr(mem_src);
2105+
u64 dst = PopPtr(mem_dst);
20912106
// TODO: change to "out of bounds"
20922107
TRAP_IF(Failed(Memory::Copy(*mem_dst, dst, *mem_src, src, size)),
20932108
"out of bounds memory access: memory.copy out of bound");
@@ -2096,9 +2111,9 @@ RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
20962111

20972112
RunResult Thread::DoMemoryFill(Instr instr, Trap::Ptr* out_trap) {
20982113
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
2099-
auto size = PopPtr(memory);
2114+
u64 size = PopPtr(memory);
21002115
auto value = Pop<u32>();
2101-
auto dst = PopPtr(memory);
2116+
u64 dst = PopPtr(memory);
21022117
TRAP_IF(Failed(memory->Fill(dst, value, size)),
21032118
"out of bounds memory access: memory.fill out of bounds");
21042119
return RunResult::Ok;
@@ -2109,7 +2124,7 @@ RunResult Thread::DoTableInit(Instr instr, Trap::Ptr* out_trap) {
21092124
auto&& elem = inst_->elems()[instr.imm_u32x2.snd];
21102125
auto size = Pop<u32>();
21112126
auto src = Pop<u32>();
2112-
auto dst = Pop<u32>();
2127+
u64 dst = PopPtr(table);
21132128
TRAP_IF(Failed(table->Init(store_, dst, elem, src, size)),
21142129
"out of bounds table access: table.init out of bounds");
21152130
return RunResult::Ok;
@@ -2123,61 +2138,61 @@ RunResult Thread::DoElemDrop(Instr instr) {
21232138
RunResult Thread::DoTableCopy(Instr instr, Trap::Ptr* out_trap) {
21242139
Table::Ptr table_dst{store_, inst_->tables()[instr.imm_u32x2.fst]};
21252140
Table::Ptr table_src{store_, inst_->tables()[instr.imm_u32x2.snd]};
2126-
auto size = Pop<u32>();
2127-
auto src = Pop<u32>();
2128-
auto dst = Pop<u32>();
2141+
u64 size = PopPtr(table_src);
2142+
u64 src = PopPtr(table_src);
2143+
u64 dst = PopPtr(table_dst);
21292144
TRAP_IF(Failed(Table::Copy(store_, *table_dst, dst, *table_src, src, size)),
21302145
"out of bounds table access: table.copy out of bounds");
21312146
return RunResult::Ok;
21322147
}
21332148

21342149
RunResult Thread::DoTableGet(Instr instr, Trap::Ptr* out_trap) {
21352150
Table::Ptr table{store_, inst_->tables()[instr.imm_u32]};
2136-
auto index = Pop<u32>();
2151+
u64 index = PopPtr(table);
21372152
Ref ref;
21382153
TRAP_IF(Failed(table->Get(index, &ref)),
2139-
StringPrintf(
2140-
"out of bounds table access: table.get at %u >= max value %u",
2141-
index, table->size()));
2154+
StringPrintf("out of bounds table access: table.get at %" PRIu64
2155+
" >= max value %u",
2156+
index, table->size()));
21422157
Push(ref);
21432158
return RunResult::Ok;
21442159
}
21452160

21462161
RunResult Thread::DoTableSet(Instr instr, Trap::Ptr* out_trap) {
21472162
Table::Ptr table{store_, inst_->tables()[instr.imm_u32]};
21482163
auto ref = Pop<Ref>();
2149-
auto index = Pop<u32>();
2164+
u64 index = PopPtr(table);
21502165
TRAP_IF(Failed(table->Set(store_, index, ref)),
2151-
StringPrintf(
2152-
"out of bounds table access: table.set at %u >= max value %u",
2153-
index, table->size()));
2166+
StringPrintf("out of bounds table access: table.set at %" PRIu64
2167+
" >= max value %u",
2168+
index, table->size()));
21542169
return RunResult::Ok;
21552170
}
21562171

21572172
RunResult Thread::DoTableGrow(Instr instr, Trap::Ptr* out_trap) {
21582173
Table::Ptr table{store_, inst_->tables()[instr.imm_u32]};
21592174
u32 old_size = table->size();
2160-
auto delta = Pop<u32>();
2175+
auto delta = PopPtr(table);
21612176
auto ref = Pop<Ref>();
21622177
if (Failed(table->Grow(store_, delta, ref))) {
2163-
Push<s32>(-1);
2178+
PushPtr(table, -1);
21642179
} else {
2165-
Push<u32>(old_size);
2180+
PushPtr(table, old_size);
21662181
}
21672182
return RunResult::Ok;
21682183
}
21692184

21702185
RunResult Thread::DoTableSize(Instr instr) {
21712186
Table::Ptr table{store_, inst_->tables()[instr.imm_u32]};
2172-
Push<u32>(table->size());
2187+
PushPtr(table, table->size());
21732188
return RunResult::Ok;
21742189
}
21752190

21762191
RunResult Thread::DoTableFill(Instr instr, Trap::Ptr* out_trap) {
21772192
Table::Ptr table{store_, inst_->tables()[instr.imm_u32]};
2178-
auto size = Pop<u32>();
2193+
u64 size = PopPtr(table);
21792194
auto value = Pop<Ref>();
2180-
auto dst = Pop<u32>();
2195+
u64 dst = PopPtr(table);
21812196
TRAP_IF(Failed(table->Fill(store_, dst, value, size)),
21822197
"out of bounds table access: table.fill out of bounds");
21832198
return RunResult::Ok;

0 commit comments

Comments
 (0)