mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWasm: Introduce TRY_READ
for parser
Convenience macro akin to `TRY` for reading from a stream.
This commit is contained in:
parent
dc52998341
commit
9800ef6047
Notes:
github-actions[bot]
2024-07-28 11:03:38 +00:00
Author: https://github.com/dzfrias Commit: https://github.com/LadybirdBrowser/ladybird/commit/9800ef60473 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/875 Reviewed-by: https://github.com/alimpfard ✅
1 changed files with 71 additions and 191 deletions
|
@ -16,6 +16,18 @@
|
|||
|
||||
namespace Wasm {
|
||||
|
||||
#define TRY_READ(stream, type, error) \
|
||||
({ \
|
||||
/* Ignore -Wshadow to allow nesting the macro. */ \
|
||||
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
|
||||
auto&& _temporary_result = stream.read_value<type>()); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return with_eof_check(stream, error); \
|
||||
_temporary_result.release_value(); \
|
||||
})
|
||||
|
||||
ParseError with_eof_check(Stream const& stream, ParseError error_if_not_eof)
|
||||
{
|
||||
if (stream.is_eof())
|
||||
|
@ -90,11 +102,7 @@ static ParseResult<ByteString> parse_name(Stream& stream)
|
|||
ParseResult<ValueType> ValueType::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("ValueType"sv);
|
||||
auto tag_or_error = stream.read_value<u8>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
auto tag = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
switch (tag) {
|
||||
case Constants::i32_tag:
|
||||
|
@ -112,7 +120,7 @@ ParseResult<ValueType> ValueType::parse(Stream& stream)
|
|||
case Constants::extern_reference_tag:
|
||||
return ValueType(ExternReference);
|
||||
default:
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
return ParseError::InvalidTag;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,11 +134,7 @@ ParseResult<ResultType> ResultType::parse(Stream& stream)
|
|||
ParseResult<FunctionType> FunctionType::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionType"sv);
|
||||
auto tag_or_error = stream.read_value<u8>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
auto tag = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
if (tag != Constants::function_signature_tag) {
|
||||
dbgln("Expected 0x60, but found {:#x}", tag);
|
||||
|
@ -146,11 +150,7 @@ ParseResult<FunctionType> FunctionType::parse(Stream& stream)
|
|||
ParseResult<Limits> Limits::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Limits"sv);
|
||||
auto flag_or_error = stream.read_value<u8>();
|
||||
if (flag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto flag = flag_or_error.release_value();
|
||||
auto flag = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
if (flag > 1)
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
|
@ -183,7 +183,7 @@ ParseResult<TableType> TableType::parse(Stream& stream)
|
|||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableType"sv);
|
||||
auto type_result = TRY(ValueType::parse(stream));
|
||||
if (!type_result.is_reference())
|
||||
return with_eof_check(stream, ParseError::InvalidType);
|
||||
return ParseError::InvalidType;
|
||||
auto limits_result = TRY(Limits::parse(stream));
|
||||
return TableType { type_result, limits_result };
|
||||
}
|
||||
|
@ -192,12 +192,7 @@ ParseResult<GlobalType> GlobalType::parse(Stream& stream)
|
|||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalType"sv);
|
||||
auto type_result = TRY(ValueType::parse(stream));
|
||||
|
||||
auto mutable_or_error = stream.read_value<u8>();
|
||||
if (mutable_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto mutable_ = mutable_or_error.release_value();
|
||||
auto mutable_ = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
if (mutable_ > 1)
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
|
@ -208,11 +203,8 @@ ParseResult<GlobalType> GlobalType::parse(Stream& stream)
|
|||
ParseResult<BlockType> BlockType::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("BlockType"sv);
|
||||
auto kind_or_error = stream.read_value<u8>();
|
||||
if (kind_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
auto kind = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
auto kind = kind_or_error.release_value();
|
||||
if (kind == Constants::empty_block_tag)
|
||||
return BlockType {};
|
||||
|
||||
|
@ -227,10 +219,7 @@ ParseResult<BlockType> BlockType::parse(Stream& stream)
|
|||
|
||||
// FIXME: should be an i33. Right now, we're missing a potential last bit at
|
||||
// the end. See https://webassembly.github.io/spec/core/binary/instructions.html#binary-blocktype
|
||||
auto index_value_or_error = new_stream.read_value<LEB128<i32>>();
|
||||
if (index_value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
i32 index_value = index_value_or_error.release_value();
|
||||
i32 index_value = TRY_READ(new_stream, LEB128<i32>, ParseError::ExpectedIndex);
|
||||
|
||||
if (index_value < 0) {
|
||||
dbgln("Invalid type index {}", index_value);
|
||||
|
@ -243,11 +232,7 @@ ParseResult<BlockType> BlockType::parse(Stream& stream)
|
|||
ParseResult<Instruction> Instruction::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv);
|
||||
auto byte_or_error = stream.read_value<u8>();
|
||||
if (byte_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto byte = byte_or_error.release_value();
|
||||
auto byte = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
OpCode opcode { byte };
|
||||
|
||||
|
@ -307,27 +292,18 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case Instructions::i64_store16.value():
|
||||
case Instructions::i64_store32.value(): {
|
||||
// op (align [multi-memory: memindex] offset)
|
||||
auto align_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
size_t align = align_or_error.release_value();
|
||||
u32 align = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
|
||||
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||
size_t memory_index = 0;
|
||||
auto memory_index = 0;
|
||||
if ((align & 0x40) != 0) {
|
||||
align &= ~0x40;
|
||||
auto memory_index_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
memory_index = memory_index_or_error.release_value();
|
||||
memory_index = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
}
|
||||
|
||||
auto offset_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (offset_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
size_t offset = offset_or_error.release_value();
|
||||
auto offset = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
|
||||
return Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) } };
|
||||
return Instruction { opcode, MemoryArgument { align, offset, MemoryIndex(memory_index) } };
|
||||
}
|
||||
case Instructions::local_get.value():
|
||||
case Instructions::local_set.value():
|
||||
|
@ -343,48 +319,31 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case Instructions::memory_size.value():
|
||||
case Instructions::memory_grow.value(): {
|
||||
// op [multi-memory: memindex]|0x00
|
||||
|
||||
auto memory_index_or_error = stream.read_value<u8>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
auto memory_index = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
return Instruction { opcode, MemoryIndexArgument { MemoryIndex(memory_index) } };
|
||||
}
|
||||
case Instructions::i32_const.value(): {
|
||||
auto value_or_error = stream.read_value<LEB128<i32>>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
||||
i32 value = value_or_error.release_value();
|
||||
auto value = TRY_READ(stream, LEB128<i32>, ParseError::ExpectedSignedImmediate);
|
||||
|
||||
return Instruction { opcode, value };
|
||||
}
|
||||
case Instructions::i64_const.value(): {
|
||||
// op literal
|
||||
auto value_or_error = stream.read_value<LEB128<i64>>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
|
||||
i64 value = value_or_error.release_value();
|
||||
auto value = TRY_READ(stream, LEB128<i64>, ParseError::ExpectedSignedImmediate);
|
||||
|
||||
return Instruction { opcode, value };
|
||||
}
|
||||
case Instructions::f32_const.value(): {
|
||||
// op literal
|
||||
auto value_or_error = stream.read_value<LittleEndian<u32>>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
||||
auto value = value_or_error.release_value();
|
||||
auto value = TRY_READ(stream, LittleEndian<u32>, ParseError::ExpectedFloatingImmediate);
|
||||
|
||||
auto floating = bit_cast<float>(static_cast<u32>(value));
|
||||
return Instruction { opcode, floating };
|
||||
}
|
||||
case Instructions::f64_const.value(): {
|
||||
// op literal
|
||||
auto value_or_error = stream.read_value<LittleEndian<u64>>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
|
||||
auto value = value_or_error.release_value();
|
||||
auto value = TRY_READ(stream, LittleEndian<u64>, ParseError::ExpectedFloatingImmediate);
|
||||
|
||||
auto floating = bit_cast<double>(static_cast<u64>(value));
|
||||
return Instruction { opcode, floating };
|
||||
|
@ -549,10 +508,7 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case 0xfc:
|
||||
case 0xfd: {
|
||||
// These are multibyte instructions.
|
||||
auto selector_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (selector_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
u32 selector = selector_or_error.release_value();
|
||||
auto selector = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
OpCode full_opcode = static_cast<u64>(opcode.value()) << 56 | selector;
|
||||
|
||||
switch (full_opcode.value()) {
|
||||
|
@ -569,11 +525,7 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
auto index = TRY(GenericIndexParser<DataIndex>::parse(stream));
|
||||
|
||||
// Proposal "multi-memory", literal 0x00 is replaced with a memory index.
|
||||
auto memory_index_or_error = stream.read_value<u8>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
auto memory_index = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
|
||||
return Instruction { full_opcode, MemoryInitArgs { index, MemoryIndex(memory_index) } };
|
||||
}
|
||||
|
@ -586,21 +538,14 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
MemoryIndex indices[] = { 0, 0 };
|
||||
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
auto memory_index_or_error = stream.read_value<u8>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
|
||||
indices[i] = memory_index_or_error.release_value();
|
||||
auto memory_index = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
indices[i] = memory_index;
|
||||
}
|
||||
return Instruction { full_opcode, MemoryCopyArgs { indices[1], indices[0] } };
|
||||
}
|
||||
case Instructions::memory_fill.value(): {
|
||||
// Proposal "multi-memory", literal 0x00 is replaced with a memory index.
|
||||
auto memory_index_or_error = stream.read_value<u8>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
|
||||
auto memory_index = memory_index_or_error.release_value();
|
||||
auto memory_index = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
return Instruction { full_opcode, MemoryIndexArgument { MemoryIndex { memory_index } } };
|
||||
}
|
||||
case Instructions::table_init.value(): {
|
||||
|
@ -638,27 +583,18 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case Instructions::v128_load64_zero.value():
|
||||
case Instructions::v128_store.value(): {
|
||||
// op (align [multi-memory memindex] offset)
|
||||
auto align_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
size_t align = align_or_error.release_value();
|
||||
u32 align = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedIndex);
|
||||
|
||||
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||
size_t memory_index = 0;
|
||||
auto memory_index = 0;
|
||||
if ((align & 0x20) != 0) {
|
||||
align &= ~0x20;
|
||||
auto memory_index_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
memory_index = memory_index_or_error.release_value();
|
||||
memory_index = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
}
|
||||
|
||||
auto offset_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (offset_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
size_t offset = offset_or_error.release_value();
|
||||
auto offset = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedIndex);
|
||||
|
||||
return Instruction { full_opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) } };
|
||||
return Instruction { full_opcode, MemoryArgument { align, offset, MemoryIndex(memory_index) } };
|
||||
}
|
||||
case Instructions::v128_load8_lane.value():
|
||||
case Instructions::v128_load16_lane.value():
|
||||
|
@ -669,48 +605,31 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case Instructions::v128_store32_lane.value():
|
||||
case Instructions::v128_store64_lane.value(): {
|
||||
// op (align [multi-memory: memindex] offset) (index)
|
||||
auto align_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (align_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
size_t align = align_or_error.release_value();
|
||||
u32 align = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedIndex);
|
||||
|
||||
// Proposal "multi-memory", if bit 6 of alignment is set, then a memory index follows the alignment.
|
||||
size_t memory_index = 0;
|
||||
auto memory_index = 0;
|
||||
if ((align & 0x20) != 0) {
|
||||
align &= ~0x20;
|
||||
auto memory_index_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (memory_index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
memory_index = memory_index_or_error.release_value();
|
||||
memory_index = TRY_READ(stream, LEB128<u32>, ParseError::InvalidInput);
|
||||
}
|
||||
|
||||
auto offset_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (offset_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
size_t offset = offset_or_error.release_value();
|
||||
auto offset = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedIndex);
|
||||
auto index = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
|
||||
auto index_or_error = stream.read_value<u8>();
|
||||
if (index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
auto index = index_or_error.release_value();
|
||||
|
||||
return Instruction { full_opcode, MemoryAndLaneArgument { { static_cast<u32>(align), static_cast<u32>(offset), MemoryIndex(memory_index) }, index } };
|
||||
return Instruction { full_opcode, MemoryAndLaneArgument { { align, offset, MemoryIndex(memory_index) }, index } };
|
||||
}
|
||||
case Instructions::v128_const.value(): {
|
||||
// op (literal:16)
|
||||
auto value_or_error = stream.read_value<LittleEndian<u128>>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidImmediate);
|
||||
return Instruction { full_opcode, value_or_error.release_value() };
|
||||
auto value = TRY_READ(stream, LittleEndian<u128>, ParseError::InvalidImmediate);
|
||||
return Instruction { full_opcode, value };
|
||||
}
|
||||
case Instructions::i8x16_shuffle.value(): {
|
||||
// op 16x(lane)
|
||||
u8 lanes[16];
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
auto value_or_error = stream.read_value<u8>();
|
||||
if (value_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
lanes[i] = value_or_error.release_value();
|
||||
auto value = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
lanes[i] = value;
|
||||
}
|
||||
return Instruction { full_opcode, ShuffleArgument(lanes) };
|
||||
}
|
||||
|
@ -729,10 +648,7 @@ ParseResult<Instruction> Instruction::parse(Stream& stream)
|
|||
case Instructions::f64x2_extract_lane.value():
|
||||
case Instructions::f64x2_replace_lane.value(): {
|
||||
// op (lane)
|
||||
auto lane_or_error = stream.read_value<u8>();
|
||||
if (lane_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidInput);
|
||||
auto lane = lane_or_error.release_value();
|
||||
auto lane = TRY_READ(stream, u8, ParseError::InvalidInput);
|
||||
return Instruction { full_opcode, LaneIndex { lane } };
|
||||
}
|
||||
case Instructions::i8x16_swizzle.value():
|
||||
|
@ -961,7 +877,7 @@ ParseResult<CustomSection> CustomSection::parse(Stream& stream)
|
|||
if (size == 0)
|
||||
break;
|
||||
if (data_buffer.try_append(buf, size).is_error())
|
||||
return with_eof_check(stream, ParseError::HugeAllocationRequested);
|
||||
return ParseError::HugeAllocationRequested;
|
||||
}
|
||||
|
||||
return CustomSection(name, move(data_buffer));
|
||||
|
@ -979,11 +895,7 @@ ParseResult<ImportSection::Import> ImportSection::Import::parse(Stream& stream)
|
|||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Import"sv);
|
||||
auto module = TRY(parse_name(stream));
|
||||
auto name = TRY(parse_name(stream));
|
||||
auto tag_or_error = stream.read_value<u8>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
auto tag = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
switch (tag) {
|
||||
case Constants::extern_function_tag: {
|
||||
|
@ -997,7 +909,7 @@ ParseResult<ImportSection::Import> ImportSection::Import::parse(Stream& stream)
|
|||
case Constants::extern_global_tag:
|
||||
return parse_with_type<GlobalType>(stream, module, name);
|
||||
default:
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
return ParseError::InvalidTag;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1110,16 +1022,9 @@ ParseResult<ExportSection::Export> ExportSection::Export::parse(Stream& stream)
|
|||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Export"sv);
|
||||
auto name = TRY(parse_name(stream));
|
||||
auto tag_or_error = stream.read_value<u8>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
auto tag = TRY_READ(stream, u8, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
|
||||
auto index_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (index_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
size_t index = index_or_error.release_value();
|
||||
auto index = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedIndex);
|
||||
|
||||
switch (tag) {
|
||||
case Constants::extern_function_tag:
|
||||
|
@ -1131,7 +1036,7 @@ ParseResult<ExportSection::Export> ExportSection::Export::parse(Stream& stream)
|
|||
case Constants::extern_global_tag:
|
||||
return Export { name, ExportDesc { GlobalIndex { index } } };
|
||||
default:
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
return ParseError::InvalidTag;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1159,11 +1064,7 @@ ParseResult<StartSection> StartSection::parse(Stream& stream)
|
|||
ParseResult<ElementSection::Element> ElementSection::Element::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element"sv);
|
||||
auto tag_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
auto tag = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedKindTag);
|
||||
|
||||
if (tag > 0x07)
|
||||
return ParseError::InvalidTag;
|
||||
|
@ -1192,12 +1093,10 @@ ParseResult<ElementSection::Element> ElementSection::Element::parse(Stream& stre
|
|||
if (has_exprs) {
|
||||
type = TRY(ValueType::parse(stream));
|
||||
} else {
|
||||
auto extern_or_error = stream.read_value<u8>();
|
||||
if (extern_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidType);
|
||||
auto extern_ = TRY_READ(stream, u8, ParseError::InvalidType);
|
||||
// Make sure that this is a function, as it's technically only the
|
||||
// allowed one.
|
||||
if (extern_or_error.release_value() != 0x00) {
|
||||
if (extern_ != 0x00) {
|
||||
return ParseError::InvalidType;
|
||||
}
|
||||
type = ValueType(ValueType::FunctionReference);
|
||||
|
@ -1228,17 +1127,14 @@ ParseResult<ElementSection> ElementSection::parse(Stream& stream)
|
|||
ParseResult<Locals> Locals::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Locals"sv);
|
||||
auto count_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (count_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidSize);
|
||||
size_t count = count_or_error.release_value();
|
||||
auto count = TRY_READ(stream, LEB128<u32>, ParseError::InvalidSize);
|
||||
|
||||
if (count > Constants::max_allowed_function_locals_per_type)
|
||||
return with_eof_check(stream, ParseError::HugeAllocationRequested);
|
||||
return ParseError::HugeAllocationRequested;
|
||||
|
||||
auto type = TRY(ValueType::parse(stream));
|
||||
|
||||
return Locals { static_cast<u32>(count), type };
|
||||
return Locals { count, type };
|
||||
}
|
||||
|
||||
ParseResult<CodeSection::Func> CodeSection::Func::parse(Stream& stream, size_t size_hint)
|
||||
|
@ -1252,16 +1148,13 @@ ParseResult<CodeSection::Func> CodeSection::Func::parse(Stream& stream, size_t s
|
|||
ParseResult<CodeSection::Code> CodeSection::Code::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Code"sv);
|
||||
auto size_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (size_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::InvalidSize);
|
||||
size_t size = size_or_error.release_value();
|
||||
auto size = TRY_READ(stream, LEB128<u32>, ParseError::InvalidSize);
|
||||
|
||||
// Emprically, if there are `size` bytes to be read, then there's around
|
||||
// `size / 2` instructions, so we pass that as our size hint.
|
||||
auto func = TRY(Func::parse(stream, size / 2));
|
||||
|
||||
return Code { static_cast<u32>(size), move(func) };
|
||||
return Code { size, move(func) };
|
||||
}
|
||||
|
||||
ParseResult<CodeSection> CodeSection::parse(Stream& stream)
|
||||
|
@ -1274,14 +1167,10 @@ ParseResult<CodeSection> CodeSection::parse(Stream& stream)
|
|||
ParseResult<DataSection::Data> DataSection::Data::parse(Stream& stream)
|
||||
{
|
||||
ScopeLogger<WASM_BINPARSER_DEBUG> logger("Data"sv);
|
||||
auto tag_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (tag_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedKindTag);
|
||||
|
||||
auto tag = tag_or_error.release_value();
|
||||
auto tag = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedKindTag);
|
||||
|
||||
if (tag > 0x02)
|
||||
return with_eof_check(stream, ParseError::InvalidTag);
|
||||
return ParseError::InvalidTag;
|
||||
|
||||
if (tag == 0x00) {
|
||||
auto expr = TRY(Expression::parse(stream));
|
||||
|
@ -1340,17 +1229,8 @@ ParseResult<Module> Module::parse(Stream& stream)
|
|||
|
||||
Vector<AnySection> sections;
|
||||
while (!stream.is_eof()) {
|
||||
auto section_id_or_error = stream.read_value<u8>();
|
||||
if (section_id_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedIndex);
|
||||
|
||||
auto section_id = section_id_or_error.release_value();
|
||||
|
||||
auto section_size_or_error = stream.read_value<LEB128<u32>>();
|
||||
if (section_size_or_error.is_error())
|
||||
return with_eof_check(stream, ParseError::ExpectedSize);
|
||||
size_t section_size = section_size_or_error.release_value();
|
||||
|
||||
auto section_id = TRY_READ(stream, u8, ParseError::ExpectedIndex);
|
||||
size_t section_size = TRY_READ(stream, LEB128<u32>, ParseError::ExpectedSize);
|
||||
auto section_stream = ConstrainedStream { MaybeOwned<Stream>(stream), section_size };
|
||||
|
||||
switch (section_id) {
|
||||
|
@ -1394,7 +1274,7 @@ ParseResult<Module> Module::parse(Stream& stream)
|
|||
sections.append(TRY(DataCountSection::parse(section_stream)));
|
||||
break;
|
||||
default:
|
||||
return with_eof_check(stream, ParseError::InvalidIndex);
|
||||
return ParseError::InvalidIndex;
|
||||
}
|
||||
if (section_stream.remaining() != 0)
|
||||
return ParseError::SectionSizeMismatch;
|
||||
|
|
Loading…
Reference in a new issue