mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:47:35 +00:00
LibWasm: Avoid parsing if/block/loop instructions recursively
This commit is contained in:
parent
f6830eaf73
commit
0d1471e72f
1 changed files with 462 additions and 426 deletions
|
@ -277,11 +277,52 @@ ParseResult<BlockType> BlockType::parse(InputStream& stream)
|
||||||
|
|
||||||
ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, InstructionPointer& ip)
|
ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, InstructionPointer& ip)
|
||||||
{
|
{
|
||||||
|
struct NestedInstructionState {
|
||||||
|
Vector<Instruction> prior_instructions;
|
||||||
|
OpCode opcode;
|
||||||
|
BlockType block_type;
|
||||||
|
InstructionPointer end_ip;
|
||||||
|
Optional<InstructionPointer> else_ip;
|
||||||
|
};
|
||||||
|
Vector<NestedInstructionState, 4> nested_instructions;
|
||||||
|
Vector<Instruction> resulting_instructions;
|
||||||
|
|
||||||
|
do {
|
||||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv);
|
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv);
|
||||||
u8 byte;
|
u8 byte;
|
||||||
stream >> byte;
|
stream >> byte;
|
||||||
if (stream.has_any_error())
|
if (stream.has_any_error())
|
||||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||||
|
|
||||||
|
if (!nested_instructions.is_empty()) {
|
||||||
|
auto& nested_structure = nested_instructions.last();
|
||||||
|
if (byte == 0x0b) {
|
||||||
|
// block/loop/if end
|
||||||
|
nested_structure.end_ip = ip + (nested_structure.else_ip.has_value() ? 1 : 0);
|
||||||
|
++ip;
|
||||||
|
|
||||||
|
// Transform op(..., instr*) -> op(...) instr* op(end(ip))
|
||||||
|
auto instructions = move(nested_structure.prior_instructions);
|
||||||
|
instructions.ensure_capacity(instructions.size() + 2 + resulting_instructions.size());
|
||||||
|
instructions.append(Instruction { nested_structure.opcode, StructuredInstructionArgs { nested_structure.block_type, nested_structure.end_ip, nested_structure.else_ip } });
|
||||||
|
instructions.extend(move(resulting_instructions));
|
||||||
|
instructions.append(Instruction { Instructions::structured_end });
|
||||||
|
resulting_instructions = move(instructions);
|
||||||
|
nested_instructions.take_last();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byte == 0x05) {
|
||||||
|
// if...else
|
||||||
|
|
||||||
|
// Transform op(..., instr*, instr*) -> op(...) instr* op(else(ip) instr* op(end(ip))
|
||||||
|
resulting_instructions.append(Instruction { Instructions::structured_else });
|
||||||
|
++ip;
|
||||||
|
nested_structure.else_ip = ip.value();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OpCode opcode { byte };
|
OpCode opcode { byte };
|
||||||
++ip;
|
++ip;
|
||||||
|
|
||||||
|
@ -292,44 +333,10 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
auto block_type = BlockType::parse(stream);
|
auto block_type = BlockType::parse(stream);
|
||||||
if (block_type.is_error())
|
if (block_type.is_error())
|
||||||
return block_type.error();
|
return block_type.error();
|
||||||
Vector<Instruction> instructions;
|
|
||||||
InstructionPointer end_ip, else_ip;
|
|
||||||
|
|
||||||
{
|
nested_instructions.append({ move(resulting_instructions), opcode, block_type.release_value(), {}, {} });
|
||||||
auto result = parse_until_any_of<Instruction, 0x0b, 0x05>(stream, ip);
|
resulting_instructions = {};
|
||||||
if (result.is_error())
|
break;
|
||||||
return result.error();
|
|
||||||
|
|
||||||
if (result.value().terminator == 0x0b) {
|
|
||||||
// block/loop/if without else
|
|
||||||
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.value(), {} } });
|
|
||||||
++ip;
|
|
||||||
return result.release_value().values;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform op(..., instr*, instr*) -> op(...) instr* op(else(ip) instr* op(end(ip))
|
|
||||||
VERIFY(result.value().terminator == 0x05);
|
|
||||||
instructions.extend(result.release_value().values);
|
|
||||||
instructions.append(Instruction { Instructions::structured_else });
|
|
||||||
++ip;
|
|
||||||
else_ip = ip.value();
|
|
||||||
}
|
|
||||||
// if with else
|
|
||||||
{
|
|
||||||
auto result = parse_until_any_of<Instruction, 0x0b>(stream, ip);
|
|
||||||
if (result.is_error())
|
|
||||||
return result.error();
|
|
||||||
instructions.extend(result.release_value().values);
|
|
||||||
instructions.append(Instruction { Instructions::structured_end });
|
|
||||||
++ip;
|
|
||||||
end_ip = ip.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
instructions.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, end_ip, else_ip } });
|
|
||||||
return instructions;
|
|
||||||
}
|
}
|
||||||
case Instructions::br.value():
|
case Instructions::br.value():
|
||||||
case Instructions::br_if.value(): {
|
case Instructions::br_if.value(): {
|
||||||
|
@ -338,7 +345,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::br_table.value(): {
|
case Instructions::br_table.value(): {
|
||||||
// br_table label* label
|
// br_table label* label
|
||||||
|
@ -350,7 +358,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (default_label.is_error())
|
if (default_label.is_error())
|
||||||
return default_label.error();
|
return default_label.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, TableBranchArgs { labels.release_value(), default_label.release_value() } } };
|
resulting_instructions.append(Instruction { opcode, TableBranchArgs { labels.release_value(), default_label.release_value() } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::call.value(): {
|
case Instructions::call.value(): {
|
||||||
// call function
|
// call function
|
||||||
|
@ -358,7 +367,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (function_index.is_error())
|
if (function_index.is_error())
|
||||||
return function_index.error();
|
return function_index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, function_index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, function_index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::call_indirect.value(): {
|
case Instructions::call_indirect.value(): {
|
||||||
// call_indirect type table
|
// call_indirect type table
|
||||||
|
@ -370,7 +380,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (table_index.is_error())
|
if (table_index.is_error())
|
||||||
return table_index.error();
|
return table_index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, IndirectCallArgs { type_index.release_value(), table_index.release_value() } } };
|
resulting_instructions.append(Instruction { opcode, IndirectCallArgs { type_index.release_value(), table_index.release_value() } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::i32_load.value():
|
case Instructions::i32_load.value():
|
||||||
case Instructions::i64_load.value():
|
case Instructions::i64_load.value():
|
||||||
|
@ -396,13 +407,16 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
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 offset)
|
||||||
size_t align, offset;
|
size_t align;
|
||||||
if (!LEB128::read_unsigned(stream, align))
|
if (!LEB128::read_unsigned(stream, align))
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
|
||||||
|
size_t offset;
|
||||||
if (!LEB128::read_unsigned(stream, offset))
|
if (!LEB128::read_unsigned(stream, offset))
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
|
|
||||||
return Vector { 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) } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::local_get.value():
|
case Instructions::local_get.value():
|
||||||
case Instructions::local_set.value():
|
case Instructions::local_set.value():
|
||||||
|
@ -411,7 +425,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::global_get.value():
|
case Instructions::global_get.value():
|
||||||
case Instructions::global_set.value(): {
|
case Instructions::global_set.value(): {
|
||||||
|
@ -419,7 +434,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::memory_size.value():
|
case Instructions::memory_size.value():
|
||||||
case Instructions::memory_grow.value(): {
|
case Instructions::memory_grow.value(): {
|
||||||
|
@ -434,14 +450,16 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
return with_eof_check(stream, ParseError::InvalidTag);
|
return with_eof_check(stream, ParseError::InvalidTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Vector { Instruction { opcode } };
|
resulting_instructions.append(Instruction { opcode });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::i32_const.value(): {
|
case Instructions::i32_const.value(): {
|
||||||
i32 value;
|
i32 value;
|
||||||
if (!LEB128::read_signed(stream, value))
|
if (!LEB128::read_signed(stream, value))
|
||||||
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
||||||
|
|
||||||
return Vector { Instruction { opcode, value } };
|
resulting_instructions.append(Instruction { opcode, value });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::i64_const.value(): {
|
case Instructions::i64_const.value(): {
|
||||||
// op literal
|
// op literal
|
||||||
|
@ -449,7 +467,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (!LEB128::read_signed(stream, value))
|
if (!LEB128::read_signed(stream, value))
|
||||||
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
||||||
|
|
||||||
return Vector { Instruction { opcode, value } };
|
resulting_instructions.append(Instruction { opcode, value });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::f32_const.value(): {
|
case Instructions::f32_const.value(): {
|
||||||
// op literal
|
// op literal
|
||||||
|
@ -459,7 +478,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
||||||
|
|
||||||
auto floating = bit_cast<float>(static_cast<u32>(value));
|
auto floating = bit_cast<float>(static_cast<u32>(value));
|
||||||
return Vector { Instruction { opcode, floating } };
|
resulting_instructions.append(Instruction { opcode, floating });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::f64_const.value(): {
|
case Instructions::f64_const.value(): {
|
||||||
// op literal
|
// op literal
|
||||||
|
@ -469,7 +489,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
||||||
|
|
||||||
auto floating = bit_cast<double>(static_cast<u64>(value));
|
auto floating = bit_cast<double>(static_cast<u64>(value));
|
||||||
return Vector { Instruction { opcode, floating } };
|
resulting_instructions.append(Instruction { opcode, floating });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::table_get.value():
|
case Instructions::table_get.value():
|
||||||
case Instructions::table_set.value(): {
|
case Instructions::table_set.value(): {
|
||||||
|
@ -477,14 +498,16 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::select_typed.value(): {
|
case Instructions::select_typed.value(): {
|
||||||
auto types = parse_vector<ValueType>(stream);
|
auto types = parse_vector<ValueType>(stream);
|
||||||
if (types.is_error())
|
if (types.is_error())
|
||||||
return types.error();
|
return types.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, types.release_value() } };
|
resulting_instructions.append(Instruction { opcode, types.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::ref_null.value(): {
|
case Instructions::ref_null.value(): {
|
||||||
auto type = ValueType::parse(stream);
|
auto type = ValueType::parse(stream);
|
||||||
|
@ -493,14 +516,16 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (!type.value().is_reference())
|
if (!type.value().is_reference())
|
||||||
return ParseError::InvalidType;
|
return ParseError::InvalidType;
|
||||||
|
|
||||||
return Vector { Instruction { opcode, type.release_value() } };
|
resulting_instructions.append(Instruction { opcode, type.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::ref_func.value(): {
|
case Instructions::ref_func.value(): {
|
||||||
auto index = GenericIndexParser<FunctionIndex>::parse(stream);
|
auto index = GenericIndexParser<FunctionIndex>::parse(stream);
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
|
|
||||||
return Vector { Instruction { opcode, index.release_value() } };
|
resulting_instructions.append(Instruction { opcode, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::ref_is_null.value():
|
case Instructions::ref_is_null.value():
|
||||||
case Instructions::unreachable.value():
|
case Instructions::unreachable.value():
|
||||||
|
@ -636,7 +661,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
case Instructions::i64_extend8_s.value():
|
case Instructions::i64_extend8_s.value():
|
||||||
case Instructions::i64_extend16_s.value():
|
case Instructions::i64_extend16_s.value():
|
||||||
case Instructions::i64_extend32_s.value():
|
case Instructions::i64_extend32_s.value():
|
||||||
return Vector { Instruction { opcode } };
|
resulting_instructions.append(Instruction { opcode });
|
||||||
|
break;
|
||||||
case 0xfc: {
|
case 0xfc: {
|
||||||
// These are multibyte instructions.
|
// These are multibyte instructions.
|
||||||
u32 selector;
|
u32 selector;
|
||||||
|
@ -651,7 +677,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
case Instructions::i64_trunc_sat_f32_u_second:
|
case Instructions::i64_trunc_sat_f32_u_second:
|
||||||
case Instructions::i64_trunc_sat_f64_s_second:
|
case Instructions::i64_trunc_sat_f64_s_second:
|
||||||
case Instructions::i64_trunc_sat_f64_u_second:
|
case Instructions::i64_trunc_sat_f64_u_second:
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector } } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
|
||||||
|
break;
|
||||||
case Instructions::memory_init_second: {
|
case Instructions::memory_init_second: {
|
||||||
auto index = GenericIndexParser<DataIndex>::parse(stream);
|
auto index = GenericIndexParser<DataIndex>::parse(stream);
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
|
@ -662,13 +689,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
if (unused != 0x00)
|
if (unused != 0x00)
|
||||||
return ParseError::InvalidImmediate;
|
return ParseError::InvalidImmediate;
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, index.release_value() } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::data_drop_second: {
|
case Instructions::data_drop_second: {
|
||||||
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();
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, index.release_value() } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::memory_copy_second: {
|
case Instructions::memory_copy_second: {
|
||||||
for (size_t i = 0; i < 2; ++i) {
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
|
@ -679,7 +708,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
if (unused != 0x00)
|
if (unused != 0x00)
|
||||||
return ParseError::InvalidImmediate;
|
return ParseError::InvalidImmediate;
|
||||||
}
|
}
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector } } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::memory_fill_second: {
|
case Instructions::memory_fill_second: {
|
||||||
u8 unused;
|
u8 unused;
|
||||||
|
@ -688,7 +718,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
return with_eof_check(stream, ParseError::InvalidInput);
|
return with_eof_check(stream, ParseError::InvalidInput);
|
||||||
if (unused != 0x00)
|
if (unused != 0x00)
|
||||||
return ParseError::InvalidImmediate;
|
return ParseError::InvalidImmediate;
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector } } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::table_init_second: {
|
case Instructions::table_init_second: {
|
||||||
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
|
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
|
||||||
|
@ -697,13 +728,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
auto table_index = GenericIndexParser<TableIndex>::parse(stream);
|
auto table_index = GenericIndexParser<TableIndex>::parse(stream);
|
||||||
if (table_index.is_error())
|
if (table_index.is_error())
|
||||||
return table_index.error();
|
return table_index.error();
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, TableElementArgs { element_index.release_value(), table_index.release_value() } } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableElementArgs { element_index.release_value(), table_index.release_value() } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::elem_drop_second: {
|
case Instructions::elem_drop_second: {
|
||||||
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
|
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
|
||||||
if (element_index.is_error())
|
if (element_index.is_error())
|
||||||
return element_index.error();
|
return element_index.error();
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, element_index.release_value() } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, element_index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::table_copy_second: {
|
case Instructions::table_copy_second: {
|
||||||
auto lhs = GenericIndexParser<TableIndex>::parse(stream);
|
auto lhs = GenericIndexParser<TableIndex>::parse(stream);
|
||||||
|
@ -712,7 +745,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
auto rhs = GenericIndexParser<TableIndex>::parse(stream);
|
auto rhs = GenericIndexParser<TableIndex>::parse(stream);
|
||||||
if (rhs.is_error())
|
if (rhs.is_error())
|
||||||
return rhs.error();
|
return rhs.error();
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, TableTableArgs { lhs.release_value(), rhs.release_value() } } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableTableArgs { lhs.release_value(), rhs.release_value() } });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instructions::table_grow_second:
|
case Instructions::table_grow_second:
|
||||||
case Instructions::table_size_second:
|
case Instructions::table_size_second:
|
||||||
|
@ -720,15 +754,17 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
|
||||||
auto index = GenericIndexParser<TableIndex>::parse(stream);
|
auto index = GenericIndexParser<TableIndex>::parse(stream);
|
||||||
if (index.is_error())
|
if (index.is_error())
|
||||||
return index.error();
|
return index.error();
|
||||||
return Vector { Instruction { OpCode { 0xfc00 | selector }, index.release_value() } };
|
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ParseError::UnknownInstruction;
|
return ParseError::UnknownInstruction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} while (!nested_instructions.is_empty());
|
||||||
|
|
||||||
return ParseError::UnknownInstruction;
|
return resulting_instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseResult<CustomSection> CustomSection::parse(InputStream& stream)
|
ParseResult<CustomSection> CustomSection::parse(InputStream& stream)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue