Skip to content

Commit 8e42376

Browse files
authored
Changes required to make the new Memory64 spec tests run (#1560)
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 8e42376

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)