Commit f1ffb4df authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][memory64] Enforce i64 index on i64 memory

We now remember whether the memory was 64 bit, in in this case force the
index value to be an i64 instead of an i32.

This is only the decoding part of this change. TurboFan and Liftoff will
have to be fixed separately to handle the i64 values correctly.

R=manoskouk@chromium.org

Bug: v8:10949
Change-Id: Ia504e7eb5a2a55caf8dfdbd0833481ef590c55bf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2461239
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70473}
parent b206bdd0
......@@ -3327,7 +3327,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (!CheckHasMemory()) return 0;
MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
type.size_log_2());
Value index = Pop(0, kWasmI32);
ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value index = Pop(0, index_type);
Value* result = Push(type.value_type());
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
return prefix_len + imm.length;
......@@ -3341,7 +3342,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
transform == LoadTransformationKind::kExtend ? 3 : type.size_log_2();
MemoryAccessImmediate<validate> imm(this, this->pc_ + opcode_length,
max_alignment);
Value index = Pop(0, kWasmI32);
ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value index = Pop(0, index_type);
Value* result = Push(kWasmS128);
CALL_INTERFACE_IF_REACHABLE(LoadTransform, type, transform, imm, index,
result);
......@@ -3368,7 +3370,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
store.size_log_2());
Value value = Pop(1, store.value_type());
Value index = Pop(0, kWasmI32);
ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value index = Pop(0, index_type);
CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
return prefix_len + imm.length;
}
......@@ -4066,6 +4069,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (!CheckHasMemoryForAtomics()) return 0;
MemoryAccessImmediate<validate> imm(
this, this->pc_ + 2, ElementSizeLog2Of(memtype.representation()));
// TODO(10949): Fix this for memory64 (index type should be kWasmI64
// then).
CHECK(!this->module_->is_memory64);
ArgVector args = PopArgs(sig);
Value* result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args), imm, result);
......
......@@ -635,7 +635,8 @@ class ModuleDecoderImpl : public Decoder {
case kExternalMemory: {
// ===== Imported memory =============================================
if (!AddMemory(module_.get())) break;
uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
&module_->is_memory64);
consume_resizable_limits("memory", "pages", max_mem_pages(),
&module_->initial_pages,
&module_->has_maximum_pages, max_mem_pages(),
......@@ -735,7 +736,8 @@ class ModuleDecoderImpl : public Decoder {
for (uint32_t i = 0; ok() && i < memory_count; i++) {
if (!AddMemory(module_.get())) break;
uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
&module_->is_memory64);
consume_resizable_limits("memory", "pages", max_mem_pages(),
&module_->initial_pages,
&module_->has_maximum_pages, max_mem_pages(),
......@@ -1531,7 +1533,7 @@ class ModuleDecoderImpl : public Decoder {
return flags;
}
uint8_t validate_memory_flags(bool* has_shared_memory) {
uint8_t validate_memory_flags(bool* has_shared_memory, bool* is_memory64) {
uint8_t flags = consume_u8("memory limits flags");
*has_shared_memory = false;
switch (flags) {
......@@ -1560,6 +1562,7 @@ class ModuleDecoderImpl : public Decoder {
"invalid memory limits flags (enable via "
"--experimental-wasm-memory64)");
}
*is_memory64 = true;
break;
}
return flags;
......
......@@ -266,6 +266,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
uint32_t maximum_pages = 0; // maximum size of the memory in 64k pages
bool has_shared_memory = false; // true if memory is a SharedArrayBuffer
bool has_maximum_pages = false; // true if there is a maximum memory size
bool is_memory64 = false; // true if the memory is 64 bit
bool has_memory = false; // true if the memory was defined or imported
bool mem_export = false; // true if the memory is exported
int start_function_index = -1; // start function, >= 0 if any
......
......@@ -206,8 +206,10 @@
// Misc expressions.
//------------------------------------------------------------------------------
#define WASM_STMTS(...) __VA_ARGS__
#define WASM_ZERO kExprI32Const, 0
#define WASM_ONE kExprI32Const, 1
#define WASM_ZERO WASM_I32V_1(0)
#define WASM_ONE WASM_I32V_1(1)
#define WASM_ZERO64 WASM_I64V_1(0)
#define WASM_ONE64 WASM_I64V_1(1)
#define I32V_MIN(length) -(1 << (6 + (7 * ((length)-1))))
#define I32V_MAX(length) ((1 << (6 + (7 * ((length)-1)))) - 1)
......
......@@ -68,6 +68,8 @@ constexpr size_t kMaxByteSizedLeb128 = 127;
using F = std::pair<ValueType, bool>;
enum MemoryType { kMemory32, kMemory64 };
// A helper for tests that require a module environment for functions,
// globals, or memories.
class TestModuleBuilder {
......@@ -139,8 +141,9 @@ class TestModuleBuilder {
return static_cast<byte>(mod.type_kinds.size() - 1);
}
void InitializeMemory() {
void InitializeMemory(MemoryType mem_type = kMemory32) {
mod.has_memory = true;
mod.is_memory64 = mem_type == kMemory64;
mod.initial_pages = 1;
mod.maximum_pages = 100;
}
......@@ -4801,6 +4804,31 @@ TEST_F(BytecodeIteratorTest, WithLocalDecls) {
EXPECT_FALSE(iter.has_next());
}
/*******************************************************************************
* Memory64 tests
******************************************************************************/
TEST_F(FunctionBodyDecoderTest, IndexTypesOn32BitMemory) {
builder.InitializeMemory(kMemory32);
ExpectValidates(sigs.i_v(), {WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)});
ExpectFailure(sigs.i_v(), {WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO64)});
ExpectValidates(sigs.v_v(),
{WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_ZERO)});
ExpectFailure(sigs.v_v(),
{WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO64, WASM_ZERO)});
}
TEST_F(FunctionBodyDecoderTest, IndexTypesOn64BitMemory) {
builder.InitializeMemory(kMemory64);
ExpectFailure(sigs.i_v(), {WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)});
ExpectValidates(sigs.i_v(),
{WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO64)});
ExpectFailure(sigs.v_v(),
{WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_ZERO)});
ExpectValidates(sigs.v_v(), {WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO64,
WASM_ZERO)});
}
#undef B1
#undef B2
#undef B3
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment