srctree

Robin Linden parent 201bc74f 890c98e4
wasm: Eagerly parse instructions

inlinesplit
wasm/byte_code_parser.cpp added: 22, removed: 20, total 2
@@ -4,6 +4,7 @@
 
#include "wasm/byte_code_parser.h"
 
#include "wasm/instructions.h"
#include "wasm/leb128.h"
#include "wasm/types.h"
#include "wasm/wasm.h"
@@ -11,7 +12,6 @@
#include <tl/expected.hpp>
 
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <istream>
@@ -204,24 +204,18 @@ std::optional<CodeEntry> parse(std::istream &is) {
return std::nullopt;
}
 
auto cursor_before_locals = is.tellg();
 
auto locals = parse_vector<CodeEntry::Local>(is);
if (!locals) {
return std::nullopt;
}
 
auto bytes_consumed_by_locals = is.tellg() - cursor_before_locals;
assert(bytes_consumed_by_locals >= 0);
 
std::vector<std::uint8_t> code;
code.resize(*size - bytes_consumed_by_locals);
if (!is.read(reinterpret_cast<char *>(code.data()), code.size())) {
auto instructions = instructions::parse(is);
if (!instructions) {
return std::nullopt;
}
 
return CodeEntry{
.code = std::move(code),
.code = *std::move(instructions),
.locals = *std::move(locals),
};
}
 
wasm/byte_code_parser_test.cpp added: 22, removed: 20, total 2
@@ -4,6 +4,7 @@
 
#include "wasm/byte_code_parser.h"
 
#include "wasm/instructions.h"
#include "wasm/types.h"
#include "wasm/wasm.h"
 
@@ -399,12 +400,13 @@ void code_section_tests() {
});
 
etest::test("code section, one entry", [] {
auto module =
ByteCodeParser::parse_module(make_module_bytes(SectionId::Code, {1, 6, 1, 1, 0x7f, 4, 4, 4})).value();
auto module = ByteCodeParser::parse_module(
make_module_bytes(SectionId::Code, {1, 6, 1, 1, 0x7f, 0x41, 0b11, 0x69, 0x0b}))
.value();
 
wasm::CodeSection expected{.entries{
wasm::CodeEntry{
.code{4, 4, 4},
.code{wasm::instructions::I32Const{0b11}, wasm::instructions::I32PopulationCount{}},
.locals{{1, wasm::ValueType{wasm::ValueType::Int32}}},
},
}};
@@ -413,22 +415,27 @@ void code_section_tests() {
 
etest::test("code section, two entries", [] {
auto module = ByteCodeParser::parse_module(
make_module_bytes(SectionId::Code, {2, 6, 1, 1, 0x7f, 4, 4, 4, 9, 2, 5, 0x7e, 6, 0x7d, 7, 8, 9, 10}))
make_module_bytes(SectionId::Code, {2, 6, 1, 1, 0x7f, 0x41, 42, 0x0b, 9, 2, 5, 0x7e, 6, 0x7d, 0x0b}))
.value();
 
wasm::CodeSection expected{.entries{
wasm::CodeEntry{
.code{4, 4, 4},
.code{wasm::instructions::I32Const{42}},
.locals{{1, wasm::ValueType{wasm::ValueType::Int32}}},
},
wasm::CodeEntry{
.code{7, 8, 9, 10},
.code{},
.locals{{5, wasm::ValueType{wasm::ValueType::Int64}},
{6, wasm::ValueType{wasm::ValueType::Float32}}},
},
}};
expect_eq(module.code_section, expected);
});
 
etest::test("code section, unhandled opcode", [] {
auto module = ByteCodeParser::parse_module(make_module_bytes(SectionId::Code, {1, 6, 1, 1, 0x7f, 0xff, 0x0b}));
expect_eq(module, tl::unexpected{wasm::ModuleParseError::InvalidCodeSection});
});
}
 
} // namespace
 
wasm/wasm.h added: 22, removed: 20, total 2
@@ -5,6 +5,7 @@
#ifndef WASM_WASM_H_
#define WASM_WASM_H_
 
#include "wasm/instructions.h"
#include "wasm/types.h"
 
#include <cstdint>
@@ -75,7 +76,7 @@ struct CodeEntry {
[[nodiscard]] bool operator==(Local const &) const = default;
};
 
std::vector<std::uint8_t> code{};
std::vector<instructions::Instruction> code{};
std::vector<Local> locals{};
 
[[nodiscard]] bool operator==(CodeEntry const &) const = default;