mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 01:08:11 +00:00
LibWasm: Implement the multi-memory proposal
This commit is contained in:
parent
f4515aae80
commit
22d411345d
5 changed files with 221 additions and 139 deletions
|
@ -88,13 +88,13 @@ void BytecodeInterpreter::branch_to_label(Configuration& configuration, LabelInd
|
||||||
template<typename ReadType, typename PushType>
|
template<typename ReadType, typename PushType>
|
||||||
void BytecodeInterpreter::load_and_push(Configuration& configuration, Instruction const& instruction)
|
void BytecodeInterpreter::load_and_push(Configuration& configuration, Instruction const& instruction)
|
||||||
{
|
{
|
||||||
auto& address = configuration.frame().module().memories().first();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
auto& address = configuration.frame().module().memories()[arg.memory_index.value()];
|
||||||
auto memory = configuration.store().get(address);
|
auto memory = configuration.store().get(address);
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
m_trap = Trap { "Nonexistent memory" };
|
m_trap = Trap { "Nonexistent memory" };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
|
||||||
auto& entry = configuration.stack().peek();
|
auto& entry = configuration.stack().peek();
|
||||||
auto base = entry.get<Value>().to<i32>();
|
auto base = entry.get<Value>().to<i32>();
|
||||||
if (!base.has_value()) {
|
if (!base.has_value()) {
|
||||||
|
@ -123,13 +123,13 @@ ALWAYS_INLINE static TDst convert_vector(TSrc v)
|
||||||
template<size_t M, size_t N, template<typename> typename SetSign>
|
template<size_t M, size_t N, template<typename> typename SetSign>
|
||||||
void BytecodeInterpreter::load_and_push_mxn(Configuration& configuration, Instruction const& instruction)
|
void BytecodeInterpreter::load_and_push_mxn(Configuration& configuration, Instruction const& instruction)
|
||||||
{
|
{
|
||||||
auto& address = configuration.frame().module().memories().first();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
auto& address = configuration.frame().module().memories()[arg.memory_index.value()];
|
||||||
auto memory = configuration.store().get(address);
|
auto memory = configuration.store().get(address);
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
m_trap = Trap { "Nonexistent memory" };
|
m_trap = Trap { "Nonexistent memory" };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
|
||||||
auto& entry = configuration.stack().peek();
|
auto& entry = configuration.stack().peek();
|
||||||
auto base = entry.get<Value>().to<i32>();
|
auto base = entry.get<Value>().to<i32>();
|
||||||
if (!base.has_value()) {
|
if (!base.has_value()) {
|
||||||
|
@ -161,13 +161,13 @@ void BytecodeInterpreter::load_and_push_mxn(Configuration& configuration, Instru
|
||||||
template<size_t M>
|
template<size_t M>
|
||||||
void BytecodeInterpreter::load_and_push_m_splat(Configuration& configuration, Instruction const& instruction)
|
void BytecodeInterpreter::load_and_push_m_splat(Configuration& configuration, Instruction const& instruction)
|
||||||
{
|
{
|
||||||
auto& address = configuration.frame().module().memories().first();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
auto& address = configuration.frame().module().memories()[arg.memory_index.value()];
|
||||||
auto memory = configuration.store().get(address);
|
auto memory = configuration.store().get(address);
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
m_trap = Trap { "Nonexistent memory" };
|
m_trap = Trap { "Nonexistent memory" };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
|
||||||
auto& entry = configuration.stack().peek();
|
auto& entry = configuration.stack().peek();
|
||||||
auto base = entry.get<Value>().to<i32>();
|
auto base = entry.get<Value>().to<i32>();
|
||||||
if (!base.has_value()) {
|
if (!base.has_value()) {
|
||||||
|
@ -384,9 +384,9 @@ void BytecodeInterpreter::pop_and_store(Configuration& configuration, Instructio
|
||||||
|
|
||||||
void BytecodeInterpreter::store_to_memory(Configuration& configuration, Instruction const& instruction, ReadonlyBytes data, i32 base)
|
void BytecodeInterpreter::store_to_memory(Configuration& configuration, Instruction const& instruction, ReadonlyBytes data, i32 base)
|
||||||
{
|
{
|
||||||
auto& address = configuration.frame().module().memories().first();
|
|
||||||
auto memory = configuration.store().get(address);
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
auto& address = configuration.frame().module().memories()[arg.memory_index.value()];
|
||||||
|
auto memory = configuration.store().get(address);
|
||||||
u64 instance_address = static_cast<u64>(bit_cast<u32>(base)) + arg.offset;
|
u64 instance_address = static_cast<u64>(bit_cast<u32>(base)) + arg.offset;
|
||||||
Checked addition { instance_address };
|
Checked addition { instance_address };
|
||||||
addition += data.size();
|
addition += data.size();
|
||||||
|
@ -745,7 +745,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Instructions::memory_size.value(): {
|
case Instructions::memory_size.value(): {
|
||||||
auto address = configuration.frame().module().memories()[0];
|
auto& args = instruction.arguments().get<Instruction::MemoryIndexArgument>();
|
||||||
|
auto address = configuration.frame().module().memories()[args.memory_index.value()];
|
||||||
auto instance = configuration.store().get(address);
|
auto instance = configuration.store().get(address);
|
||||||
auto pages = instance->size() / Constants::page_size;
|
auto pages = instance->size() / Constants::page_size;
|
||||||
dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
|
dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
|
||||||
|
@ -753,7 +754,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Instructions::memory_grow.value(): {
|
case Instructions::memory_grow.value(): {
|
||||||
auto address = configuration.frame().module().memories()[0];
|
auto& args = instruction.arguments().get<Instruction::MemoryIndexArgument>();
|
||||||
|
auto address = configuration.frame().module().memories()[args.memory_index.value()];
|
||||||
auto instance = configuration.store().get(address);
|
auto instance = configuration.store().get(address);
|
||||||
i32 old_pages = instance->size() / Constants::page_size;
|
i32 old_pages = instance->size() / Constants::page_size;
|
||||||
auto& entry = configuration.stack().peek();
|
auto& entry = configuration.stack().peek();
|
||||||
|
@ -767,7 +769,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
}
|
}
|
||||||
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-fill
|
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-fill
|
||||||
case Instructions::memory_fill.value(): {
|
case Instructions::memory_fill.value(): {
|
||||||
auto address = configuration.frame().module().memories()[0];
|
auto& args = instruction.arguments().get<Instruction::MemoryIndexArgument>();
|
||||||
|
auto address = configuration.frame().module().memories()[args.memory_index.value()];
|
||||||
auto instance = configuration.store().get(address);
|
auto instance = configuration.store().get(address);
|
||||||
auto count = configuration.stack().pop().get<Value>().to<i32>().value();
|
auto count = configuration.stack().pop().get<Value>().to<i32>().value();
|
||||||
auto value = configuration.stack().pop().get<Value>().to<i32>().value();
|
auto value = configuration.stack().pop().get<Value>().to<i32>().value();
|
||||||
|
@ -790,31 +793,35 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
}
|
}
|
||||||
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-copy
|
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-copy
|
||||||
case Instructions::memory_copy.value(): {
|
case Instructions::memory_copy.value(): {
|
||||||
auto address = configuration.frame().module().memories()[0];
|
auto& args = instruction.arguments().get<Instruction::MemoryCopyArgs>();
|
||||||
auto instance = configuration.store().get(address);
|
auto source_address = configuration.frame().module().memories()[args.src_index.value()];
|
||||||
|
auto destination_address = configuration.frame().module().memories()[args.dst_index.value()];
|
||||||
|
auto source_instance = configuration.store().get(source_address);
|
||||||
|
auto destination_instance = configuration.store().get(destination_address);
|
||||||
|
|
||||||
auto count = configuration.stack().pop().get<Value>().to<i32>().value();
|
auto count = configuration.stack().pop().get<Value>().to<i32>().value();
|
||||||
auto source_offset = configuration.stack().pop().get<Value>().to<i32>().value();
|
auto source_offset = configuration.stack().pop().get<Value>().to<i32>().value();
|
||||||
auto destination_offset = configuration.stack().pop().get<Value>().to<i32>().value();
|
auto destination_offset = configuration.stack().pop().get<Value>().to<i32>().value();
|
||||||
|
|
||||||
TRAP_IF_NOT(static_cast<size_t>(source_offset + count) <= instance->data().size());
|
TRAP_IF_NOT(static_cast<size_t>(source_offset + count) <= source_instance->data().size());
|
||||||
TRAP_IF_NOT(static_cast<size_t>(destination_offset + count) <= instance->data().size());
|
TRAP_IF_NOT(static_cast<size_t>(destination_offset + count) <= destination_instance->data().size());
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Instruction synthetic_store_instruction {
|
Instruction synthetic_store_instruction {
|
||||||
Instructions::i32_store8,
|
Instructions::i32_store8,
|
||||||
Instruction::MemoryArgument { 0, 0 }
|
Instruction::MemoryArgument { 0, 0, args.dst_index }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (destination_offset <= source_offset) {
|
if (destination_offset <= source_offset) {
|
||||||
for (auto i = 0; i < count; ++i) {
|
for (auto i = 0; i < count; ++i) {
|
||||||
auto value = instance->data()[source_offset + i];
|
auto value = source_instance->data()[source_offset + i];
|
||||||
store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i);
|
store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto i = count - 1; i >= 0; --i) {
|
for (auto i = count - 1; i >= 0; --i) {
|
||||||
auto value = instance->data()[source_offset + i];
|
auto value = source_instance->data()[source_offset + i];
|
||||||
store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i);
|
store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,8 +830,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
}
|
}
|
||||||
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-init
|
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-init
|
||||||
case Instructions::memory_init.value(): {
|
case Instructions::memory_init.value(): {
|
||||||
auto data_index = instruction.arguments().get<DataIndex>();
|
auto& args = instruction.arguments().get<Instruction::MemoryInitArgs>();
|
||||||
auto& data_address = configuration.frame().module().datas()[data_index.value()];
|
auto& data_address = configuration.frame().module().datas()[args.data_index.value()];
|
||||||
auto& data = *configuration.store().get(data_address);
|
auto& data = *configuration.store().get(data_address);
|
||||||
auto count = *configuration.stack().pop().get<Value>().to<i32>();
|
auto count = *configuration.stack().pop().get<Value>().to<i32>();
|
||||||
auto source_offset = *configuration.stack().pop().get<Value>().to<i32>();
|
auto source_offset = *configuration.stack().pop().get<Value>().to<i32>();
|
||||||
|
@ -836,7 +843,7 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||||
|
|
||||||
Instruction synthetic_store_instruction {
|
Instruction synthetic_store_instruction {
|
||||||
Instructions::i32_store8,
|
Instructions::i32_store8,
|
||||||
Instruction::MemoryArgument { 0, 0 }
|
Instruction::MemoryArgument { 0, 0, args.memory_index }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < (size_t)count; ++i) {
|
for (size_t i = 0; i < (size_t)count; ++i) {
|
||||||
|
|
|
@ -148,11 +148,6 @@ ErrorOr<void, ValidationError> Validator::validate(Module& module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_context.memories.size() > 1) {
|
|
||||||
module.set_validation_status(Module::ValidationStatus::Invalid, {});
|
|
||||||
return Errors::out_of_bounds("memory section count"sv, m_context.memories.size(), 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.set_validation_status(Module::ValidationStatus::Valid, {});
|
module.set_validation_status(Module::ValidationStatus::Valid, {});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -1577,9 +1572,10 @@ VALIDATE_INSTRUCTION(elem_drop)
|
||||||
// https://webassembly.github.io/spec/core/bikeshed/#memory-instructions%E2%91%A2
|
// https://webassembly.github.io/spec/core/bikeshed/#memory-instructions%E2%91%A2
|
||||||
VALIDATE_INSTRUCTION(i32_load)
|
VALIDATE_INSTRUCTION(i32_load)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(i32))
|
if ((1ull << arg.align) > sizeof(i32))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i32));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i32));
|
||||||
|
|
||||||
|
@ -1590,9 +1586,10 @@ VALIDATE_INSTRUCTION(i32_load)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load)
|
VALIDATE_INSTRUCTION(i64_load)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(i64))
|
if ((1ull << arg.align) > sizeof(i64))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i64));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i64));
|
||||||
|
|
||||||
|
@ -1603,9 +1600,10 @@ VALIDATE_INSTRUCTION(i64_load)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(f32_load)
|
VALIDATE_INSTRUCTION(f32_load)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(float))
|
if ((1ull << arg.align) > sizeof(float))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(float));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(float));
|
||||||
|
|
||||||
|
@ -1616,9 +1614,10 @@ VALIDATE_INSTRUCTION(f32_load)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(f64_load)
|
VALIDATE_INSTRUCTION(f64_load)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(double))
|
if ((1ull << arg.align) > sizeof(double))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(double));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(double));
|
||||||
|
|
||||||
|
@ -1629,9 +1628,10 @@ VALIDATE_INSTRUCTION(f64_load)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_load16_s)
|
VALIDATE_INSTRUCTION(i32_load16_s)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1642,9 +1642,10 @@ VALIDATE_INSTRUCTION(i32_load16_s)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_load16_u)
|
VALIDATE_INSTRUCTION(i32_load16_u)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1655,9 +1656,10 @@ VALIDATE_INSTRUCTION(i32_load16_u)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_load8_s)
|
VALIDATE_INSTRUCTION(i32_load8_s)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1668,9 +1670,10 @@ VALIDATE_INSTRUCTION(i32_load8_s)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_load8_u)
|
VALIDATE_INSTRUCTION(i32_load8_u)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1681,9 +1684,10 @@ VALIDATE_INSTRUCTION(i32_load8_u)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load32_s)
|
VALIDATE_INSTRUCTION(i64_load32_s)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 32 / 8)
|
if ((1ull << arg.align) > 32 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
||||||
|
|
||||||
|
@ -1694,9 +1698,10 @@ VALIDATE_INSTRUCTION(i64_load32_s)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load32_u)
|
VALIDATE_INSTRUCTION(i64_load32_u)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 32 / 8)
|
if ((1ull << arg.align) > 32 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
||||||
|
|
||||||
|
@ -1707,9 +1712,10 @@ VALIDATE_INSTRUCTION(i64_load32_u)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load16_s)
|
VALIDATE_INSTRUCTION(i64_load16_s)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1720,9 +1726,10 @@ VALIDATE_INSTRUCTION(i64_load16_s)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load16_u)
|
VALIDATE_INSTRUCTION(i64_load16_u)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1733,9 +1740,10 @@ VALIDATE_INSTRUCTION(i64_load16_u)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load8_s)
|
VALIDATE_INSTRUCTION(i64_load8_s)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1746,9 +1754,10 @@ VALIDATE_INSTRUCTION(i64_load8_s)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_load8_u)
|
VALIDATE_INSTRUCTION(i64_load8_u)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1759,9 +1768,10 @@ VALIDATE_INSTRUCTION(i64_load8_u)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_store)
|
VALIDATE_INSTRUCTION(i32_store)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(i32))
|
if ((1ull << arg.align) > sizeof(i32))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i32));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i32));
|
||||||
|
|
||||||
|
@ -1772,9 +1782,10 @@ VALIDATE_INSTRUCTION(i32_store)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_store)
|
VALIDATE_INSTRUCTION(i64_store)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(i64))
|
if ((1ull << arg.align) > sizeof(i64))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i64));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(i64));
|
||||||
|
|
||||||
|
@ -1785,9 +1796,10 @@ VALIDATE_INSTRUCTION(i64_store)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(f32_store)
|
VALIDATE_INSTRUCTION(f32_store)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(float))
|
if ((1ull << arg.align) > sizeof(float))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(float));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(float));
|
||||||
|
|
||||||
|
@ -1798,9 +1810,10 @@ VALIDATE_INSTRUCTION(f32_store)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(f64_store)
|
VALIDATE_INSTRUCTION(f64_store)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(double))
|
if ((1ull << arg.align) > sizeof(double))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(double));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(double));
|
||||||
|
|
||||||
|
@ -1811,9 +1824,10 @@ VALIDATE_INSTRUCTION(f64_store)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_store16)
|
VALIDATE_INSTRUCTION(i32_store16)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1824,9 +1838,10 @@ VALIDATE_INSTRUCTION(i32_store16)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i32_store8)
|
VALIDATE_INSTRUCTION(i32_store8)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1837,9 +1852,10 @@ VALIDATE_INSTRUCTION(i32_store8)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_store32)
|
VALIDATE_INSTRUCTION(i64_store32)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 32 / 8)
|
if ((1ull << arg.align) > 32 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 32 / 8);
|
||||||
|
|
||||||
|
@ -1850,9 +1866,10 @@ VALIDATE_INSTRUCTION(i64_store32)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_store16)
|
VALIDATE_INSTRUCTION(i64_store16)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 16 / 8)
|
if ((1ull << arg.align) > 16 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 16 / 8);
|
||||||
|
|
||||||
|
@ -1863,9 +1880,10 @@ VALIDATE_INSTRUCTION(i64_store16)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(i64_store8)
|
VALIDATE_INSTRUCTION(i64_store8)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > 8 / 8)
|
if ((1ull << arg.align) > 8 / 8)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, 8 / 8);
|
||||||
|
|
||||||
|
@ -1876,7 +1894,7 @@ VALIDATE_INSTRUCTION(i64_store8)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(memory_size)
|
VALIDATE_INSTRUCTION(memory_size)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(instruction.arguments().get<Instruction::MemoryIndexArgument>().memory_index));
|
||||||
|
|
||||||
stack.append(ValueType(ValueType::I32));
|
stack.append(ValueType(ValueType::I32));
|
||||||
return {};
|
return {};
|
||||||
|
@ -1884,7 +1902,8 @@ VALIDATE_INSTRUCTION(memory_size)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(memory_grow)
|
VALIDATE_INSTRUCTION(memory_grow)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(instruction.arguments().get<Instruction::MemoryIndexArgument>().memory_index));
|
||||||
|
|
||||||
TRY((stack.take<ValueType::I32>()));
|
TRY((stack.take<ValueType::I32>()));
|
||||||
stack.append(ValueType(ValueType::I32));
|
stack.append(ValueType(ValueType::I32));
|
||||||
|
|
||||||
|
@ -1893,7 +1912,7 @@ VALIDATE_INSTRUCTION(memory_grow)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(memory_fill)
|
VALIDATE_INSTRUCTION(memory_fill)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(instruction.arguments().get<Instruction::MemoryIndexArgument>().memory_index));
|
||||||
|
|
||||||
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
||||||
|
|
||||||
|
@ -1902,7 +1921,9 @@ VALIDATE_INSTRUCTION(memory_fill)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(memory_copy)
|
VALIDATE_INSTRUCTION(memory_copy)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
auto& args = instruction.arguments().get<Instruction::MemoryCopyArgs>();
|
||||||
|
TRY(validate(args.src_index));
|
||||||
|
TRY(validate(args.dst_index));
|
||||||
|
|
||||||
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
||||||
|
|
||||||
|
@ -1911,10 +1932,11 @@ VALIDATE_INSTRUCTION(memory_copy)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(memory_init)
|
VALIDATE_INSTRUCTION(memory_init)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto index = instruction.arguments().get<DataIndex>();
|
auto& args = instruction.arguments().get<Instruction::MemoryInitArgs>();
|
||||||
TRY(validate(index));
|
|
||||||
|
TRY(validate(args.memory_index));
|
||||||
|
TRY(validate(args.data_index));
|
||||||
|
|
||||||
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
||||||
|
|
||||||
|
@ -2183,9 +2205,10 @@ VALIDATE_INSTRUCTION(call_indirect)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(v128_load)
|
VALIDATE_INSTRUCTION(v128_load)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(u128))
|
if ((1ull << arg.align) > sizeof(u128))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(u128));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(u128));
|
||||||
|
|
||||||
|
@ -2201,7 +2224,7 @@ VALIDATE_INSTRUCTION(v128_load8x8_s)
|
||||||
constexpr auto M = 8;
|
constexpr auto M = 8;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2216,7 +2239,7 @@ VALIDATE_INSTRUCTION(v128_load8x8_u)
|
||||||
constexpr auto M = 8;
|
constexpr auto M = 8;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2231,7 +2254,7 @@ VALIDATE_INSTRUCTION(v128_load16x4_s)
|
||||||
constexpr auto M = 4;
|
constexpr auto M = 4;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2246,7 +2269,7 @@ VALIDATE_INSTRUCTION(v128_load16x4_u)
|
||||||
constexpr auto M = 4;
|
constexpr auto M = 4;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2261,7 +2284,7 @@ VALIDATE_INSTRUCTION(v128_load32x2_s)
|
||||||
constexpr auto M = 2;
|
constexpr auto M = 2;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2276,7 +2299,7 @@ VALIDATE_INSTRUCTION(v128_load32x2_u)
|
||||||
constexpr auto M = 2;
|
constexpr auto M = 2;
|
||||||
constexpr auto max_alignment = N * M / 8;
|
constexpr auto max_alignment = N * M / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2290,7 +2313,7 @@ VALIDATE_INSTRUCTION(v128_load8_splat)
|
||||||
constexpr auto N = 8;
|
constexpr auto N = 8;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2304,7 +2327,7 @@ VALIDATE_INSTRUCTION(v128_load16_splat)
|
||||||
constexpr auto N = 16;
|
constexpr auto N = 16;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2318,7 +2341,7 @@ VALIDATE_INSTRUCTION(v128_load32_splat)
|
||||||
constexpr auto N = 32;
|
constexpr auto N = 32;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2332,7 +2355,7 @@ VALIDATE_INSTRUCTION(v128_load64_splat)
|
||||||
constexpr auto N = 64;
|
constexpr auto N = 64;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -2342,9 +2365,10 @@ VALIDATE_INSTRUCTION(v128_load64_splat)
|
||||||
|
|
||||||
VALIDATE_INSTRUCTION(v128_store)
|
VALIDATE_INSTRUCTION(v128_store)
|
||||||
{
|
{
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
|
||||||
|
|
||||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||||
|
|
||||||
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1ull << arg.align) > sizeof(u128))
|
if ((1ull << arg.align) > sizeof(u128))
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(u128));
|
return Errors::out_of_bounds("memory op alignment"sv, 1ull << arg.align, 0, sizeof(u128));
|
||||||
|
|
||||||
|
@ -2865,7 +2889,7 @@ VALIDATE_INSTRUCTION(v128_load8_lane)
|
||||||
if (arg.lane > max_lane)
|
if (arg.lane > max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2883,7 +2907,7 @@ VALIDATE_INSTRUCTION(v128_load16_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2901,7 +2925,7 @@ VALIDATE_INSTRUCTION(v128_load32_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2919,7 +2943,7 @@ VALIDATE_INSTRUCTION(v128_load64_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if (arg.memory.align > max_alignment)
|
if (arg.memory.align > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2937,7 +2961,7 @@ VALIDATE_INSTRUCTION(v128_store8_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2955,7 +2979,7 @@ VALIDATE_INSTRUCTION(v128_store16_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2973,7 +2997,7 @@ VALIDATE_INSTRUCTION(v128_store32_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -2991,7 +3015,7 @@ VALIDATE_INSTRUCTION(v128_store64_lane)
|
||||||
if (arg.lane >= max_lane)
|
if (arg.lane >= max_lane)
|
||||||
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
return Errors::out_of_bounds("lane index"sv, arg.lane, 0u, max_lane);
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.memory.align) > max_alignment)
|
if ((1 << arg.memory.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.memory.align, 0u, max_alignment);
|
||||||
|
@ -3005,7 +3029,7 @@ VALIDATE_INSTRUCTION(v128_load32_zero)
|
||||||
constexpr auto N = 32;
|
constexpr auto N = 32;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
@ -3019,7 +3043,7 @@ VALIDATE_INSTRUCTION(v128_load64_zero)
|
||||||
constexpr auto N = 64;
|
constexpr auto N = 64;
|
||||||
constexpr auto max_alignment = N / 8;
|
constexpr auto max_alignment = N / 8;
|
||||||
|
|
||||||
TRY(validate(MemoryIndex { 0 }));
|
TRY(validate(arg.memory_index));
|
||||||
|
|
||||||
if ((1 << arg.align) > max_alignment)
|
if ((1 << arg.align) > max_alignment)
|
||||||
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
return Errors::out_of_bounds("memory op alignment"sv, 1 << arg.align, 0u, max_alignment);
|
||||||
|
|
|
@ -418,18 +418,28 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
case Instructions::i64_store8.value():
|
case Instructions::i64_store8.value():
|
||||||
case Instructions::i64_store16.value():
|
case Instructions::i64_store16.value():
|
||||||
case Instructions::i64_store32.value(): {
|
case Instructions::i64_store32.value(): {
|
||||||
// op (align offset)
|
// op (align [multi-memory: memindex] offset)
|
||||||
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (align_or_error.is_error())
|
if (align_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
size_t align = align_or_error.release_value();
|
size_t align = align_or_error.release_value();
|
||||||
|
|
||||||
|
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||||
|
size_t memory_index = 0;
|
||||||
|
if ((align & 0x20) != 0) {
|
||||||
|
align &= ~0x20;
|
||||||
|
auto memory_index_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
|
if (memory_index_or_error.is_error())
|
||||||
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
memory_index = memory_index_or_error.release_value();
|
||||||
|
}
|
||||||
|
|
||||||
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (offset_or_error.is_error())
|
if (offset_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
size_t offset = offset_or_error.release_value();
|
size_t offset = offset_or_error.release_value();
|
||||||
|
|
||||||
resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } });
|
resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::local_get.value():
|
case Instructions::local_get.value():
|
||||||
|
@ -453,19 +463,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
}
|
}
|
||||||
case Instructions::memory_size.value():
|
case Instructions::memory_size.value():
|
||||||
case Instructions::memory_grow.value(): {
|
case Instructions::memory_grow.value(): {
|
||||||
// op 0x0
|
// op [multi-memory: memindex]|0x00
|
||||||
// The zero is currently unused.
|
|
||||||
auto unused_or_error = stream.read_value<u8>();
|
auto memory_index_or_error = stream.read_value<u8>();
|
||||||
if (unused_or_error.is_error())
|
if (memory_index_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||||
|
|
||||||
auto unused = unused_or_error.release_value();
|
auto memory_index = memory_index_or_error.release_value();
|
||||||
if (unused != 0x00) {
|
|
||||||
dbgln("Invalid tag in memory_grow {}", unused);
|
|
||||||
return with_eof_check(stream, ParseError::InvalidTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
resulting_instructions.append(Instruction { opcode });
|
resulting_instructions.append(Instruction { opcode, MemoryIndexArgument { MemoryIndex(memory_index) } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::i32_const.value(): {
|
case Instructions::i32_const.value(): {
|
||||||
|
@ -704,14 +710,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
auto index = GenericIndexParser<DataIndex>::parse(stream);
|
auto index = GenericIndexParser<DataIndex>::parse(stream);
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
auto unused_or_error = stream.read_value<u8>();
|
|
||||||
if (unused_or_error.is_error())
|
// Proposal "multi-memory", literal 0x00 is replaced with a memory index.
|
||||||
|
auto memory_index_or_error = stream.read_value<u8>();
|
||||||
|
if (memory_index_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
|
||||||
auto unused = unused_or_error.release_value();
|
auto memory_index = memory_index_or_error.release_value();
|
||||||
if (unused != 0x00)
|
|
||||||
return ParseError::InvalidImmediate;
|
resulting_instructions.append(Instruction { full_opcode, MemoryInitArgs { index.release_value(), MemoryIndex(memory_index) } });
|
||||||
resulting_instructions.append(Instruction { full_opcode, index.release_value() });
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::data_drop.value(): {
|
case Instructions::data_drop.value(): {
|
||||||
|
@ -722,27 +729,27 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::memory_copy.value(): {
|
case Instructions::memory_copy.value(): {
|
||||||
|
// Proposal "multi-memory", literal 0x00 is replaced with two memory indices, destination and source, respectively.
|
||||||
|
MemoryIndex indices[] = { 0, 0 };
|
||||||
|
|
||||||
for (size_t i = 0; i < 2; ++i) {
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
auto unused_or_error = stream.read_value<u8>();
|
auto memory_index_or_error = stream.read_value<u8>();
|
||||||
if (unused_or_error.is_error())
|
if (memory_index_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
|
||||||
auto unused = unused_or_error.release_value();
|
indices[i] = memory_index_or_error.release_value();
|
||||||
if (unused != 0x00)
|
|
||||||
return ParseError::InvalidImmediate;
|
|
||||||
}
|
}
|
||||||
resulting_instructions.append(Instruction { full_opcode });
|
resulting_instructions.append(Instruction { full_opcode, MemoryCopyArgs { indices[1], indices[0] } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::memory_fill.value(): {
|
case Instructions::memory_fill.value(): {
|
||||||
auto unused_or_error = stream.read_value<u8>();
|
// Proposal "multi-memory", literal 0x00 is replaced with a memory index.
|
||||||
if (unused_or_error.is_error())
|
auto memory_index_or_error = stream.read_value<u8>();
|
||||||
|
if (memory_index_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
|
||||||
auto unused = unused_or_error.release_value();
|
auto memory_index = memory_index_or_error.release_value();
|
||||||
if (unused != 0x00)
|
resulting_instructions.append(Instruction { full_opcode, MemoryIndexArgument { MemoryIndex { memory_index } } });
|
||||||
return ParseError::InvalidImmediate;
|
|
||||||
resulting_instructions.append(Instruction { full_opcode });
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::table_init.value(): {
|
case Instructions::table_init.value(): {
|
||||||
|
@ -793,17 +800,28 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
case Instructions::v128_load32_splat.value():
|
case Instructions::v128_load32_splat.value():
|
||||||
case Instructions::v128_load64_splat.value():
|
case Instructions::v128_load64_splat.value():
|
||||||
case Instructions::v128_store.value(): {
|
case Instructions::v128_store.value(): {
|
||||||
// op (align offset)
|
// op (align [multi-memory memindex] offset)
|
||||||
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (align_or_error.is_error())
|
if (align_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||||
size_t align = align_or_error.release_value();
|
size_t align = align_or_error.release_value();
|
||||||
|
|
||||||
|
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||||
|
size_t memory_index = 0;
|
||||||
|
if ((align & 0x20) != 0) {
|
||||||
|
align &= ~0x20;
|
||||||
|
auto memory_index_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
|
if (memory_index_or_error.is_error())
|
||||||
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
memory_index = memory_index_or_error.release_value();
|
||||||
|
}
|
||||||
|
|
||||||
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (offset_or_error.is_error())
|
if (offset_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||||
size_t offset = offset_or_error.release_value();
|
size_t offset = offset_or_error.release_value();
|
||||||
|
|
||||||
resulting_instructions.append(Instruction { full_opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } });
|
resulting_instructions.append(Instruction { full_opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::v128_load8_lane.value():
|
case Instructions::v128_load8_lane.value():
|
||||||
|
@ -814,11 +832,22 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
case Instructions::v128_store16_lane.value():
|
case Instructions::v128_store16_lane.value():
|
||||||
case Instructions::v128_store32_lane.value():
|
case Instructions::v128_store32_lane.value():
|
||||||
case Instructions::v128_store64_lane.value(): {
|
case Instructions::v128_store64_lane.value(): {
|
||||||
// op (align offset) (index)
|
// op (align [multi-memory: memindex] offset) (index)
|
||||||
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
auto align_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (align_or_error.is_error())
|
if (align_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||||
size_t align = align_or_error.release_value();
|
size_t align = align_or_error.release_value();
|
||||||
|
|
||||||
|
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||||
|
size_t memory_index = 0;
|
||||||
|
if ((align & 0x20) != 0) {
|
||||||
|
align &= ~0x20;
|
||||||
|
auto memory_index_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
|
if (memory_index_or_error.is_error())
|
||||||
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
memory_index = memory_index_or_error.release_value();
|
||||||
|
}
|
||||||
|
|
||||||
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
auto offset_or_error = stream.read_value<LEB128<size_t>>();
|
||||||
if (offset_or_error.is_error())
|
if (offset_or_error.is_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||||
|
@ -829,7 +858,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
auto index = index_or_error.release_value();
|
auto index = index_or_error.release_value();
|
||||||
|
|
||||||
resulting_instructions.append(Instruction { full_opcode, MemoryAndLaneArgument { { static_cast<u32>(align), static_cast<u32>(offset) }, index } });
|
resulting_instructions.append(Instruction { full_opcode, MemoryAndLaneArgument { { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) }, index } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::v128_const.value(): {
|
case Instructions::v128_const.value(): {
|
||||||
|
|
|
@ -432,8 +432,11 @@ void Printer::print(Wasm::Instruction const& instruction)
|
||||||
[&](LocalIndex const& index) { print("(local index {})", index.value()); },
|
[&](LocalIndex const& index) { print("(local index {})", index.value()); },
|
||||||
[&](TableIndex const& index) { print("(table index {})", index.value()); },
|
[&](TableIndex const& index) { print("(table index {})", index.value()); },
|
||||||
[&](Instruction::IndirectCallArgs const& args) { print("(indirect (type index {}) (table index {}))", args.type.value(), args.table.value()); },
|
[&](Instruction::IndirectCallArgs const& args) { print("(indirect (type index {}) (table index {}))", args.type.value(), args.table.value()); },
|
||||||
[&](Instruction::MemoryArgument const& args) { print("(memory (align {}) (offset {}))", args.align, args.offset); },
|
[&](Instruction::MemoryArgument const& args) { print("(memory index {} (align {}) (offset {}))", args.memory_index.value(), args.align, args.offset); },
|
||||||
[&](Instruction::MemoryAndLaneArgument const& args) { print("(memory (align {}) (offset {})) (lane {})", args.memory.align, args.memory.offset, args.lane); },
|
[&](Instruction::MemoryAndLaneArgument const& args) { print("(memory index {} (align {}) (offset {})) (lane {})", args.memory.memory_index.value(), args.memory.align, args.memory.offset, args.lane); },
|
||||||
|
[&](Instruction::MemoryInitArgs const& args) { print("(memory index {}) (data index {})", args.memory_index.value(), args.data_index.value()); },
|
||||||
|
[&](Instruction::MemoryCopyArgs const& args) { print("(from (memory index {}) to (memory index {}))", args.src_index.value(), args.dst_index.value()); },
|
||||||
|
[&](Instruction::MemoryIndexArgument const& args) { print("(memory index {})", args.memory_index.value()); },
|
||||||
[&](Instruction::LaneIndex const& args) { print("(lane {})", args.lane); },
|
[&](Instruction::LaneIndex const& args) { print("(lane {})", args.lane); },
|
||||||
[&](Instruction::ShuffleArgument const& args) {
|
[&](Instruction::ShuffleArgument const& args) {
|
||||||
print("{{ {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} }}",
|
print("{{ {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} }}",
|
||||||
|
|
|
@ -410,6 +410,7 @@ public:
|
||||||
struct MemoryArgument {
|
struct MemoryArgument {
|
||||||
u32 align;
|
u32 align;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
MemoryIndex memory_index { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryAndLaneArgument {
|
struct MemoryAndLaneArgument {
|
||||||
|
@ -421,6 +422,21 @@ public:
|
||||||
u8 lane;
|
u8 lane;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Proposal "multi-memory"
|
||||||
|
struct MemoryCopyArgs {
|
||||||
|
MemoryIndex src_index;
|
||||||
|
MemoryIndex dst_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemoryInitArgs {
|
||||||
|
DataIndex data_index;
|
||||||
|
MemoryIndex memory_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemoryIndexArgument {
|
||||||
|
MemoryIndex memory_index;
|
||||||
|
};
|
||||||
|
|
||||||
struct ShuffleArgument {
|
struct ShuffleArgument {
|
||||||
explicit ShuffleArgument(u8 (&lanes)[16])
|
explicit ShuffleArgument(u8 (&lanes)[16])
|
||||||
: lanes {
|
: lanes {
|
||||||
|
@ -460,6 +476,9 @@ private:
|
||||||
LocalIndex,
|
LocalIndex,
|
||||||
MemoryArgument,
|
MemoryArgument,
|
||||||
MemoryAndLaneArgument,
|
MemoryAndLaneArgument,
|
||||||
|
MemoryCopyArgs,
|
||||||
|
MemoryIndexArgument,
|
||||||
|
MemoryInitArgs,
|
||||||
StructuredInstructionArgs,
|
StructuredInstructionArgs,
|
||||||
ShuffleArgument,
|
ShuffleArgument,
|
||||||
TableBranchArgs,
|
TableBranchArgs,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue