srctree

Robin Linden parent b9e49bdb 1a49f248
wasm: Implement parsing the function section

inlinesplit
wasm/wasm.cpp added: 72, removed: 3, total 69
@@ -32,6 +32,11 @@ std::optional<std::vector<T>> parse_vector(std::istream &&);
template<typename T>
std::optional<T> parse(std::istream &) = delete;
 
template<>
std::optional<std::uint32_t> parse(std::istream &is) {
return Leb128<std::uint32_t>::decode_from(is);
}
 
template<>
std::optional<ValueType> parse(std::istream &is) {
std::uint8_t byte{};
@@ -217,6 +222,19 @@ std::optional<TypeSection> Module::type_section() const {
return std::nullopt;
}
 
std::optional<FunctionSection> Module::function_section() const {
auto content = get_section_data(sections, SectionId::Function);
if (!content) {
return std::nullopt;
}
 
if (auto maybe_type_indices = parse_vector<TypeIdx>(std::stringstream{*std::move(content)})) {
return FunctionSection{.type_indices = *std::move(maybe_type_indices)};
}
 
return std::nullopt;
}
 
std::optional<ExportSection> Module::export_section() const {
auto content = get_section_data(sections, SectionId::Export);
if (!content) {
 
wasm/wasm.h added: 72, removed: 3, total 69
@@ -13,6 +13,9 @@
 
namespace wasm {
 
// https://webassembly.github.io/spec/core/binary/modules.html#indices
using TypeIdx = std::uint32_t;
 
// https://webassembly.github.io/spec/core/bikeshed/#sections
enum class SectionId {
Custom = 0,
@@ -71,6 +74,13 @@ struct TypeSection {
[[nodiscard]] bool operator==(TypeSection const &) const = default;
};
 
// https://webassembly.github.io/spec/core/binary/modules.html#function-section
struct FunctionSection {
std::vector<TypeIdx> type_indices;
 
[[nodiscard]] bool operator==(FunctionSection const &) const = default;
};
 
// https://webassembly.github.io/spec/core/bikeshed/#binary-export
struct Export {
enum class Type { Function = 0, Table = 1, Memory = 2, Global = 3 };
@@ -97,6 +107,7 @@ struct Module {
std::vector<Section> sections{};
 
std::optional<TypeSection> type_section() const;
std::optional<FunctionSection> function_section() const;
std::optional<ExportSection> export_section() const;
 
[[nodiscard]] bool operator==(Module const &) const = default;
 
wasm/wasm_test.cpp added: 72, removed: 3, total 69
@@ -102,6 +102,45 @@ void export_section_tests() {
});
}
 
void function_section_tests() {
etest::test("function section, non-existent", [] {
auto module = wasm::Module{};
expect_eq(module.function_section(), std::nullopt);
});
 
etest::test("function section, missing data", [] {
auto module = wasm::Module{.sections{wasm::Section{
.id = wasm::SectionId::Function,
.content{},
}}};
expect_eq(module.function_section(), std::nullopt);
});
 
etest::test("function section, empty", [] {
auto module = wasm::Module{.sections{wasm::Section{
.id = wasm::SectionId::Function,
.content{0},
}}};
expect_eq(module.function_section(), wasm::FunctionSection{});
});
 
etest::test("function section, missing type indices after count", [] {
auto module = wasm::Module{.sections{wasm::Section{
.id = wasm::SectionId::Function,
.content{1},
}}};
expect_eq(module.function_section(), std::nullopt);
});
 
etest::test("function section, good one", [] {
auto module = wasm::Module{.sections{wasm::Section{
.id = wasm::SectionId::Function,
.content{2, 9, 13},
}}};
expect_eq(module.function_section(), wasm::FunctionSection{.type_indices{9, 13}});
});
}
 
void type_section_tests() {
etest::test("type section, non-existent", [] {
auto module = wasm::Module{};
@@ -275,6 +314,7 @@ int main() {
});
 
type_section_tests();
function_section_tests();
export_section_tests();
 
return etest::run_all_tests();