mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:57:44 +00:00
LibWasm: Stub out/implement parsing of all ElementSection segments
Previously, this was parsing only one kind because I mistakenly assumed that they all had the same shape, now it can parse two kinds, and will return NotImplemented for the rest.
This commit is contained in:
parent
4d9246ac9d
commit
a5194274af
5 changed files with 235 additions and 81 deletions
|
@ -91,7 +91,7 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
|
|||
m_module_instance.types() = section.types();
|
||||
});
|
||||
|
||||
// TODO: Validate stuff
|
||||
// FIXME: Validate stuff
|
||||
|
||||
Vector<Value> global_values;
|
||||
ModuleInstance auxiliary_instance;
|
||||
|
@ -125,29 +125,10 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
|
|||
return result.error();
|
||||
}
|
||||
|
||||
module.for_each_section_of_type<ElementSection>([&](const ElementSection& element_section) {
|
||||
auto frame = make<Frame>(
|
||||
m_module_instance,
|
||||
Vector<Value> {},
|
||||
element_section.function().offset(),
|
||||
1);
|
||||
Configuration config { m_store };
|
||||
config.set_frame(move(frame));
|
||||
auto result = config.execute();
|
||||
// What if this traps?
|
||||
VERIFY(!result.is_trap());
|
||||
size_t offset = 0;
|
||||
result.values().first().value().visit(
|
||||
[&](const auto& value) { offset = value; },
|
||||
[&](const FunctionAddress&) { VERIFY_NOT_REACHED(); },
|
||||
[&](const ExternAddress&) { VERIFY_NOT_REACHED(); });
|
||||
// FIXME: Module::get(*Index)
|
||||
auto table_address = m_module_instance.tables().at(element_section.function().table().value());
|
||||
if (auto table_instance = m_store.get(table_address)) {
|
||||
auto& init = element_section.function().init();
|
||||
for (size_t i = 0; i < init.size(); ++i)
|
||||
table_instance->elements()[offset + i] = Reference { Reference::Func { init[i].value() } }; // HACK!
|
||||
}
|
||||
module.for_each_section_of_type<ElementSection>([&](const ElementSection&) {
|
||||
// FIXME: Implement me
|
||||
// https://webassembly.github.io/spec/core/bikeshed/#element-segments%E2%91%A0
|
||||
// https://webassembly.github.io/spec/core/bikeshed/#instantiation%E2%91%A1 step 9
|
||||
});
|
||||
|
||||
module.for_each_section_of_type<DataSection>([&](const DataSection& data_section) {
|
||||
|
|
|
@ -931,26 +931,141 @@ ParseResult<StartSection> StartSection::parse(InputStream& stream)
|
|||
return StartSection { result.release_value() };
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::Element> ElementSection::Element::parse(InputStream& stream)
|
||||
ParseResult<ElementSection::SegmentType0> ElementSection::SegmentType0::parse(InputStream& stream)
|
||||
{
|
||||
auto expression = Expression::parse(stream);
|
||||
if (expression.is_error())
|
||||
return expression.error();
|
||||
auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
|
||||
if (indices.is_error())
|
||||
return indices.error();
|
||||
|
||||
return SegmentType0 { ValueType(ValueType::FunctionReference), indices.release_value(), Active { 0, expression.release_value() } };
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType1> ElementSection::SegmentType1::parse(InputStream& stream)
|
||||
{
|
||||
u8 kind;
|
||||
stream >> kind;
|
||||
if (stream.has_any_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
if (kind != 0)
|
||||
return ParseError::InvalidTag;
|
||||
auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
|
||||
if (indices.is_error())
|
||||
return indices.error();
|
||||
|
||||
return SegmentType1 { ValueType(ValueType::FunctionReference), indices.release_value() };
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType2> ElementSection::SegmentType2::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 2");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType3> ElementSection::SegmentType3::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 3");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType4> ElementSection::SegmentType4::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 4");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType5> ElementSection::SegmentType5::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 5");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType6> ElementSection::SegmentType6::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 6");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::SegmentType7> ElementSection::SegmentType7::parse(InputStream& stream)
|
||||
{
|
||||
dbgln("Type 7");
|
||||
(void)stream;
|
||||
return ParseError::NotImplemented;
|
||||
}
|
||||
|
||||
ParseResult<ElementSection::AnyElementType> ElementSection::Element::parse(InputStream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element");
|
||||
auto table_index = GenericIndexParser<TableIndex>::parse(stream);
|
||||
if (table_index.is_error())
|
||||
return table_index.error();
|
||||
auto offset = Expression::parse(stream);
|
||||
if (offset.is_error())
|
||||
return offset.error();
|
||||
auto init = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
|
||||
if (init.is_error())
|
||||
return init.error();
|
||||
u8 tag;
|
||||
stream >> tag;
|
||||
if (stream.has_any_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
return Element { table_index.release_value(), offset.release_value(), init.release_value() };
|
||||
switch (tag) {
|
||||
case 0x00:
|
||||
if (auto result = SegmentType0::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x01:
|
||||
if (auto result = SegmentType1::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x02:
|
||||
if (auto result = SegmentType2::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x03:
|
||||
if (auto result = SegmentType3::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x04:
|
||||
if (auto result = SegmentType4::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x05:
|
||||
if (auto result = SegmentType5::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x06:
|
||||
if (auto result = SegmentType6::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
case 0x07:
|
||||
if (auto result = SegmentType7::parse(stream); result.is_error()) {
|
||||
return result.error();
|
||||
} else {
|
||||
return AnyElementType { result.release_value() };
|
||||
}
|
||||
default:
|
||||
return ParseError::InvalidTag;
|
||||
}
|
||||
}
|
||||
|
||||
ParseResult<ElementSection> ElementSection::parse(InputStream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection");
|
||||
auto result = Element::parse(stream);
|
||||
auto result = parse_vector<Element>(stream);
|
||||
if (result.is_error())
|
||||
return result.error();
|
||||
return ElementSection { result.release_value() };
|
||||
|
|
|
@ -169,42 +169,56 @@ void Printer::print(const Wasm::ElementSection& section)
|
|||
print("(section element\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
print(section.function());
|
||||
for (auto& entry : section.segments())
|
||||
entry.visit([this](auto& segment) { print(segment); });
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::Element& element)
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType0&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType1& segment)
|
||||
{
|
||||
print_indent();
|
||||
print("(element\n");
|
||||
print("(element segment kind 1\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
print_indent();
|
||||
print("(table with index {})\n", element.table().value());
|
||||
print_indent();
|
||||
print("(offset\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
print(element.offset());
|
||||
for (auto& index : segment.function_indices) {
|
||||
print_indent();
|
||||
print("(function index {})\n", index.value());
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
print_indent();
|
||||
print("(initializers\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
for (auto& index : element.init())
|
||||
print("(init function {})\n", index.value());
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType2&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType3&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType4&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType5&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType6&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ElementSection::SegmentType7&)
|
||||
{
|
||||
}
|
||||
|
||||
void Printer::print(const Wasm::ExportSection& section)
|
||||
{
|
||||
print_indent();
|
||||
|
|
|
@ -21,13 +21,19 @@ struct Printer {
|
|||
void print(const Wasm::CodeSection&);
|
||||
void print(const Wasm::CodeSection::Code&);
|
||||
void print(const Wasm::CodeSection::Func&);
|
||||
void print(const Wasm::ConstrainedStream&);
|
||||
void print(const Wasm::CustomSection&);
|
||||
void print(const Wasm::DataCountSection&);
|
||||
void print(const Wasm::DataSection&);
|
||||
void print(const Wasm::DataSection::Data&);
|
||||
void print(const Wasm::ElementSection&);
|
||||
void print(const Wasm::ElementSection::Element&);
|
||||
void print(const Wasm::ElementSection::SegmentType0&);
|
||||
void print(const Wasm::ElementSection::SegmentType1&);
|
||||
void print(const Wasm::ElementSection::SegmentType2&);
|
||||
void print(const Wasm::ElementSection::SegmentType3&);
|
||||
void print(const Wasm::ElementSection::SegmentType4&);
|
||||
void print(const Wasm::ElementSection::SegmentType5&);
|
||||
void print(const Wasm::ElementSection::SegmentType6&);
|
||||
void print(const Wasm::ElementSection::SegmentType7&);
|
||||
void print(const Wasm::ExportSection&);
|
||||
void print(const Wasm::ExportSection::Export&);
|
||||
void print(const Wasm::Expression&);
|
||||
|
@ -46,8 +52,6 @@ struct Printer {
|
|||
void print(const Wasm::MemoryType&);
|
||||
void print(const Wasm::Module&);
|
||||
void print(const Wasm::Module::Function&);
|
||||
void print(const Wasm::ReconsumableStream&);
|
||||
void print(const Wasm::ResultType&);
|
||||
void print(const Wasm::StartSection&);
|
||||
void print(const Wasm::StartSection::StartFunction&);
|
||||
void print(const Wasm::TableSection&);
|
||||
|
|
|
@ -744,40 +744,80 @@ private:
|
|||
|
||||
class ElementSection {
|
||||
public:
|
||||
class Element {
|
||||
public:
|
||||
explicit Element(TableIndex table, Expression expr, Vector<FunctionIndex> init)
|
||||
: m_table(table)
|
||||
, m_offset(move(expr))
|
||||
, m_init(move(init))
|
||||
{
|
||||
}
|
||||
struct Active {
|
||||
TableIndex index;
|
||||
Expression expression;
|
||||
};
|
||||
struct Declarative {
|
||||
};
|
||||
struct Passive {
|
||||
};
|
||||
|
||||
auto& table() const { return m_table; }
|
||||
auto& offset() const { return m_offset; }
|
||||
auto& init() const { return m_init; }
|
||||
struct SegmentType0 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType0> parse(InputStream& stream);
|
||||
|
||||
static ParseResult<Element> parse(InputStream& stream);
|
||||
ValueType type;
|
||||
Vector<FunctionIndex> function_indices;
|
||||
Active mode;
|
||||
};
|
||||
struct SegmentType1 {
|
||||
static ParseResult<SegmentType1> parse(InputStream& stream);
|
||||
ValueType type;
|
||||
Vector<FunctionIndex> function_indices;
|
||||
};
|
||||
struct SegmentType2 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType2> parse(InputStream& stream);
|
||||
};
|
||||
struct SegmentType3 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType3> parse(InputStream& stream);
|
||||
};
|
||||
struct SegmentType4 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType4> parse(InputStream& stream);
|
||||
};
|
||||
struct SegmentType5 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType5> parse(InputStream& stream);
|
||||
};
|
||||
struct SegmentType6 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType6> parse(InputStream& stream);
|
||||
};
|
||||
struct SegmentType7 {
|
||||
// FIXME: Implement me!
|
||||
static ParseResult<SegmentType7> parse(InputStream& stream);
|
||||
};
|
||||
|
||||
private:
|
||||
TableIndex m_table;
|
||||
Expression m_offset;
|
||||
Vector<FunctionIndex> m_init;
|
||||
using AnyElementType = Variant<
|
||||
SegmentType0,
|
||||
SegmentType1,
|
||||
SegmentType2,
|
||||
SegmentType3,
|
||||
SegmentType4,
|
||||
SegmentType5,
|
||||
SegmentType6,
|
||||
SegmentType7>;
|
||||
|
||||
struct Element {
|
||||
static ParseResult<AnyElementType> parse(InputStream&);
|
||||
};
|
||||
|
||||
static constexpr u8 section_id = 9;
|
||||
|
||||
explicit ElementSection(Element func)
|
||||
: m_function(move(func))
|
||||
explicit ElementSection(Vector<AnyElementType> segs)
|
||||
: m_segments(move(segs))
|
||||
{
|
||||
}
|
||||
|
||||
auto& function() const { return m_function; }
|
||||
auto& segments() const { return m_segments; }
|
||||
|
||||
static ParseResult<ElementSection> parse(InputStream& stream);
|
||||
|
||||
private:
|
||||
Element m_function;
|
||||
Vector<AnyElementType> m_segments;
|
||||
};
|
||||
|
||||
class Locals {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue