LibWasm: Fix nested structured instruction parsing

Previously, the ip would not be propagated correctly, and we would
produce invalid jumps when more than one level of nesting was involved.
This makes loops work :P
This commit is contained in:
Ali Mohammad Pur 2021-05-18 00:23:41 +04:30 committed by Linus Groh
parent 29b193d25d
commit 207379165f
Notes: sideshowbarker 2024-07-18 17:39:30 +09:00
2 changed files with 12 additions and 8 deletions

View file

@ -28,10 +28,12 @@ void Interpreter::interpret(Configuration& configuration)
while (current_ip_value < max_ip_value) {
auto& instruction = instructions[current_ip_value.value()];
auto old_ip = current_ip_value;
interpret(configuration, current_ip_value, instruction);
if (m_do_trap)
return;
++current_ip_value;
if (current_ip_value == old_ip) // If no jump occurred
++current_ip_value;
}
}
@ -46,18 +48,19 @@ void Interpreter::branch_to_label(Configuration& configuration, LabelIndex index
size_t drop_count = index.value() + 1;
for (; !configuration.stack().is_empty();) {
auto entry = configuration.stack().pop();
auto& entry = configuration.stack().peek();
if (entry.has<NonnullOwnPtr<Label>>()) {
if (drop_count-- == 0)
break;
}
configuration.stack().pop();
}
// Push results in reverse
for (size_t i = results.size(); i > 0; --i)
configuration.stack().push(move(static_cast<Vector<NonnullOwnPtr<Value>>&>(results)[i - 1]));
configuration.ip() = label->continuation() + 1;
configuration.ip() = label->continuation();
}
ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
@ -321,7 +324,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
if (args.block_type.kind() != BlockType::Empty)
arity = 1;
configuration.stack().push(make<Label>(arity, ip.value() + 1));
configuration.stack().push(make<Label>(arity, ip.value()));
return;
}
case Instructions::if_.value(): {

View file

@ -82,7 +82,7 @@ struct ParseUntilAnyOfResult {
Vector<T> values;
};
template<typename T, u8... terminators, typename... Args>
static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(InputStream& stream, Args... args) requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...); })
static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(InputStream& stream, Args&... args) requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...); })
{
ScopeLogger<WASM_BINPARSER_DEBUG> logger;
ReconsumableStream new_stream { stream };
@ -305,7 +305,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
result.value().values.append(Instruction { Instructions::structured_end });
// Transform op(..., instr*) -> op(...) instr* op(end(ip))
result.value().values.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, ++ip, {} } });
result.value().values.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, ip.value(), {} } });
++ip;
return result.release_value().values;
}
@ -314,7 +315,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
instructions.append(result.release_value().values);
instructions.append(Instruction { Instructions::structured_else });
++ip;
else_ip = ip;
else_ip = ip.value();
}
// if with else
{
@ -324,7 +325,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
instructions.append(result.release_value().values);
instructions.append(Instruction { Instructions::structured_end });
++ip;
end_ip = ip;
end_ip = ip.value();
}
instructions.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, end_ip, else_ip } });