Skip to content

Commit d465963

Browse files
committed
Changes required to make the new Memory64 spec tests run
These uncovered some things the previous tests didn't! Also required the switching of the location of the index as discussed in WebAssembly/memory64#5 Also one small .py change that ensures the new tests have consistent posix paths.
1 parent 30af7af commit d465963

33 files changed

+932
-65
lines changed

src/interp/interp-inl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,11 @@ inline Memory::Ptr Memory::New(interp::Store& store, MemoryType type) {
633633
}
634634

635635
inline bool Memory::IsValidAccess(u64 offset, u64 addend, u64 size) const {
636-
return offset + addend + size <= data_.size();
636+
// FIXME: make this faster.
637+
return offset <= data_.size() &&
638+
addend <= data_.size() &&
639+
size <= data_.size() &&
640+
offset + addend + size <= data_.size();
637641
}
638642

639643
inline bool Memory::IsValidAtomicAccess(u64 offset,

src/interp/interp.cc

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,10 @@ Value Thread::Pop() {
10231023
return value;
10241024
}
10251025

1026+
u64 Thread::PopPtr(const Memory::Ptr& memory) {
1027+
return memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
1028+
}
1029+
10261030
template <typename T>
10271031
void WABT_VECTORCALL Thread::Push(T value) {
10281032
Push(Value::Make(value));
@@ -1187,15 +1191,15 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
11871191
case O::MemoryGrow: {
11881192
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
11891193
u64 old_size = memory->PageSize();
1190-
if (Failed(memory->Grow(Pop<u32>()))) {
1191-
if (memory->type().limits.is_64) {
1194+
if (memory->type().limits.is_64) {
1195+
if (Failed(memory->Grow(Pop<u64>()))) {
11921196
Push<s64>(-1);
11931197
} else {
1194-
Push<s32>(-1);
1198+
Push<u64>(old_size);
11951199
}
11961200
} else {
1197-
if (memory->type().limits.is_64) {
1198-
Push<u64>(old_size);
1201+
if (Failed(memory->Grow(Pop<u32>()))) {
1202+
Push<s32>(-1);
11991203
} else {
12001204
Push<u32>(old_size);
12011205
}
@@ -1754,7 +1758,7 @@ RunResult Thread::DoCall(const Func::Ptr& func, Trap::Ptr* out_trap) {
17541758
template <typename T>
17551759
RunResult Thread::Load(Instr instr, T* out, Trap::Ptr* out_trap) {
17561760
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
1757-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
1761+
u64 offset = PopPtr(memory);
17581762
TRAP_IF(Failed(memory->Load(offset, instr.imm_u32x2.snd, out)),
17591763
StringPrintf("out of bounds memory access: access at %" PRIu64
17601764
"+%" PRIzd " >= max value %" PRIu64,
@@ -1777,7 +1781,7 @@ template <typename T, typename V>
17771781
RunResult Thread::DoStore(Instr instr, Trap::Ptr* out_trap) {
17781782
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
17791783
V val = static_cast<V>(Pop<T>());
1780-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
1784+
u64 offset = PopPtr(memory);
17811785
TRAP_IF(Failed(memory->Store(offset, instr.imm_u32x2.snd, val)),
17821786
StringPrintf("out of bounds memory access: access at %" PRIu64
17831787
"+%" PRIzd " >= max value %" PRIu64,
@@ -1843,7 +1847,7 @@ RunResult Thread::DoMemoryInit(Instr instr, Trap::Ptr* out_trap) {
18431847
auto&& data = inst_->datas()[instr.imm_u32x2.snd];
18441848
auto size = Pop<u32>();
18451849
auto src = Pop<u32>();
1846-
auto dst = Pop<u32>();
1850+
auto dst = PopPtr(memory);
18471851
TRAP_IF(Failed(memory->Init(dst, data, src, size)),
18481852
"out of bounds memory access: memory.init out of bounds");
18491853
return RunResult::Ok;
@@ -1857,9 +1861,9 @@ RunResult Thread::DoDataDrop(Instr instr) {
18571861
RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
18581862
Memory::Ptr mem_dst{store_, inst_->memories()[instr.imm_u32x2.fst]};
18591863
Memory::Ptr mem_src{store_, inst_->memories()[instr.imm_u32x2.snd]};
1860-
auto size = Pop<u32>();
1861-
auto src = Pop<u32>();
1862-
auto dst = Pop<u32>();
1864+
auto size = PopPtr(mem_src);
1865+
auto src = PopPtr(mem_src);
1866+
auto dst = PopPtr(mem_dst);
18631867
// TODO: change to "out of bounds"
18641868
TRAP_IF(Failed(Memory::Copy(*mem_dst, dst, *mem_src, src, size)),
18651869
"out of bounds memory access: memory.copy out of bound");
@@ -1868,9 +1872,9 @@ RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
18681872

18691873
RunResult Thread::DoMemoryFill(Instr instr, Trap::Ptr* out_trap) {
18701874
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
1871-
auto size = Pop<u32>();
1875+
auto size = PopPtr(memory);
18721876
auto value = Pop<u32>();
1873-
auto dst = Pop<u32>();
1877+
auto dst = PopPtr(memory);
18741878
TRAP_IF(Failed(memory->Fill(dst, value, size)),
18751879
"out of bounds memory access: memory.fill out of bounds");
18761880
return RunResult::Ok;
@@ -2151,7 +2155,7 @@ RunResult Thread::DoSimdLoadExtend(Instr instr, Trap::Ptr* out_trap) {
21512155
template <typename T, typename V>
21522156
RunResult Thread::DoAtomicLoad(Instr instr, Trap::Ptr* out_trap) {
21532157
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
2154-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
2158+
u64 offset = PopPtr(memory);
21552159
V val;
21562160
TRAP_IF(Failed(memory->AtomicLoad(offset, instr.imm_u32x2.snd, &val)),
21572161
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
@@ -2164,7 +2168,7 @@ template <typename T, typename V>
21642168
RunResult Thread::DoAtomicStore(Instr instr, Trap::Ptr* out_trap) {
21652169
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
21662170
V val = static_cast<V>(Pop<T>());
2167-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
2171+
u64 offset = PopPtr(memory);
21682172
TRAP_IF(Failed(memory->AtomicStore(offset, instr.imm_u32x2.snd, val)),
21692173
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
21702174
instr.imm_u32x2.snd));
@@ -2177,7 +2181,7 @@ RunResult Thread::DoAtomicRmw(BinopFunc<T, T> f,
21772181
Trap::Ptr* out_trap) {
21782182
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
21792183
T val = static_cast<T>(Pop<R>());
2180-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
2184+
u64 offset = PopPtr(memory);
21812185
T old;
21822186
TRAP_IF(Failed(memory->AtomicRmw(offset, instr.imm_u32x2.snd, val, f, &old)),
21832187
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
@@ -2192,7 +2196,7 @@ RunResult Thread::DoAtomicRmwCmpxchg(Instr instr, Trap::Ptr* out_trap) {
21922196
V replace = static_cast<V>(Pop<T>());
21932197
V expect = static_cast<V>(Pop<T>());
21942198
V old;
2195-
u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
2199+
u64 offset = PopPtr(memory);
21962200
TRAP_IF(Failed(memory->AtomicRmwCmpxchg(offset, instr.imm_u32x2.snd, expect,
21972201
replace, &old)),
21982202
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,

src/interp/interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ class Thread : public Object {
10651065
template <typename T>
10661066
T WABT_VECTORCALL Pop();
10671067
Value Pop();
1068+
u64 PopPtr(const Memory::Ptr& memory);
10681069

10691070
template <typename T>
10701071
void WABT_VECTORCALL Push(T);

src/wast-parser.cc

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,22 @@ bool WastParser::ParseAlignOpt(Address* out_align) {
939939
}
940940
}
941941

942+
Result WastParser::ParseLimitsIndex(Limits* out_limits) {
943+
WABT_TRACE(ParseLimitsIndex);
944+
945+
if (PeekMatch(TokenType::ValueType)) {
946+
if (GetToken().type() == Type::I64) {
947+
Consume();
948+
out_limits->is_64 = true;
949+
} else if (GetToken().type() == Type::I32) {
950+
Consume();
951+
out_limits->is_64 = false;
952+
}
953+
}
954+
955+
return Result::Ok;
956+
}
957+
942958
Result WastParser::ParseLimits(Limits* out_limits) {
943959
WABT_TRACE(ParseLimits);
944960

@@ -954,11 +970,6 @@ Result WastParser::ParseLimits(Limits* out_limits) {
954970
out_limits->is_shared = true;
955971
}
956972

957-
if (PeekMatch(TokenType::ValueType) && GetToken().type() == Type::I64) {
958-
Consume();
959-
out_limits->is_64 = true;
960-
}
961-
962973
return Result::Ok;
963974
}
964975

@@ -1387,6 +1398,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
13871398
Consume();
13881399
ParseBindVarOpt(&name);
13891400
auto import = MakeUnique<MemoryImport>(name);
1401+
CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
13901402
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
13911403
EXPECT(Rpar);
13921404
field = MakeUnique<ImportModuleField>(std::move(import), loc);
@@ -1441,32 +1453,35 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
14411453
CheckImportOrdering(module);
14421454
auto import = MakeUnique<MemoryImport>(name);
14431455
CHECK_RESULT(ParseInlineImport(import.get()));
1456+
CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
14441457
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
14451458
auto field =
14461459
MakeUnique<ImportModuleField>(std::move(import), GetLocation());
14471460
module->AppendField(std::move(field));
1448-
} else if (MatchLpar(TokenType::Data)) {
1449-
auto data_segment_field = MakeUnique<DataSegmentModuleField>(loc);
1450-
DataSegment& data_segment = data_segment_field->data_segment;
1451-
data_segment.memory_var = Var(module->memories.size());
1452-
data_segment.offset.push_back(MakeUnique<ConstExpr>(Const::I32(0)));
1453-
data_segment.offset.back().loc = loc;
1454-
ParseTextListOpt(&data_segment.data);
1455-
EXPECT(Rpar);
1456-
1457-
auto memory_field = MakeUnique<MemoryModuleField>(loc, name);
1458-
uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
1459-
uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
1460-
memory_field->memory.page_limits.initial = page_size;
1461-
memory_field->memory.page_limits.max = page_size;
1462-
memory_field->memory.page_limits.has_max = true;
1463-
1464-
module->AppendField(std::move(memory_field));
1465-
module->AppendField(std::move(data_segment_field));
14661461
} else {
14671462
auto field = MakeUnique<MemoryModuleField>(loc, name);
1468-
CHECK_RESULT(ParseLimits(&field->memory.page_limits));
1469-
module->AppendField(std::move(field));
1463+
CHECK_RESULT(ParseLimitsIndex(&field->memory.page_limits));
1464+
if (MatchLpar(TokenType::Data)) {
1465+
auto data_segment_field = MakeUnique<DataSegmentModuleField>(loc);
1466+
DataSegment& data_segment = data_segment_field->data_segment;
1467+
data_segment.memory_var = Var(module->memories.size());
1468+
data_segment.offset.push_back(MakeUnique<ConstExpr>(Const::I32(0)));
1469+
data_segment.offset.back().loc = loc;
1470+
ParseTextListOpt(&data_segment.data);
1471+
EXPECT(Rpar);
1472+
1473+
uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
1474+
uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
1475+
field->memory.page_limits.initial = page_size;
1476+
field->memory.page_limits.max = page_size;
1477+
field->memory.page_limits.has_max = true;
1478+
1479+
module->AppendField(std::move(field));
1480+
module->AppendField(std::move(data_segment_field));
1481+
} else {
1482+
CHECK_RESULT(ParseLimits(&field->memory.page_limits));
1483+
module->AppendField(std::move(field));
1484+
}
14701485
}
14711486

14721487
AppendInlineExportFields(module, &export_fields, module->memories.size() - 1);

src/wast-parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class WastParser {
137137
Result ParseQuotedText(std::string* text);
138138
bool ParseOffsetOpt(Address* offset);
139139
bool ParseAlignOpt(Address* align);
140+
Result ParseLimitsIndex(Limits*);
140141
Result ParseLimits(Limits*);
141142
Result ParseNat(uint64_t*);
142143

src/wat-writer.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,16 +1267,16 @@ void WatWriter::WriteEvent(const Event& event) {
12671267
}
12681268

12691269
void WatWriter::WriteLimits(const Limits& limits) {
1270+
if (limits.is_64) {
1271+
Writef("i64");
1272+
}
12701273
Writef("%" PRIu64, limits.initial);
12711274
if (limits.has_max) {
12721275
Writef("%" PRIu64, limits.max);
12731276
}
12741277
if (limits.is_shared) {
12751278
Writef("shared");
12761279
}
1277-
if (limits.is_64) {
1278-
Writef("i64");
1279-
}
12801280
}
12811281

12821282
void WatWriter::WriteTable(const Table& table) {

test/dump/bulk-memory64.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
;;; ARGS0: --enable-bulk-memory
33

44
(module
5-
(memory 1 i64)
5+
(memory i64 1)
66
(data "a")
77
(func
88
i64.const 0 i32.const 0 i32.const 0 memory.init 0

test/dump/load64.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
;;; TOOL: run-objdump
22
;;; ARGS0: -v
33
(module
4-
(memory 1 i64)
4+
(memory i64 1)
55
(func
66
i64.const 0
77
i32.load

test/dump/store64.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
;;; TOOL: run-objdump
22
;;; ARGS0: -v
33
(module
4-
(memory 1 i64)
4+
(memory i64 1)
55
(func
66
i64.const 0
77
i32.const 0

test/interp/load64.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
;;; TOOL: run-interp
22
;;; ARGS: --enable-memory64
33
(module
4-
(memory 1 i64)
4+
(memory i64 1)
55
(data (i32.const 0) "\ff\ff\ff\ff")
66
(data (i32.const 4) "\00\00\ce\41")
77
(data (i32.const 8) "\00\00\00\00\00\ff\8f\40")

0 commit comments

Comments
 (0)