1
Fork 0
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:
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();
});
// 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) {

View file

@ -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() };

View file

@ -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();

View file

@ -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&);

View file

@ -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 {