mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-26 19:32:06 -05:00
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:
parent
29b193d25d
commit
207379165f
2 changed files with 12 additions and 8 deletions
|
@ -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(): {
|
||||
|
|
|
@ -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 } });
|
||||
|
|
Loading…
Add table
Reference in a new issue