mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-05 05:56:53 +03:00
LibWasm: Implement the multi-memory proposal
This commit is contained in:
parent
f4515aae80
commit
22d411345d
Notes:
sideshowbarker
2024-07-17 08:55:54 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/22d411345d Pull-request: https://github.com/SerenityOS/serenity/pull/21549
@ -88,13 +88,13 @@ void BytecodeInterpreter::branch_to_label(Configuration& configuration, LabelInd
|
||||
template<typename ReadType, typename PushType>
|
||||
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);
|
||||
if (!memory) {
|
||||
m_trap = Trap { "Nonexistent memory" };
|
||||
return;
|
||||
}
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
auto& entry = configuration.stack().peek();
|
||||
auto base = entry.get<Value>().to<i32>();
|
||||
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>
|
||||
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);
|
||||
if (!memory) {
|
||||
m_trap = Trap { "Nonexistent memory" };
|
||||
return;
|
||||
}
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
auto& entry = configuration.stack().peek();
|
||||
auto base = entry.get<Value>().to<i32>();
|
||||
if (!base.has_value()) {
|
||||
@ -161,13 +161,13 @@ void BytecodeInterpreter::load_and_push_mxn(Configuration& configuration, Instru
|
||||
template<size_t M>
|
||||
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);
|
||||
if (!memory) {
|
||||
m_trap = Trap { "Nonexistent memory" };
|
||||
return;
|
||||
}
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
auto& entry = configuration.stack().peek();
|
||||
auto base = entry.get<Value>().to<i32>();
|
||||
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)
|
||||
{
|
||||
auto& address = configuration.frame().module().memories().first();
|
||||
auto memory = configuration.store().get(address);
|
||||
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;
|
||||
Checked addition { instance_address };
|
||||
addition += data.size();
|
||||
@ -745,7 +745,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||
return;
|
||||
}
|
||||
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 pages = instance->size() / Constants::page_size;
|
||||
dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
|
||||
@ -753,7 +754,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||
return;
|
||||
}
|
||||
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);
|
||||
i32 old_pages = instance->size() / Constants::page_size;
|
||||
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
|
||||
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 count = 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
|
||||
case Instructions::memory_copy.value(): {
|
||||
auto address = configuration.frame().module().memories()[0];
|
||||
auto instance = configuration.store().get(address);
|
||||
auto& args = instruction.arguments().get<Instruction::MemoryCopyArgs>();
|
||||
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 source_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>(destination_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) <= destination_instance->data().size());
|
||||
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
Instruction synthetic_store_instruction {
|
||||
Instructions::i32_store8,
|
||||
Instruction::MemoryArgument { 0, 0 }
|
||||
Instruction::MemoryArgument { 0, 0, args.dst_index }
|
||||
};
|
||||
|
||||
if (destination_offset <= source_offset) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -823,8 +830,8 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
|
||||
}
|
||||
// https://webassembly.github.io/spec/core/bikeshed/#exec-memory-init
|
||||
case Instructions::memory_init.value(): {
|
||||
auto data_index = instruction.arguments().get<DataIndex>();
|
||||
auto& data_address = configuration.frame().module().datas()[data_index.value()];
|
||||
auto& args = instruction.arguments().get<Instruction::MemoryInitArgs>();
|
||||
auto& data_address = configuration.frame().module().datas()[args.data_index.value()];
|
||||
auto& data = *configuration.store().get(data_address);
|
||||
auto count = *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 {
|
||||
Instructions::i32_store8,
|
||||
Instruction::MemoryArgument { 0, 0 }
|
||||
Instruction::MemoryArgument { 0, 0, args.memory_index }
|
||||
};
|
||||
|
||||
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, {});
|
||||
return {};
|
||||
}
|
||||
@ -1577,9 +1572,10 @@ VALIDATE_INSTRUCTION(elem_drop)
|
||||
// https://webassembly.github.io/spec/core/bikeshed/#memory-instructions%E2%91%A2
|
||||
VALIDATE_INSTRUCTION(i32_load)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(instruction.arguments().get<Instruction::MemoryIndexArgument>().memory_index));
|
||||
|
||||
stack.append(ValueType(ValueType::I32));
|
||||
return {};
|
||||
@ -1884,7 +1902,8 @@ VALIDATE_INSTRUCTION(memory_size)
|
||||
|
||||
VALIDATE_INSTRUCTION(memory_grow)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(instruction.arguments().get<Instruction::MemoryIndexArgument>().memory_index));
|
||||
|
||||
TRY((stack.take<ValueType::I32>()));
|
||||
stack.append(ValueType(ValueType::I32));
|
||||
|
||||
@ -1893,7 +1912,7 @@ VALIDATE_INSTRUCTION(memory_grow)
|
||||
|
||||
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>()));
|
||||
|
||||
@ -1902,7 +1921,9 @@ VALIDATE_INSTRUCTION(memory_fill)
|
||||
|
||||
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>()));
|
||||
|
||||
@ -1911,10 +1932,11 @@ VALIDATE_INSTRUCTION(memory_copy)
|
||||
|
||||
VALIDATE_INSTRUCTION(memory_init)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto index = instruction.arguments().get<DataIndex>();
|
||||
TRY(validate(index));
|
||||
auto& args = instruction.arguments().get<Instruction::MemoryInitArgs>();
|
||||
|
||||
TRY(validate(args.memory_index));
|
||||
TRY(validate(args.data_index));
|
||||
|
||||
TRY((stack.take<ValueType::I32, ValueType::I32, ValueType::I32>()));
|
||||
|
||||
@ -2183,9 +2205,10 @@ VALIDATE_INSTRUCTION(call_indirect)
|
||||
|
||||
VALIDATE_INSTRUCTION(v128_load)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N * M / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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)
|
||||
{
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
|
||||
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
|
||||
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1ull << arg.align) > 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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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 max_alignment = N / 8;
|
||||
|
||||
TRY(validate(MemoryIndex { 0 }));
|
||||
TRY(validate(arg.memory_index));
|
||||
|
||||
if ((1 << arg.align) > 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_store16.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>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
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>>();
|
||||
if (offset_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
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;
|
||||
}
|
||||
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_grow.value(): {
|
||||
// op 0x0
|
||||
// The zero is currently unused.
|
||||
auto unused_or_error = stream.read_value<u8>();
|
||||
if (unused_or_error.is_error())
|
||||
// op [multi-memory: memindex]|0x00
|
||||
|
||||
auto memory_index_or_error = stream.read_value<u8>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto unused = unused_or_error.release_value();
|
||||
if (unused != 0x00) {
|
||||
dbgln("Invalid tag in memory_grow {}", unused);
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
}
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
|
||||
resulting_instructions.append(Instruction { opcode });
|
||||
resulting_instructions.append(Instruction { opcode, MemoryIndexArgument { MemoryIndex(memory_index) } });
|
||||
break;
|
||||
}
|
||||
case Instructions::i32_const.value(): {
|
||||
@ -704,14 +710,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||
auto index = GenericIndexParser<DataIndex>::parse(stream);
|
||||
if (index.is_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);
|
||||
|
||||
auto unused = unused_or_error.release_value();
|
||||
if (unused != 0x00)
|
||||
return ParseError::InvalidImmediate;
|
||||
resulting_instructions.append(Instruction { full_opcode, index.release_value() });
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
|
||||
resulting_instructions.append(Instruction { full_opcode, MemoryInitArgs { index.release_value(), MemoryIndex(memory_index) } });
|
||||
break;
|
||||
}
|
||||
case Instructions::data_drop.value(): {
|
||||
@ -722,27 +729,27 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
auto unused_or_error = stream.read_value<u8>();
|
||||
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);
|
||||
|
||||
auto unused = unused_or_error.release_value();
|
||||
if (unused != 0x00)
|
||||
return ParseError::InvalidImmediate;
|
||||
indices[i] = memory_index_or_error.release_value();
|
||||
}
|
||||
resulting_instructions.append(Instruction { full_opcode });
|
||||
resulting_instructions.append(Instruction { full_opcode, MemoryCopyArgs { indices[1], indices[0] } });
|
||||
break;
|
||||
}
|
||||
case Instructions::memory_fill.value(): {
|
||||
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);
|
||||
|
||||
auto unused = unused_or_error.release_value();
|
||||
if (unused != 0x00)
|
||||
return ParseError::InvalidImmediate;
|
||||
resulting_instructions.append(Instruction { full_opcode });
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
resulting_instructions.append(Instruction { full_opcode, MemoryIndexArgument { MemoryIndex { memory_index } } });
|
||||
break;
|
||||
}
|
||||
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_load64_splat.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>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
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>>();
|
||||
if (offset_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
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;
|
||||
}
|
||||
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_store32_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>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
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>>();
|
||||
if (offset_or_error.is_error())
|
||||
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);
|
||||
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;
|
||||
}
|
||||
case Instructions::v128_const.value(): {
|
||||
|
@ -432,8 +432,11 @@ void Printer::print(Wasm::Instruction const& instruction)
|
||||
[&](LocalIndex const& index) { print("(local 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::MemoryArgument const& args) { print("(memory (align {}) (offset {}))", args.align, args.offset); },
|
||||
[&](Instruction::MemoryAndLaneArgument const& args) { print("(memory (align {}) (offset {})) (lane {})", args.memory.align, args.memory.offset, args.lane); },
|
||||
[&](Instruction::MemoryArgument const& args) { print("(memory index {} (align {}) (offset {}))", args.memory_index.value(), args.align, args.offset); },
|
||||
[&](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::ShuffleArgument const& args) {
|
||||
print("{{ {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} }}",
|
||||
|
@ -410,6 +410,7 @@ public:
|
||||
struct MemoryArgument {
|
||||
u32 align;
|
||||
u32 offset;
|
||||
MemoryIndex memory_index { 0 };
|
||||
};
|
||||
|
||||
struct MemoryAndLaneArgument {
|
||||
@ -421,6 +422,21 @@ public:
|
||||
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 {
|
||||
explicit ShuffleArgument(u8 (&lanes)[16])
|
||||
: lanes {
|
||||
@ -460,6 +476,9 @@ private:
|
||||
LocalIndex,
|
||||
MemoryArgument,
|
||||
MemoryAndLaneArgument,
|
||||
MemoryCopyArgs,
|
||||
MemoryIndexArgument,
|
||||
MemoryInitArgs,
|
||||
StructuredInstructionArgs,
|
||||
ShuffleArgument,
|
||||
TableBranchArgs,
|
||||
|
Loading…
Reference in New Issue
Block a user