1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 23:27:35 +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:
Ali Mohammad Pur 2021-05-01 22:49:17 +04:30 committed by Linus Groh
parent 4d9246ac9d
commit a5194274af
5 changed files with 235 additions and 81 deletions

View file

@ -91,7 +91,7 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
m_module_instance.types() = section.types(); m_module_instance.types() = section.types();
}); });
// TODO: Validate stuff // FIXME: Validate stuff
Vector<Value> global_values; Vector<Value> global_values;
ModuleInstance auxiliary_instance; ModuleInstance auxiliary_instance;
@ -125,29 +125,10 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
return result.error(); return result.error();
} }
module.for_each_section_of_type<ElementSection>([&](const ElementSection& element_section) { module.for_each_section_of_type<ElementSection>([&](const ElementSection&) {
auto frame = make<Frame>( // FIXME: Implement me
m_module_instance, // https://webassembly.github.io/spec/core/bikeshed/#element-segments%E2%91%A0
Vector<Value> {}, // https://webassembly.github.io/spec/core/bikeshed/#instantiation%E2%91%A1 step 9
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<DataSection>([&](const DataSection& data_section) { module.for_each_section_of_type<DataSection>([&](const DataSection& data_section) {

View file

@ -931,26 +931,141 @@ ParseResult<StartSection> StartSection::parse(InputStream& stream)
return StartSection { result.release_value() }; 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"); ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element");
auto table_index = GenericIndexParser<TableIndex>::parse(stream); u8 tag;
if (table_index.is_error()) stream >> tag;
return table_index.error(); if (stream.has_any_error())
auto offset = Expression::parse(stream); return with_eof_check(stream, ParseError::ExpectedKindTag);
if (offset.is_error())
return offset.error();
auto init = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
if (init.is_error())
return init.error();
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) ParseResult<ElementSection> ElementSection::parse(InputStream& stream)
{ {
ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection"); ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection");
auto result = Element::parse(stream); auto result = parse_vector<Element>(stream);
if (result.is_error()) if (result.is_error())
return result.error(); return result.error();
return ElementSection { result.release_value() }; return ElementSection { result.release_value() };

View file

@ -169,42 +169,56 @@ void Printer::print(const Wasm::ElementSection& section)
print("(section element\n"); print("(section element\n");
{ {
TemporaryChange change { m_indent, m_indent + 1 }; 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_indent();
print(")\n"); 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_indent();
print("(element\n"); print("(element segment kind 1\n");
{ {
TemporaryChange change { m_indent, m_indent + 1 }; TemporaryChange change { m_indent, m_indent + 1 };
print_indent(); for (auto& index : segment.function_indices) {
print("(table with index {})\n", element.table().value()); print_indent();
print_indent(); print("(function index {})\n", index.value());
print("(offset\n");
{
TemporaryChange change { m_indent, m_indent + 1 };
print(element.offset());
} }
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_indent();
print(")\n"); 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) void Printer::print(const Wasm::ExportSection& section)
{ {
print_indent(); print_indent();

View file

@ -21,13 +21,19 @@ struct Printer {
void print(const Wasm::CodeSection&); void print(const Wasm::CodeSection&);
void print(const Wasm::CodeSection::Code&); void print(const Wasm::CodeSection::Code&);
void print(const Wasm::CodeSection::Func&); void print(const Wasm::CodeSection::Func&);
void print(const Wasm::ConstrainedStream&);
void print(const Wasm::CustomSection&); void print(const Wasm::CustomSection&);
void print(const Wasm::DataCountSection&); void print(const Wasm::DataCountSection&);
void print(const Wasm::DataSection&); void print(const Wasm::DataSection&);
void print(const Wasm::DataSection::Data&); void print(const Wasm::DataSection::Data&);
void print(const Wasm::ElementSection&); 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&);
void print(const Wasm::ExportSection::Export&); void print(const Wasm::ExportSection::Export&);
void print(const Wasm::Expression&); void print(const Wasm::Expression&);
@ -46,8 +52,6 @@ struct Printer {
void print(const Wasm::MemoryType&); void print(const Wasm::MemoryType&);
void print(const Wasm::Module&); void print(const Wasm::Module&);
void print(const Wasm::Module::Function&); 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&);
void print(const Wasm::StartSection::StartFunction&); void print(const Wasm::StartSection::StartFunction&);
void print(const Wasm::TableSection&); void print(const Wasm::TableSection&);

View file

@ -744,40 +744,80 @@ private:
class ElementSection { class ElementSection {
public: public:
class Element { struct Active {
public: TableIndex index;
explicit Element(TableIndex table, Expression expr, Vector<FunctionIndex> init) Expression expression;
: m_table(table) };
, m_offset(move(expr)) struct Declarative {
, m_init(move(init)) };
{ struct Passive {
} };
auto& table() const { return m_table; } struct SegmentType0 {
auto& offset() const { return m_offset; } // FIXME: Implement me!
auto& init() const { return m_init; } 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: using AnyElementType = Variant<
TableIndex m_table; SegmentType0,
Expression m_offset; SegmentType1,
Vector<FunctionIndex> m_init; SegmentType2,
SegmentType3,
SegmentType4,
SegmentType5,
SegmentType6,
SegmentType7>;
struct Element {
static ParseResult<AnyElementType> parse(InputStream&);
}; };
static constexpr u8 section_id = 9; static constexpr u8 section_id = 9;
explicit ElementSection(Element func) explicit ElementSection(Vector<AnyElementType> segs)
: m_function(move(func)) : m_segments(move(segs))
{ {
} }
auto& function() const { return m_function; } auto& segments() const { return m_segments; }
static ParseResult<ElementSection> parse(InputStream& stream); static ParseResult<ElementSection> parse(InputStream& stream);
private: private:
Element m_function; Vector<AnyElementType> m_segments;
}; };
class Locals { class Locals {