Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::vm::binary_parser< Writer, Options, DebugInfo > Class Template Reference

#include <parser.hpp>

Classes

struct  local_types_t
 
struct  operand_stack_type_tracker
 
struct  pc_element_t
 

Public Types

template<typename T >
using vec = guarded_vector<T>
 
using label_t = decltype(std::declval<Writer>().emit_end())
 
using branch_t = decltype(std::declval<Writer>().emit_if())
 

Public Member Functions

 binary_parser (growable_allocator &alloc, const Options &options=Options{})
 
int validate_utf8_code_point (wasm_code_ptr &code)
 
void validate_utf8_string (wasm_code_ptr &code, uint32_t bytes)
 
guarded_vector< uint8_tparse_utf8_string (wasm_code_ptr &code, std::uint32_t max_size)
 
template<typename T >
T parse_raw (wasm_code_ptr &code)
 
moduleparse_module (wasm_code &code, module &mod, DebugInfo &debug)
 
moduleparse_module2 (wasm_code_ptr &code_ptr, size_t sz, module &mod, DebugInfo &debug)
 
void parse_module (wasm_code_ptr &code_ptr, size_t sz, module &mod, DebugInfo &debug)
 
uint32_t parse_magic (wasm_code_ptr &code)
 
uint32_t parse_version (wasm_code_ptr &code)
 
uint8_t parse_section_id (wasm_code_ptr &code)
 
uint32_t parse_section_payload_len (wasm_code_ptr &code)
 
void parse_custom (wasm_code_ptr &code)
 
void parse_name_map (wasm_code_ptr &code, guarded_vector< name_assoc > &map)
 
void parse_name_section (wasm_code_ptr &code)
 
void parse_import_entry (wasm_code_ptr &code, import_entry &entry)
 
uint8_t parse_flags (wasm_code_ptr &code)
 
void parse_table_type (wasm_code_ptr &code, table_type &tt)
 
void parse_global_variable (wasm_code_ptr &code, global_variable &gv)
 
void parse_memory_type (wasm_code_ptr &code, memory_type &mt)
 
void parse_export_entry (wasm_code_ptr &code, export_entry &entry)
 
void parse_func_type (wasm_code_ptr &code, func_type &ft)
 
void parse_elem_segment (wasm_code_ptr &code, elem_segment &es)
 
void parse_init_expr (wasm_code_ptr &code, init_expr &ie, uint8_t type)
 
void parse_function_body (wasm_code_ptr &code, function_body &fb, std::size_t idx)
 
void parse_function_body_code (wasm_code_ptr &code, size_t bounds, const detail::max_func_local_bytes_stack_checker< Options > &local_bytes_checker, Writer &code_writer, const func_type &ft, const local_types_t &local_types)
 
void parse_data_segment (wasm_code_ptr &code, data_segment &ds)
 
template<typename Elem , typename ParseFunc >
void parse_section_impl (wasm_code_ptr &code, vec< Elem > &elems, std::uint32_t max_elements, ParseFunc &&elem_parse)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::type_section, func_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::import_section, import_entry > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::function_section, uint32_t > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::table_section, table_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::memory_section, memory_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::global_section, global_variable > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::export_section, export_entry > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, typename std::enable_if_t< id==section_id::start_section, uint32_t > &start)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::element_section, elem_segment > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::code_section, function_body > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::data_section, data_segment > > &elems)
 
template<size_t N>
varint< Nparse_varint (const wasm_code &code, size_t index)
 
template<size_t N>
varuint< Nparse_varuint (const wasm_code &code, size_t index)
 
void on_mutable_global (uint8_t type)
 
void validate_exports () const
 
 binary_parser (growable_allocator &alloc, const Options &options=Options{})
 
int validate_utf8_code_point (wasm_code_ptr &code)
 
void validate_utf8_string (wasm_code_ptr &code, uint32_t bytes)
 
guarded_vector< uint8_tparse_utf8_string (wasm_code_ptr &code, std::uint32_t max_size)
 
template<typename T >
T parse_raw (wasm_code_ptr &code)
 
moduleparse_module (wasm_code &code, module &mod, DebugInfo &debug)
 
moduleparse_module2 (wasm_code_ptr &code_ptr, size_t sz, module &mod, DebugInfo &debug)
 
void parse_module (wasm_code_ptr &code_ptr, size_t sz, module &mod, DebugInfo &debug)
 
uint32_t parse_magic (wasm_code_ptr &code)
 
uint32_t parse_version (wasm_code_ptr &code)
 
uint8_t parse_section_id (wasm_code_ptr &code)
 
uint32_t parse_section_payload_len (wasm_code_ptr &code)
 
void parse_custom (wasm_code_ptr &code)
 
void parse_name_map (wasm_code_ptr &code, guarded_vector< name_assoc > &map)
 
void parse_name_section (wasm_code_ptr &code)
 
void parse_import_entry (wasm_code_ptr &code, import_entry &entry)
 
uint8_t parse_flags (wasm_code_ptr &code)
 
void parse_table_type (wasm_code_ptr &code, table_type &tt)
 
void parse_global_variable (wasm_code_ptr &code, global_variable &gv)
 
void parse_memory_type (wasm_code_ptr &code, memory_type &mt)
 
void parse_export_entry (wasm_code_ptr &code, export_entry &entry)
 
void parse_func_type (wasm_code_ptr &code, func_type &ft)
 
void parse_elem_segment (wasm_code_ptr &code, elem_segment &es)
 
void parse_init_expr (wasm_code_ptr &code, init_expr &ie, uint8_t type)
 
void parse_function_body (wasm_code_ptr &code, function_body &fb, std::size_t idx)
 
void parse_function_body_code (wasm_code_ptr &code, size_t bounds, const detail::max_func_local_bytes_stack_checker< Options > &local_bytes_checker, Writer &code_writer, const func_type &ft, const local_types_t &local_types)
 
void parse_data_segment (wasm_code_ptr &code, data_segment &ds)
 
template<typename Elem , typename ParseFunc >
void parse_section_impl (wasm_code_ptr &code, vec< Elem > &elems, std::uint32_t max_elements, ParseFunc &&elem_parse)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::type_section, func_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::import_section, import_entry > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::function_section, uint32_t > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::table_section, table_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::memory_section, memory_type > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::global_section, global_variable > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::export_section, export_entry > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, typename std::enable_if_t< id==section_id::start_section, uint32_t > &start)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::element_section, elem_segment > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::code_section, function_body > > &elems)
 
template<uint8_t id>
void parse_section (wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::data_section, data_segment > > &elems)
 
template<size_t N>
varint< Nparse_varint (const wasm_code &code, size_t index)
 
template<size_t N>
varuint< Nparse_varuint (const wasm_code &code, size_t index)
 
void on_mutable_global (uint8_t type)
 
void validate_exports () const
 
template<typename T >
using vec
 

Static Public Member Functions

static uint8_t parse_varuint1 (wasm_code_ptr &code)
 
static uint8_t parse_varuint7 (wasm_code_ptr &code)
 
static uint32_t parse_varuint32 (wasm_code_ptr &code)
 
static int8_t parse_varint7 (wasm_code_ptr &code)
 
static int32_t parse_varint32 (wasm_code_ptr &code)
 
static int64_t parse_varint64 (wasm_code_ptr &code)
 
static uint8_t parse_varuint1 (wasm_code_ptr &code)
 
static uint8_t parse_varuint7 (wasm_code_ptr &code)
 
static uint32_t parse_varuint32 (wasm_code_ptr &code)
 
static int8_t parse_varint7 (wasm_code_ptr &code)
 
static int32_t parse_varint32 (wasm_code_ptr &code)
 
static int64_t parse_varint64 (wasm_code_ptr &code)
 

Static Public Attributes

static constexpr uint8_t any_type = 0x82
 

Detailed Description

template<typename Writer, typename Options = default_options, typename DebugInfo = null_debug_info>
class sysio::vm::binary_parser< Writer, Options, DebugInfo >

Definition at line 202 of file parser.hpp.

Member Typedef Documentation

◆ branch_t

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
decltype(std::declval< Writer >().emit_if()) typedef sysio::vm::binary_parser< Writer, Options, DebugInfo >::branch_t = decltype(std::declval<Writer>().emit_if())

Definition at line 614 of file parser.hpp.

◆ label_t

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
decltype(std::declval< Writer >().emit_end()) typedef sysio::vm::binary_parser< Writer, Options, DebugInfo >::label_t = decltype(std::declval<Writer>().emit_end())

Definition at line 613 of file parser.hpp.

◆ vec

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename T >
using sysio::vm::binary_parser< Writer, Options, DebugInfo >::vec = guarded_vector<T>

Definition at line 207 of file parser.hpp.

Constructor & Destructor Documentation

◆ binary_parser() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
sysio::vm::binary_parser< Writer, Options, DebugInfo >::binary_parser ( growable_allocator & alloc,
const Options & options = Options{} )
inlineexplicit

Definition at line 204 of file parser.hpp.

204{}) : _allocator(alloc), _options(options) {}

◆ binary_parser() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
sysio::vm::binary_parser< Writer, Options, DebugInfo >::binary_parser ( growable_allocator & alloc,
const Options & options = Options{} )
inlineexplicit

Definition at line 204 of file parser.hpp.

204{}) : _allocator(alloc), _options(options) {}

Member Function Documentation

◆ on_mutable_global() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::on_mutable_global ( uint8_t type)
inline

Definition at line 1352 of file parser.hpp.

1352 {
1353 _globals_checker.on_mutable_global(_options, type);
1354 }

◆ on_mutable_global() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::on_mutable_global ( uint8_t type)
inline

Definition at line 1352 of file parser.hpp.

1352 {
1353 _globals_checker.on_mutable_global(_options, type);
1354 }

◆ parse_custom() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_custom ( wasm_code_ptr & code)
inline

Definition at line 363 of file parser.hpp.

363 {
364 auto section_name = parse_utf8_string(code, 0xFFFFFFFFu); // ignored, but needs to be validated
365 if(detail::get_parse_custom_section_name(_options) &&
366 section_name.size() == 4 && std::memcmp(section_name.raw(), "name", 4) == 0) {
367 parse_name_section(code);
368 } else {
369 // skip to the end of the section
370 code += code.bounds() - code.offset();
371 }
372 }
void parse_name_section(wasm_code_ptr &code)
Definition parser.hpp:381
guarded_vector< uint8_t > parse_utf8_string(wasm_code_ptr &code, std::uint32_t max_size)
Definition parser.hpp:272

◆ parse_custom() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_custom ( wasm_code_ptr & code)
inline

Definition at line 363 of file parser.hpp.

363 {
364 auto section_name = parse_utf8_string(code, 0xFFFFFFFFu); // ignored, but needs to be validated
365 if(detail::get_parse_custom_section_name(_options) &&
366 section_name.size() == 4 && std::memcmp(section_name.raw(), "name", 4) == 0) {
367 parse_name_section(code);
368 } else {
369 // skip to the end of the section
370 code += code.bounds() - code.offset();
371 }
372 }

◆ parse_data_segment() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_data_segment ( wasm_code_ptr & code,
data_segment & ds )
inline

Definition at line 1229 of file parser.hpp.

1229 {
1230 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "data requires memory");
1231 ds.index = parse_varuint32(code);
1232 parse_init_expr(code, ds.offset, types::i32);
1233 auto len = parse_varuint32(code);
1234 SYS_VM_ASSERT(len <= detail::get_max_data_segment_bytes(_options), wasm_parse_exception, "data segment too large.");
1235 SYS_VM_ASSERT(static_cast<uint64_t>(static_cast<uint32_t>(ds.offset.value.i32)) + len <= detail::get_max_linear_memory_init(_options),
1236 wasm_parse_exception, "out-of-bounds data section");
1237 auto guard = code.scoped_shrink_bounds(len);
1238 ds.data = decltype(ds.data){ _allocator, len};
1239 ds.data.copy(code.raw(), len);
1240 code += len;
1241 }
static uint32_t parse_varuint32(wasm_code_ptr &code)
Definition parser.hpp:213
void parse_init_expr(wasm_code_ptr &code, init_expr &ie, uint8_t type)
Definition parser.hpp:548
static const Segment ds(Segment::ds)
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
guarded_vector< memory_type > memories
Definition types.hpp:173
#define SYS_VM_ASSERT(expr, exc_type, msg)
Definition exceptions.hpp:8
size_t len

◆ parse_data_segment() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_data_segment ( wasm_code_ptr & code,
data_segment & ds )
inline

Definition at line 1229 of file parser.hpp.

1229 {
1230 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "data requires memory");
1231 ds.index = parse_varuint32(code);
1232 parse_init_expr(code, ds.offset, types::i32);
1233 auto len = parse_varuint32(code);
1234 SYS_VM_ASSERT(len <= detail::get_max_data_segment_bytes(_options), wasm_parse_exception, "data segment too large.");
1235 SYS_VM_ASSERT(static_cast<uint64_t>(static_cast<uint32_t>(ds.offset.value.i32)) + len <= detail::get_max_linear_memory_init(_options),
1236 wasm_parse_exception, "out-of-bounds data section");
1237 auto guard = code.scoped_shrink_bounds(len);
1238 ds.data = decltype(ds.data){ _allocator, len};
1239 ds.data.copy(code.raw(), len);
1240 code += len;
1241 }

◆ parse_elem_segment() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_elem_segment ( wasm_code_ptr & code,
elem_segment & es )
inline

Definition at line 521 of file parser.hpp.

521 {
522 table_type* tt = nullptr;
523 for (std::size_t i = 0; i < _mod->tables.size(); i++) {
524 if (_mod->tables[i].element_type == types::anyfunc)
525 tt = &(_mod->tables[i]);
526 }
527 SYS_VM_ASSERT(tt != nullptr, wasm_parse_exception, "table not declared");
528 es.index = parse_varuint32(code);
529 SYS_VM_ASSERT(es.index == 0, wasm_parse_exception, "only table index of 0 is supported");
530 parse_init_expr(code, es.offset, types::i32);
531 uint32_t size = parse_varuint32(code);
532 SYS_VM_ASSERT(size <= detail::get_max_element_segment_elements(_options), wasm_parse_exception, "elem segment too large");
533 decltype(es.elems) elems = { _allocator, size };
534 for (uint32_t i = 0; i < size; i++) {
535 uint32_t index = parse_varuint32(code);
536 elems.at(i) = index;
537 SYS_VM_ASSERT(index < _mod->get_functions_total(), wasm_parse_exception, "elem for undefined function");
538 }
539 uint32_t offset = static_cast<uint32_t>(es.offset.value.i32);
540 if ( static_cast<uint64_t>(size) + offset <= tt->table.size() ) {
541 std::memcpy(tt->table.raw() + offset, elems.raw(), size * sizeof(uint32_t));
542 } else {
543 _mod->error = "elem out of range";
544 }
545 es.elems = std::move(elems);
546 }
guarded_vector< table_type > tables
Definition types.hpp:172
const char * error
Definition types.hpp:191

◆ parse_elem_segment() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_elem_segment ( wasm_code_ptr & code,
elem_segment & es )
inline

Definition at line 521 of file parser.hpp.

521 {
522 table_type* tt = nullptr;
523 for (std::size_t i = 0; i < _mod->tables.size(); i++) {
524 if (_mod->tables[i].element_type == types::anyfunc)
525 tt = &(_mod->tables[i]);
526 }
527 SYS_VM_ASSERT(tt != nullptr, wasm_parse_exception, "table not declared");
528 es.index = parse_varuint32(code);
529 SYS_VM_ASSERT(es.index == 0, wasm_parse_exception, "only table index of 0 is supported");
530 parse_init_expr(code, es.offset, types::i32);
531 uint32_t size = parse_varuint32(code);
532 SYS_VM_ASSERT(size <= detail::get_max_element_segment_elements(_options), wasm_parse_exception, "elem segment too large");
533 decltype(es.elems) elems = { _allocator, size };
534 for (uint32_t i = 0; i < size; i++) {
535 uint32_t index = parse_varuint32(code);
536 elems.at(i) = index;
537 SYS_VM_ASSERT(index < _mod->get_functions_total(), wasm_parse_exception, "elem for undefined function");
538 }
539 uint32_t offset = static_cast<uint32_t>(es.offset.value.i32);
540 if ( static_cast<uint64_t>(size) + offset <= tt->table.size() ) {
541 std::memcpy(tt->table.raw() + offset, elems.raw(), size * sizeof(uint32_t));
542 } else {
543 _mod->error = "elem out of range";
544 }
545 es.elems = std::move(elems);
546 }

◆ parse_export_entry() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_export_entry ( wasm_code_ptr & code,
export_entry & entry )
inline

Definition at line 483 of file parser.hpp.

483 {
484 entry.field_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
485 entry.kind = (external_kind)(*code++);
486 entry.index = parse_varuint32(code);
487 switch(entry.kind) {
488 case external_kind::Function: SYS_VM_ASSERT(entry.index < _mod->get_functions_total(), wasm_parse_exception, "function export out of range"); break;
489 case external_kind::Table: SYS_VM_ASSERT(entry.index < _mod->tables.size(), wasm_parse_exception, "table export out of range"); break;
490 case external_kind::Memory: SYS_VM_ASSERT(entry.index < _mod->memories.size(), wasm_parse_exception, "memory export out of range"); break;
491 case external_kind::Global:
492 SYS_VM_ASSERT(entry.index < _mod->globals.size(), wasm_parse_exception, "global export out of range");
493 SYS_VM_ASSERT(!detail::get_forbid_export_mutable_globals(_options) || !_mod->globals.at(entry.index).type.mutability,
494 wasm_parse_exception, "cannot export mutable globals");
495 break;
496 default: SYS_VM_ASSERT(false, wasm_parse_exception, "Unknown export kind"); break;
497 }
498 }
external_kind
Definition types.hpp:22
guarded_vector< global_variable > globals
Definition types.hpp:174
uint32_t get_functions_total() const
Definition types.hpp:206

◆ parse_export_entry() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_export_entry ( wasm_code_ptr & code,
export_entry & entry )
inline

Definition at line 483 of file parser.hpp.

483 {
484 entry.field_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
485 entry.kind = (external_kind)(*code++);
486 entry.index = parse_varuint32(code);
487 switch(entry.kind) {
488 case external_kind::Function: SYS_VM_ASSERT(entry.index < _mod->get_functions_total(), wasm_parse_exception, "function export out of range"); break;
489 case external_kind::Table: SYS_VM_ASSERT(entry.index < _mod->tables.size(), wasm_parse_exception, "table export out of range"); break;
490 case external_kind::Memory: SYS_VM_ASSERT(entry.index < _mod->memories.size(), wasm_parse_exception, "memory export out of range"); break;
491 case external_kind::Global:
492 SYS_VM_ASSERT(entry.index < _mod->globals.size(), wasm_parse_exception, "global export out of range");
493 SYS_VM_ASSERT(!detail::get_forbid_export_mutable_globals(_options) || !_mod->globals.at(entry.index).type.mutability,
494 wasm_parse_exception, "cannot export mutable globals");
495 break;
496 default: SYS_VM_ASSERT(false, wasm_parse_exception, "Unknown export kind"); break;
497 }
498 }

◆ parse_flags() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_flags ( wasm_code_ptr & code)
inline

Definition at line 433 of file parser.hpp.

433 {
434 if (detail::get_allow_u32_limits_flags(_options)) {
435 return parse_varuint32(code) & 0x1;
436 } else {
437 SYS_VM_ASSERT(*code == 0x0 || *code == 0x1, wasm_parse_exception, "invalid flags");
438 return *code++;
439 }
440 }

◆ parse_flags() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_flags ( wasm_code_ptr & code)
inline

Definition at line 433 of file parser.hpp.

433 {
434 if (detail::get_allow_u32_limits_flags(_options)) {
435 return parse_varuint32(code) & 0x1;
436 } else {
437 SYS_VM_ASSERT(*code == 0x0 || *code == 0x1, wasm_parse_exception, "invalid flags");
438 return *code++;
439 }
440 }

◆ parse_func_type() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_func_type ( wasm_code_ptr & code,
func_type & ft )
inline

Definition at line 500 of file parser.hpp.

500 {
501 ft.form = *code++;
502 SYS_VM_ASSERT(ft.form == 0x60, wasm_parse_exception, "invalid function type");
503 decltype(ft.param_types) param_types = { _allocator, parse_varuint32(code) };
504 for (size_t i = 0; i < param_types.size(); i++) {
505 uint8_t pt = *code++;
506 param_types.at(i) = pt;
507 SYS_VM_ASSERT(pt == types::i32 || pt == types::i64 || pt == types::f32 || pt == types::f64,
508 wasm_parse_exception, "invalid function param type");
509 }
510 ft.param_types = std::move(param_types);
511 ft.return_count = *code++;
512 SYS_VM_ASSERT(ft.return_count < 2, wasm_parse_exception, "invalid function return count");
513 if (ft.return_count > 0) {
514 uint8_t rt = *code++;
515 ft.return_type = rt;
516 SYS_VM_ASSERT(rt == types::i32 || rt == types::i64 || rt == types::f32 || rt == types::f64,
517 wasm_parse_exception, "invalid function return type");
518 }
519 }
unsigned char uint8_t
Definition stdint.h:124

◆ parse_func_type() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_func_type ( wasm_code_ptr & code,
func_type & ft )
inline

Definition at line 500 of file parser.hpp.

500 {
501 ft.form = *code++;
502 SYS_VM_ASSERT(ft.form == 0x60, wasm_parse_exception, "invalid function type");
503 decltype(ft.param_types) param_types = { _allocator, parse_varuint32(code) };
504 for (size_t i = 0; i < param_types.size(); i++) {
505 uint8_t pt = *code++;
506 param_types.at(i) = pt;
507 SYS_VM_ASSERT(pt == types::i32 || pt == types::i64 || pt == types::f32 || pt == types::f64,
508 wasm_parse_exception, "invalid function param type");
509 }
510 ft.param_types = std::move(param_types);
511 ft.return_count = *code++;
512 SYS_VM_ASSERT(ft.return_count < 2, wasm_parse_exception, "invalid function return count");
513 if (ft.return_count > 0) {
514 uint8_t rt = *code++;
515 ft.return_type = rt;
516 SYS_VM_ASSERT(rt == types::i32 || rt == types::i64 || rt == types::f32 || rt == types::f64,
517 wasm_parse_exception, "invalid function return type");
518 }
519 }

◆ parse_function_body() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_function_body ( wasm_code_ptr & code,
function_body & fb,
std::size_t idx )
inline

Definition at line 574 of file parser.hpp.

574 {
575 fb.size = parse_varuint32(code);
576 SYS_VM_ASSERT(fb.size <= detail::get_max_code_bytes(_options), wasm_parse_exception, "Function body too large");
577 const auto& before = code.offset();
578 const auto& local_cnt = parse_varuint32(code);
579 _current_function_index++;
580 SYS_VM_ASSERT(local_cnt <= detail::get_max_local_sets(_options), wasm_parse_exception, "Number of local sets exceeds limit");
581 decltype(fb.locals) locals = { _allocator, local_cnt };
582 func_type& ft = _mod->types.at(_mod->functions.at(idx));
583 detail::max_func_local_bytes_checker<Options> local_checker(_options, ft);
584 // parse the local entries
585 for (size_t i = 0; i < local_cnt; i++) {
586 auto count = parse_varuint32(code);
587 auto type = *code++;
588 if (detail::get_allow_invalid_empty_local_set(_options) && count == 0) type = types::i32;
589 SYS_VM_ASSERT(type == types::i32 || type == types::i64 || type == types::f32 || type == types::f64,
590 wasm_parse_exception, "invalid local type");
591 local_checker.on_local(_options, type, count);
592 locals.at(i).count = count;
593 locals.at(i).type = type;
594 }
595 fb.locals = std::move(locals);
596
597 fb.size -= code.offset() - before;
598 auto guard = code.scoped_shrink_bounds(fb.size);
599 _function_bodies.emplace_back(wasm_code_ptr{code.raw(), fb.size}, local_checker);
600
601 code += fb.size-1;
602 SYS_VM_ASSERT(detail::get_allow_code_after_function_end(_options) || *code == 0x0B,
603 wasm_parse_exception, "failed parsing function body, expected 'end'");
604 ++code;
605 }
int * count
guarded_ptr< uint8_t > wasm_code_ptr
Definition types.hpp:148
guarded_vector< uint32_t > functions
Definition types.hpp:171
guarded_vector< func_type > types
Definition types.hpp:169
yh_object_type type
Definition yubihsm.h:672
Here is the call graph for this function:

◆ parse_function_body() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_function_body ( wasm_code_ptr & code,
function_body & fb,
std::size_t idx )
inline

Definition at line 574 of file parser.hpp.

574 {
575 fb.size = parse_varuint32(code);
576 SYS_VM_ASSERT(fb.size <= detail::get_max_code_bytes(_options), wasm_parse_exception, "Function body too large");
577 const auto& before = code.offset();
578 const auto& local_cnt = parse_varuint32(code);
579 _current_function_index++;
580 SYS_VM_ASSERT(local_cnt <= detail::get_max_local_sets(_options), wasm_parse_exception, "Number of local sets exceeds limit");
581 decltype(fb.locals) locals = { _allocator, local_cnt };
582 func_type& ft = _mod->types.at(_mod->functions.at(idx));
583 detail::max_func_local_bytes_checker<Options> local_checker(_options, ft);
584 // parse the local entries
585 for (size_t i = 0; i < local_cnt; i++) {
586 auto count = parse_varuint32(code);
587 auto type = *code++;
588 if (detail::get_allow_invalid_empty_local_set(_options) && count == 0) type = types::i32;
589 SYS_VM_ASSERT(type == types::i32 || type == types::i64 || type == types::f32 || type == types::f64,
590 wasm_parse_exception, "invalid local type");
591 local_checker.on_local(_options, type, count);
592 locals.at(i).count = count;
593 locals.at(i).type = type;
594 }
595 fb.locals = std::move(locals);
596
597 fb.size -= code.offset() - before;
598 auto guard = code.scoped_shrink_bounds(fb.size);
599 _function_bodies.emplace_back(wasm_code_ptr{code.raw(), fb.size}, local_checker);
600
601 code += fb.size-1;
602 SYS_VM_ASSERT(detail::get_allow_code_after_function_end(_options) || *code == 0x0B,
603 wasm_parse_exception, "failed parsing function body, expected 'end'");
604 ++code;
605 }
Here is the call graph for this function:

◆ parse_function_body_code() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_function_body_code ( wasm_code_ptr & code,
size_t bounds,
const detail::max_func_local_bytes_stack_checker< Options > & local_bytes_checker,
Writer & code_writer,
const func_type & ft,
const local_types_t & local_types )
inline

Definition at line 734 of file parser.hpp.

735 {
736
737 // Initialize the control stack with the current function as the sole element
738 operand_stack_type_tracker op_stack{local_bytes_checker, _options};
739 std::vector<pc_element_t> pc_stack{{
740 op_stack.depth(),
741 ft.return_count ? ft.return_type : static_cast<uint32_t>(types::pseudo),
742 ft.return_count ? ft.return_type : static_cast<uint32_t>(types::pseudo),
743 false,
744 std::vector<branch_t>{}}};
745
746 // writes the continuation of a label to address. If the continuation
747 // is not yet available, address will be recorded in the relocations
748 // list for label.
749 auto handle_branch_target = [&](uint32_t label, branch_t address) {
750 SYS_VM_ASSERT(label < pc_stack.size(), wasm_parse_exception, "invalid label");
751 pc_element_t& branch_target = pc_stack[pc_stack.size() - label - 1];
752 std::visit(overloaded{ [&](label_t target) { code_writer.fix_branch(address, target); },
753 [&](std::vector<branch_t>& relocations) { relocations.push_back(address); } },
754 branch_target.relocations);
755 };
756
757 // Returns the number of operands that need to be popped when
758 // branching to label. If the label has a return value it will
759 // be counted in this, and the high bit will be set to signal
760 // its presence.
761 auto compute_depth_change = [&](uint32_t label) -> uint32_t {
762 SYS_VM_ASSERT(label < pc_stack.size(), wasm_parse_exception, "invalid label");
763 pc_element_t& branch_target = pc_stack[pc_stack.size() - label - 1];
764 uint32_t result = op_stack.depth() - branch_target.operand_depth;
765 if(branch_target.label_result != types::pseudo) {
766 // FIXME: Reusing the high bit imposes an additional constraint
767 // on the maximum depth of the operand stack. This isn't an
768 // actual problem right now, because the stack is hard-coded
769 // to 8192 elements, but it would be better to avoid spreading
770 // this assumption around the code.
771 result |= 0x80000000;
772 op_stack.top(branch_target.label_result);
773 }
774 return result;
775 };
776
777 // Handles branches to the end of the scope and pops the pc_stack
778 auto exit_scope = [&]() {
779 // There must be at least one element
780 SYS_VM_ASSERT(pc_stack.size(), wasm_parse_exception, "unexpected end instruction");
781 // an if with an empty else cannot have a return value
782 SYS_VM_ASSERT(!pc_stack.back().is_if || pc_stack.back().expected_result == types::pseudo, wasm_parse_exception, "wrong type");
783 auto end_pos = code_writer.emit_end();
784 if(auto* relocations = std::get_if<std::vector<branch_t>>(&pc_stack.back().relocations)) {
785 for(auto branch_op : *relocations) {
786 code_writer.fix_branch(branch_op, end_pos);
787 }
788 }
789 op_stack.pop_scope(pc_stack.back().expected_result);
790 pc_stack.pop_back();
791 };
792
793 auto check_in_bounds = [&]{
794 SYS_VM_ASSERT(!detail::get_allow_code_after_function_end(_options) || !pc_stack.empty(),
795 wasm_parse_exception, "code after function end");
796 };
797
798 while (code.offset() < bounds) {
799 SYS_VM_ASSERT(pc_stack.size() <= detail::get_max_nested_structures(_options), wasm_parse_exception,
800 "nested structures validation failure");
801
802 imap.on_instr_start(code_writer.get_addr(), code.raw());
803
804 switch (*code++) {
805 case opcodes::unreachable: check_in_bounds(); code_writer.emit_unreachable(); op_stack.start_unreachable(); break;
806 case opcodes::nop: code_writer.emit_nop(); break;
807 case opcodes::end: {
808 check_in_bounds();
809 exit_scope();
810 SYS_VM_ASSERT(detail::get_allow_code_after_function_end(_options) ||
811 !pc_stack.empty() || code.offset() == bounds, wasm_parse_exception, "function too short");
812 _nested_checker.on_end(_options);
813 break;
814 }
815 case opcodes::return_: {
816 check_in_bounds();
817 uint32_t label = pc_stack.size() - 1;
818 auto branch = code_writer.emit_return(compute_depth_change(label));
819 handle_branch_target(label, branch);
820 op_stack.start_unreachable();
821 } break;
822 case opcodes::block: {
823 uint32_t expected_result = *code++;
824 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
825 expected_result = types::pseudo;
826 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
827 expected_result == types::f32 || expected_result == types::f64 ||
828 expected_result == types::pseudo, wasm_parse_exception,
829 "Invalid type code in block");
830 pc_stack.push_back({op_stack.depth(), expected_result, expected_result, false, std::vector<branch_t>{}});
831 code_writer.emit_block();
832 op_stack.push_scope();
833 _nested_checker.on_control(_options);
834 } break;
835 case opcodes::loop: {
836 uint32_t expected_result = *code++;
837 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
838 expected_result = types::pseudo;
839 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
840 expected_result == types::f32 || expected_result == types::f64 ||
841 expected_result == types::pseudo, wasm_parse_exception,
842 "Invalid type code in loop");
843 auto pos = code_writer.emit_loop();
844 pc_stack.push_back({op_stack.depth(), expected_result, types::pseudo, false, pos});
845 op_stack.push_scope();
846 _nested_checker.on_control(_options);
847 } break;
848 case opcodes::if_: {
849 check_in_bounds();
850 uint32_t expected_result = *code++;
851 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
852 expected_result = types::pseudo;
853 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
854 expected_result == types::f32 || expected_result == types::f64 ||
855 expected_result == types::pseudo, wasm_parse_exception,
856 "Invalid type code in if");
857 auto branch = code_writer.emit_if();
858 op_stack.pop(types::i32);
859 pc_stack.push_back({op_stack.depth(), expected_result, expected_result, true, std::vector{branch}});
860 op_stack.push_scope();
861 _nested_checker.on_control(_options);
862 } break;
863 case opcodes::else_: {
864 check_in_bounds();
865 auto& old_index = pc_stack.back();
866 SYS_VM_ASSERT(old_index.is_if, wasm_parse_exception, "else outside if");
867 auto& relocations = std::get<std::vector<branch_t>>(old_index.relocations);
868 // reset the operand stack to the same state as the if
869 op_stack.pop(old_index.expected_result);
870 op_stack.pop_scope();
871 op_stack.push_scope();
872 // Overwrite the branch from the `if` with the `else`.
873 // We're left with a normal relocation list where everything
874 // branches to the corresponding `end`
875 relocations[0] = code_writer.emit_else(relocations[0]);
876 old_index.is_if = false;
877 _nested_checker.on_control(_options);
878 break;
879 }
880 case opcodes::br: {
881 check_in_bounds();
883 auto branch = code_writer.emit_br(compute_depth_change(label));
884 handle_branch_target(label, branch);
885 op_stack.start_unreachable();
886 } break;
887 case opcodes::br_if: {
888 check_in_bounds();
890 op_stack.pop(types::i32);
891 auto branch = code_writer.emit_br_if(compute_depth_change(label));
892 handle_branch_target(label, branch);
893 } break;
894 case opcodes::br_table: {
895 check_in_bounds();
896 size_t table_size = parse_varuint32(code);
897 SYS_VM_ASSERT(table_size <= detail::get_max_br_table_elements(_options), wasm_parse_exception, "Too many labels in br_table");
898 uint8_t result_type = 0;
899 op_stack.pop(types::i32);
900 auto handler = code_writer.emit_br_table(table_size);
901 for (size_t i = 0; i < table_size; i++) {
903 auto branch = handler.emit_case(compute_depth_change(label));
904 handle_branch_target(label, branch);
905 uint8_t one_result = pc_stack[pc_stack.size() - label - 1].label_result;
906 if(i == 0) {
907 result_type = one_result;
908 } else {
909 SYS_VM_ASSERT(result_type == one_result, wasm_parse_exception, "br_table labels must have the same type");
910 }
911 }
913 auto branch = handler.emit_default(compute_depth_change(label));
914 handle_branch_target(label, branch);
915 SYS_VM_ASSERT(table_size == 0 || result_type == pc_stack[pc_stack.size() - label - 1].label_result,
916 wasm_parse_exception, "br_table labels must have the same type");
917 op_stack.start_unreachable();
918 } break;
919 case opcodes::call: {
920 check_in_bounds();
921 uint32_t funcnum = parse_varuint32(code);
922 const func_type& ft = _mod->get_function_type(funcnum);
923 for(uint32_t i = 0; i < ft.param_types.size(); ++i)
924 op_stack.pop(ft.param_types[ft.param_types.size() - i - 1]);
925 SYS_VM_ASSERT(ft.return_count <= 1, wasm_parse_exception, "unsupported");
926 if(ft.return_count)
927 op_stack.push(ft.return_type);
928 code_writer.emit_call(ft, funcnum);
929 } break;
930 case opcodes::call_indirect: {
931 check_in_bounds();
932 uint32_t functypeidx = parse_varuint32(code);
933 const func_type& ft = _mod->types.at(functypeidx);
934 SYS_VM_ASSERT(_mod->tables.size() > 0, wasm_parse_exception, "call_indirect requires a table");
935 op_stack.pop(types::i32);
936 for(uint32_t i = 0; i < ft.param_types.size(); ++i)
937 op_stack.pop(ft.param_types[ft.param_types.size() - i - 1]);
938 SYS_VM_ASSERT(ft.return_count <= 1, wasm_parse_exception, "unsupported");
939 if(ft.return_count)
940 op_stack.push(ft.return_type);
941 code_writer.emit_call_indirect(ft, functypeidx);
942 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "call_indirect must end with 0x00.");
943 code++; // 0x00
944 break;
945 }
946 case opcodes::drop: check_in_bounds(); code_writer.emit_drop(); op_stack.pop(); break;
947 case opcodes::select: {
948 check_in_bounds();
949 code_writer.emit_select();
950 op_stack.pop(types::i32);
951 uint8_t t0 = op_stack.pop();
952 uint8_t t1 = op_stack.pop();
953 SYS_VM_ASSERT(t0 == t1 || t0 == any_type || t1 == any_type, wasm_parse_exception, "incorrect types for select");
954 op_stack.push(t0 != any_type? t0 : t1);
955 } break;
956 case opcodes::get_local: {
957 uint32_t local_idx = parse_varuint32(code);
958 op_stack.push(local_types[local_idx]);
959 code_writer.emit_get_local(local_idx);
960 } break;
961 case opcodes::set_local: {
962 check_in_bounds();
963 uint32_t local_idx = parse_varuint32(code);
964 op_stack.pop(local_types[local_idx]);
965 code_writer.emit_set_local(local_idx);
966 } break;
967 case opcodes::tee_local: {
968 check_in_bounds();
969 uint32_t local_idx = parse_varuint32(code);
970 op_stack.top(local_types[local_idx]);
971 code_writer.emit_tee_local(local_idx);
972 } break;
973 case opcodes::get_global: {
974 uint32_t global_idx = parse_varuint32(code);
975 op_stack.push(_mod->globals.at(global_idx).type.content_type);
976 code_writer.emit_get_global(global_idx);
977 } break;
978 case opcodes::set_global: {
979 check_in_bounds();
980 uint32_t global_idx = parse_varuint32(code);
981 SYS_VM_ASSERT(_mod->globals.at(global_idx).type.mutability, wasm_parse_exception, "cannot set const global");
982 op_stack.pop(_mod->globals.at(global_idx).type.content_type);
983 code_writer.emit_set_global(global_idx);
984 } break;
985#define LOAD_OP(op_name, max_align, type) \
986 case opcodes::op_name: { \
987 check_in_bounds(); \
988 SYS_VM_ASSERT(_mod->memories.size() > 0, wasm_parse_exception, "load requires memory"); \
989 uint32_t alignment = parse_varuint32(code); \
990 uint32_t offset = parse_varuint32(code); \
991 SYS_VM_ASSERT(alignment <= uint32_t(max_align), wasm_parse_exception, "alignment cannot be greater than size."); \
992 SYS_VM_ASSERT(offset <= detail::get_max_memory_offset(_options), wasm_parse_exception, "load offset too large."); \
993 op_stack.pop(types::i32); \
994 op_stack.push(types::type); \
995 code_writer.emit_ ## op_name( alignment, offset ); \
996 } break;
997
998 LOAD_OP(i32_load, 2, i32)
999 LOAD_OP(i64_load, 3, i64)
1000 LOAD_OP(f32_load, 2, f32)
1001 LOAD_OP(f64_load, 3, f64)
1002 LOAD_OP(i32_load8_s, 0, i32)
1003 LOAD_OP(i32_load16_s, 1, i32)
1004 LOAD_OP(i32_load8_u, 0, i32)
1005 LOAD_OP(i32_load16_u, 1, i32)
1006 LOAD_OP(i64_load8_s, 0, i64)
1007 LOAD_OP(i64_load16_s, 1, i64)
1008 LOAD_OP(i64_load32_s, 2, i64)
1009 LOAD_OP(i64_load8_u, 0, i64)
1010 LOAD_OP(i64_load16_u, 1, i64)
1011 LOAD_OP(i64_load32_u, 2, i64)
1012
1013#undef LOAD_OP
1014
1015#define STORE_OP(op_name, max_align, type) \
1016 case opcodes::op_name: { \
1017 check_in_bounds(); \
1018 SYS_VM_ASSERT(_mod->memories.size() > 0, wasm_parse_exception, "store requires memory"); \
1019 uint32_t alignment = parse_varuint32(code); \
1020 uint32_t offset = parse_varuint32(code); \
1021 SYS_VM_ASSERT(alignment <= uint32_t(max_align), wasm_parse_exception, "alignment cannot be greater than size."); \
1022 SYS_VM_ASSERT(offset <= detail::get_max_memory_offset(_options), wasm_parse_exception, "store offset too large."); \
1023 op_stack.pop(types::type); \
1024 op_stack.pop(types::i32); \
1025 code_writer.emit_ ## op_name( alignment, offset ); \
1026 } break;
1027
1028 STORE_OP(i32_store, 2, i32)
1029 STORE_OP(i64_store, 3, i64)
1030 STORE_OP(f32_store, 2, f32)
1031 STORE_OP(f64_store, 3, f64)
1032 STORE_OP(i32_store8, 0, i32)
1033 STORE_OP(i32_store16, 1, i32)
1034 STORE_OP(i64_store8, 0, i64)
1035 STORE_OP(i64_store16, 1, i64)
1036 STORE_OP(i64_store32, 2, i64)
1037
1038#undef STORE_OP
1039
1040 case opcodes::current_memory:
1041 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "memory.size requires memory");
1042 op_stack.push(types::i32);
1043 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "memory.size must end with 0x00");
1044 code++;
1045 code_writer.emit_current_memory();
1046 break;
1047 case opcodes::grow_memory:
1048 check_in_bounds();
1049 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "memory.grow requires memory");
1050 op_stack.pop(types::i32);
1051 op_stack.push(types::i32);
1052 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "memory.grow must end with 0x00");
1053 code++;
1054 code_writer.emit_grow_memory();
1055 break;
1056 case opcodes::i32_const: code_writer.emit_i32_const( parse_varint32(code) ); op_stack.push(types::i32); break;
1057 case opcodes::i64_const: code_writer.emit_i64_const( parse_varint64(code) ); op_stack.push(types::i64); break;
1058 case opcodes::f32_const: {
1059 code_writer.emit_f32_const( parse_raw<float>(code) );
1060 op_stack.push(types::f32);
1061 } break;
1062 case opcodes::f64_const: {
1063 code_writer.emit_f64_const( parse_raw<double>(code) );
1064 op_stack.push(types::f64);
1065 } break;
1066
1067#define UNOP(opname) \
1068 case opcodes::opname: check_in_bounds(); code_writer.emit_ ## opname(); op_stack.pop(types::A); op_stack.push(types::R); break;
1069#define BINOP(opname) \
1070 case opcodes::opname: check_in_bounds(); code_writer.emit_ ## opname(); op_stack.pop(types::A); op_stack.pop(types::A); op_stack.push(types::R); break;
1071#define CASTOP(dst, opname, src) \
1072 case opcodes::dst ## _ ## opname ## _ ## src: check_in_bounds(); code_writer.emit_ ## dst ## _ ## opname ## _ ## src(); op_stack.pop(types::src); op_stack.push(types::dst); break;
1073
1074#define R i32
1075#define A i32
1076 UNOP(i32_eqz)
1077 BINOP(i32_eq)
1078 BINOP(i32_ne)
1079 BINOP(i32_lt_s)
1080 BINOP(i32_lt_u)
1081 BINOP(i32_gt_s)
1082 BINOP(i32_gt_u)
1083 BINOP(i32_le_s)
1084 BINOP(i32_le_u)
1085 BINOP(i32_ge_s)
1086 BINOP(i32_ge_u)
1087#undef A
1088#define A i64
1089 UNOP(i64_eqz)
1090 BINOP(i64_eq)
1091 BINOP(i64_ne)
1092 BINOP(i64_lt_s)
1093 BINOP(i64_lt_u)
1094 BINOP(i64_gt_s)
1095 BINOP(i64_gt_u)
1096 BINOP(i64_le_s)
1097 BINOP(i64_le_u)
1098 BINOP(i64_ge_s)
1099 BINOP(i64_ge_u)
1100#undef A
1101#define A f32
1102 BINOP(f32_eq)
1103 BINOP(f32_ne)
1104 BINOP(f32_lt)
1105 BINOP(f32_gt)
1106 BINOP(f32_le)
1107 BINOP(f32_ge)
1108#undef A
1109#define A f64
1110 BINOP(f64_eq)
1111 BINOP(f64_ne)
1112 BINOP(f64_lt)
1113 BINOP(f64_gt)
1114 BINOP(f64_le)
1115 BINOP(f64_ge)
1116#undef A
1117#undef R
1118#define R A
1119#define A i32
1120 UNOP(i32_clz)
1121 UNOP(i32_ctz)
1122 UNOP(i32_popcnt)
1123 BINOP(i32_add)
1124 BINOP(i32_sub)
1125 BINOP(i32_mul)
1126 BINOP(i32_div_s)
1127 BINOP(i32_div_u)
1128 BINOP(i32_rem_s)
1129 BINOP(i32_rem_u)
1130 BINOP(i32_and)
1131 BINOP(i32_or)
1132 BINOP(i32_xor)
1133 BINOP(i32_shl)
1134 BINOP(i32_shr_s)
1135 BINOP(i32_shr_u)
1136 BINOP(i32_rotl)
1137 BINOP(i32_rotr)
1138#undef A
1139#define A i64
1140 UNOP(i64_clz)
1141 UNOP(i64_ctz)
1142 UNOP(i64_popcnt)
1143 BINOP(i64_add)
1144 BINOP(i64_sub)
1145 BINOP(i64_mul)
1146 BINOP(i64_div_s)
1147 BINOP(i64_div_u)
1148 BINOP(i64_rem_s)
1149 BINOP(i64_rem_u)
1150 BINOP(i64_and)
1151 BINOP(i64_or)
1152 BINOP(i64_xor)
1153 BINOP(i64_shl)
1154 BINOP(i64_shr_s)
1155 BINOP(i64_shr_u)
1156 BINOP(i64_rotl)
1157 BINOP(i64_rotr)
1158#undef A
1159#define A f32
1160 UNOP(f32_abs)
1161 UNOP(f32_neg)
1162 UNOP(f32_ceil)
1163 UNOP(f32_floor)
1164 UNOP(f32_trunc)
1165 UNOP(f32_nearest)
1166 UNOP(f32_sqrt)
1167 BINOP(f32_add)
1168 BINOP(f32_sub)
1169 BINOP(f32_mul)
1170 BINOP(f32_div)
1171 BINOP(f32_min)
1172 BINOP(f32_max)
1173 BINOP(f32_copysign)
1174#undef A
1175#define A f64
1176 UNOP(f64_abs)
1177 UNOP(f64_neg)
1178 UNOP(f64_ceil)
1179 UNOP(f64_floor)
1180 UNOP(f64_trunc)
1181 UNOP(f64_nearest)
1182 UNOP(f64_sqrt)
1183 BINOP(f64_add)
1184 BINOP(f64_sub)
1185 BINOP(f64_mul)
1186 BINOP(f64_div)
1187 BINOP(f64_min)
1188 BINOP(f64_max)
1189 BINOP(f64_copysign)
1190#undef A
1191#undef R
1192
1193 CASTOP(i32, wrap, i64)
1194 CASTOP(i32, trunc_s, f32)
1195 CASTOP(i32, trunc_u, f32)
1196 CASTOP(i32, trunc_s, f64)
1197 CASTOP(i32, trunc_u, f64)
1198 CASTOP(i64, extend_s, i32)
1199 CASTOP(i64, extend_u, i32)
1200 CASTOP(i64, trunc_s, f32)
1201 CASTOP(i64, trunc_u, f32)
1202 CASTOP(i64, trunc_s, f64)
1203 CASTOP(i64, trunc_u, f64)
1204 CASTOP(f32, convert_s, i32)
1205 CASTOP(f32, convert_u, i32)
1206 CASTOP(f32, convert_s, i64)
1207 CASTOP(f32, convert_u, i64)
1208 CASTOP(f32, demote, f64)
1209 CASTOP(f64, convert_s, i32)
1210 CASTOP(f64, convert_u, i32)
1211 CASTOP(f64, convert_s, i64)
1212 CASTOP(f64, convert_u, i64)
1213 CASTOP(f64, promote, f32)
1214 CASTOP(i32, reinterpret, f32)
1215 CASTOP(i64, reinterpret, f64)
1216 CASTOP(f32, reinterpret, i32)
1217 CASTOP(f64, reinterpret, i64)
1218
1219#undef CASTOP
1220#undef UNOP
1221#undef BINOP
1222 default: SYS_VM_ASSERT(false, wasm_parse_exception, "Illegal instruction");
1223 }
1224 }
1225 SYS_VM_ASSERT( pc_stack.empty(), wasm_parse_exception, "function body too long" );
1226 _mod->maximum_stack = std::max(_mod->maximum_stack, static_cast<uint64_t>(op_stack.maximum_operand_depth) + local_types.locals_count());
1227 }
decltype(std::declval< Writer >().emit_if()) branch_t
Definition parser.hpp:614
decltype(std::declval< Writer >().emit_end()) label_t
Definition parser.hpp:613
T parse_raw(wasm_code_ptr &code)
Definition parser.hpp:283
static int32_t parse_varint32(wasm_code_ptr &code)
Definition parser.hpp:217
static constexpr uint8_t any_type
Definition parser.hpp:623
static int64_t parse_varint64(wasm_code_ptr &code)
Definition parser.hpp:219
Definition name.hpp:106
overloaded(Ts...) -> overloaded< Ts... >
float32_t f32_add(float32_t a, float32_t b)
Definition f32_add.c:43
float32_t f32_div(float32_t a, float32_t b)
Definition f32_div.c:44
bool f32_eq(float32_t a, float32_t b)
Definition f32_eq.c:44
bool f32_le(float32_t a, float32_t b)
Definition f32_le.c:43
bool f32_lt(float32_t a, float32_t b)
Definition f32_lt.c:43
float32_t f32_mul(float32_t a, float32_t b)
Definition f32_mul.c:44
float32_t f32_sqrt(float32_t a)
Definition f32_sqrt.c:44
float32_t f32_sub(float32_t a, float32_t b)
Definition f32_sub.c:43
float64_t f64_add(float64_t a, float64_t b)
Definition f64_add.c:43
float64_t f64_div(float64_t a, float64_t b)
Definition f64_div.c:44
bool f64_eq(float64_t a, float64_t b)
Definition f64_eq.c:44
bool f64_le(float64_t a, float64_t b)
Definition f64_le.c:43
bool f64_lt(float64_t a, float64_t b)
Definition f64_lt.c:43
float64_t f64_mul(float64_t a, float64_t b)
Definition f64_mul.c:44
float64_t f64_sqrt(float64_t a)
Definition f64_sqrt.c:44
float64_t f64_sub(float64_t a, float64_t b)
Definition f64_sub.c:43
const unsigned char expected_result[]
Definition ssh.c:73
auto & get_function_type(uint32_t index) const
Definition types.hpp:221
uint64_t maximum_stack
Definition types.hpp:187
#define CASTOP(dst, opname, src)
#define UNOP
#define LOAD_OP
#define STORE_OP
#define BINOP
char * label
Here is the call graph for this function:

◆ parse_function_body_code() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_function_body_code ( wasm_code_ptr & code,
size_t bounds,
const detail::max_func_local_bytes_stack_checker< Options > & local_bytes_checker,
Writer & code_writer,
const func_type & ft,
const local_types_t & local_types )
inline

Definition at line 734 of file parser.hpp.

735 {
736
737 // Initialize the control stack with the current function as the sole element
738 operand_stack_type_tracker op_stack{local_bytes_checker, _options};
739 std::vector<pc_element_t> pc_stack{{
740 op_stack.depth(),
741 ft.return_count ? ft.return_type : static_cast<uint32_t>(types::pseudo),
742 ft.return_count ? ft.return_type : static_cast<uint32_t>(types::pseudo),
743 false,
744 std::vector<branch_t>{}}};
745
746 // writes the continuation of a label to address. If the continuation
747 // is not yet available, address will be recorded in the relocations
748 // list for label.
749 auto handle_branch_target = [&](uint32_t label, branch_t address) {
750 SYS_VM_ASSERT(label < pc_stack.size(), wasm_parse_exception, "invalid label");
751 pc_element_t& branch_target = pc_stack[pc_stack.size() - label - 1];
752 std::visit(overloaded{ [&](label_t target) { code_writer.fix_branch(address, target); },
753 [&](std::vector<branch_t>& relocations) { relocations.push_back(address); } },
754 branch_target.relocations);
755 };
756
757 // Returns the number of operands that need to be popped when
758 // branching to label. If the label has a return value it will
759 // be counted in this, and the high bit will be set to signal
760 // its presence.
761 auto compute_depth_change = [&](uint32_t label) -> uint32_t {
762 SYS_VM_ASSERT(label < pc_stack.size(), wasm_parse_exception, "invalid label");
763 pc_element_t& branch_target = pc_stack[pc_stack.size() - label - 1];
764 uint32_t result = op_stack.depth() - branch_target.operand_depth;
765 if(branch_target.label_result != types::pseudo) {
766 // FIXME: Reusing the high bit imposes an additional constraint
767 // on the maximum depth of the operand stack. This isn't an
768 // actual problem right now, because the stack is hard-coded
769 // to 8192 elements, but it would be better to avoid spreading
770 // this assumption around the code.
771 result |= 0x80000000;
772 op_stack.top(branch_target.label_result);
773 }
774 return result;
775 };
776
777 // Handles branches to the end of the scope and pops the pc_stack
778 auto exit_scope = [&]() {
779 // There must be at least one element
780 SYS_VM_ASSERT(pc_stack.size(), wasm_parse_exception, "unexpected end instruction");
781 // an if with an empty else cannot have a return value
782 SYS_VM_ASSERT(!pc_stack.back().is_if || pc_stack.back().expected_result == types::pseudo, wasm_parse_exception, "wrong type");
783 auto end_pos = code_writer.emit_end();
784 if(auto* relocations = std::get_if<std::vector<branch_t>>(&pc_stack.back().relocations)) {
785 for(auto branch_op : *relocations) {
786 code_writer.fix_branch(branch_op, end_pos);
787 }
788 }
789 op_stack.pop_scope(pc_stack.back().expected_result);
790 pc_stack.pop_back();
791 };
792
793 auto check_in_bounds = [&]{
794 SYS_VM_ASSERT(!detail::get_allow_code_after_function_end(_options) || !pc_stack.empty(),
795 wasm_parse_exception, "code after function end");
796 };
797
798 while (code.offset() < bounds) {
799 SYS_VM_ASSERT(pc_stack.size() <= detail::get_max_nested_structures(_options), wasm_parse_exception,
800 "nested structures validation failure");
801
802 imap.on_instr_start(code_writer.get_addr(), code.raw());
803
804 switch (*code++) {
805 case opcodes::unreachable: check_in_bounds(); code_writer.emit_unreachable(); op_stack.start_unreachable(); break;
806 case opcodes::nop: code_writer.emit_nop(); break;
807 case opcodes::end: {
808 check_in_bounds();
809 exit_scope();
810 SYS_VM_ASSERT(detail::get_allow_code_after_function_end(_options) ||
811 !pc_stack.empty() || code.offset() == bounds, wasm_parse_exception, "function too short");
812 _nested_checker.on_end(_options);
813 break;
814 }
815 case opcodes::return_: {
816 check_in_bounds();
817 uint32_t label = pc_stack.size() - 1;
818 auto branch = code_writer.emit_return(compute_depth_change(label));
819 handle_branch_target(label, branch);
820 op_stack.start_unreachable();
821 } break;
822 case opcodes::block: {
823 uint32_t expected_result = *code++;
824 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
825 expected_result = types::pseudo;
826 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
827 expected_result == types::f32 || expected_result == types::f64 ||
828 expected_result == types::pseudo, wasm_parse_exception,
829 "Invalid type code in block");
830 pc_stack.push_back({op_stack.depth(), expected_result, expected_result, false, std::vector<branch_t>{}});
831 code_writer.emit_block();
832 op_stack.push_scope();
833 _nested_checker.on_control(_options);
834 } break;
835 case opcodes::loop: {
836 uint32_t expected_result = *code++;
837 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
838 expected_result = types::pseudo;
839 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
840 expected_result == types::f32 || expected_result == types::f64 ||
841 expected_result == types::pseudo, wasm_parse_exception,
842 "Invalid type code in loop");
843 auto pos = code_writer.emit_loop();
844 pc_stack.push_back({op_stack.depth(), expected_result, types::pseudo, false, pos});
845 op_stack.push_scope();
846 _nested_checker.on_control(_options);
847 } break;
848 case opcodes::if_: {
849 check_in_bounds();
850 uint32_t expected_result = *code++;
851 if(detail::get_allow_zero_blocktype(_options) && expected_result == 0)
852 expected_result = types::pseudo;
853 SYS_VM_ASSERT(expected_result == types::i32 || expected_result == types::i64 ||
854 expected_result == types::f32 || expected_result == types::f64 ||
855 expected_result == types::pseudo, wasm_parse_exception,
856 "Invalid type code in if");
857 auto branch = code_writer.emit_if();
858 op_stack.pop(types::i32);
859 pc_stack.push_back({op_stack.depth(), expected_result, expected_result, true, std::vector{branch}});
860 op_stack.push_scope();
861 _nested_checker.on_control(_options);
862 } break;
863 case opcodes::else_: {
864 check_in_bounds();
865 auto& old_index = pc_stack.back();
866 SYS_VM_ASSERT(old_index.is_if, wasm_parse_exception, "else outside if");
867 auto& relocations = std::get<std::vector<branch_t>>(old_index.relocations);
868 // reset the operand stack to the same state as the if
869 op_stack.pop(old_index.expected_result);
870 op_stack.pop_scope();
871 op_stack.push_scope();
872 // Overwrite the branch from the `if` with the `else`.
873 // We're left with a normal relocation list where everything
874 // branches to the corresponding `end`
875 relocations[0] = code_writer.emit_else(relocations[0]);
876 old_index.is_if = false;
877 _nested_checker.on_control(_options);
878 break;
879 }
880 case opcodes::br: {
881 check_in_bounds();
883 auto branch = code_writer.emit_br(compute_depth_change(label));
884 handle_branch_target(label, branch);
885 op_stack.start_unreachable();
886 } break;
887 case opcodes::br_if: {
888 check_in_bounds();
890 op_stack.pop(types::i32);
891 auto branch = code_writer.emit_br_if(compute_depth_change(label));
892 handle_branch_target(label, branch);
893 } break;
894 case opcodes::br_table: {
895 check_in_bounds();
896 size_t table_size = parse_varuint32(code);
897 SYS_VM_ASSERT(table_size <= detail::get_max_br_table_elements(_options), wasm_parse_exception, "Too many labels in br_table");
898 uint8_t result_type = 0;
899 op_stack.pop(types::i32);
900 auto handler = code_writer.emit_br_table(table_size);
901 for (size_t i = 0; i < table_size; i++) {
903 auto branch = handler.emit_case(compute_depth_change(label));
904 handle_branch_target(label, branch);
905 uint8_t one_result = pc_stack[pc_stack.size() - label - 1].label_result;
906 if(i == 0) {
907 result_type = one_result;
908 } else {
909 SYS_VM_ASSERT(result_type == one_result, wasm_parse_exception, "br_table labels must have the same type");
910 }
911 }
913 auto branch = handler.emit_default(compute_depth_change(label));
914 handle_branch_target(label, branch);
915 SYS_VM_ASSERT(table_size == 0 || result_type == pc_stack[pc_stack.size() - label - 1].label_result,
916 wasm_parse_exception, "br_table labels must have the same type");
917 op_stack.start_unreachable();
918 } break;
919 case opcodes::call: {
920 check_in_bounds();
921 uint32_t funcnum = parse_varuint32(code);
922 const func_type& ft = _mod->get_function_type(funcnum);
923 for(uint32_t i = 0; i < ft.param_types.size(); ++i)
924 op_stack.pop(ft.param_types[ft.param_types.size() - i - 1]);
925 SYS_VM_ASSERT(ft.return_count <= 1, wasm_parse_exception, "unsupported");
926 if(ft.return_count)
927 op_stack.push(ft.return_type);
928 code_writer.emit_call(ft, funcnum);
929 } break;
930 case opcodes::call_indirect: {
931 check_in_bounds();
932 uint32_t functypeidx = parse_varuint32(code);
933 const func_type& ft = _mod->types.at(functypeidx);
934 SYS_VM_ASSERT(_mod->tables.size() > 0, wasm_parse_exception, "call_indirect requires a table");
935 op_stack.pop(types::i32);
936 for(uint32_t i = 0; i < ft.param_types.size(); ++i)
937 op_stack.pop(ft.param_types[ft.param_types.size() - i - 1]);
938 SYS_VM_ASSERT(ft.return_count <= 1, wasm_parse_exception, "unsupported");
939 if(ft.return_count)
940 op_stack.push(ft.return_type);
941 code_writer.emit_call_indirect(ft, functypeidx);
942 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "call_indirect must end with 0x00.");
943 code++; // 0x00
944 break;
945 }
946 case opcodes::drop: check_in_bounds(); code_writer.emit_drop(); op_stack.pop(); break;
947 case opcodes::select: {
948 check_in_bounds();
949 code_writer.emit_select();
950 op_stack.pop(types::i32);
951 uint8_t t0 = op_stack.pop();
952 uint8_t t1 = op_stack.pop();
953 SYS_VM_ASSERT(t0 == t1 || t0 == any_type || t1 == any_type, wasm_parse_exception, "incorrect types for select");
954 op_stack.push(t0 != any_type? t0 : t1);
955 } break;
956 case opcodes::get_local: {
957 uint32_t local_idx = parse_varuint32(code);
958 op_stack.push(local_types[local_idx]);
959 code_writer.emit_get_local(local_idx);
960 } break;
961 case opcodes::set_local: {
962 check_in_bounds();
963 uint32_t local_idx = parse_varuint32(code);
964 op_stack.pop(local_types[local_idx]);
965 code_writer.emit_set_local(local_idx);
966 } break;
967 case opcodes::tee_local: {
968 check_in_bounds();
969 uint32_t local_idx = parse_varuint32(code);
970 op_stack.top(local_types[local_idx]);
971 code_writer.emit_tee_local(local_idx);
972 } break;
973 case opcodes::get_global: {
974 uint32_t global_idx = parse_varuint32(code);
975 op_stack.push(_mod->globals.at(global_idx).type.content_type);
976 code_writer.emit_get_global(global_idx);
977 } break;
978 case opcodes::set_global: {
979 check_in_bounds();
980 uint32_t global_idx = parse_varuint32(code);
981 SYS_VM_ASSERT(_mod->globals.at(global_idx).type.mutability, wasm_parse_exception, "cannot set const global");
982 op_stack.pop(_mod->globals.at(global_idx).type.content_type);
983 code_writer.emit_set_global(global_idx);
984 } break;
985#define LOAD_OP(op_name, max_align, type) \
986 case opcodes::op_name: { \
987 check_in_bounds(); \
988 SYS_VM_ASSERT(_mod->memories.size() > 0, wasm_parse_exception, "load requires memory"); \
989 uint32_t alignment = parse_varuint32(code); \
990 uint32_t offset = parse_varuint32(code); \
991 SYS_VM_ASSERT(alignment <= uint32_t(max_align), wasm_parse_exception, "alignment cannot be greater than size."); \
992 SYS_VM_ASSERT(offset <= detail::get_max_memory_offset(_options), wasm_parse_exception, "load offset too large."); \
993 op_stack.pop(types::i32); \
994 op_stack.push(types::type); \
995 code_writer.emit_ ## op_name( alignment, offset ); \
996 } break;
997
998 LOAD_OP(i32_load, 2, i32)
999 LOAD_OP(i64_load, 3, i64)
1000 LOAD_OP(f32_load, 2, f32)
1001 LOAD_OP(f64_load, 3, f64)
1002 LOAD_OP(i32_load8_s, 0, i32)
1003 LOAD_OP(i32_load16_s, 1, i32)
1004 LOAD_OP(i32_load8_u, 0, i32)
1005 LOAD_OP(i32_load16_u, 1, i32)
1006 LOAD_OP(i64_load8_s, 0, i64)
1007 LOAD_OP(i64_load16_s, 1, i64)
1008 LOAD_OP(i64_load32_s, 2, i64)
1009 LOAD_OP(i64_load8_u, 0, i64)
1010 LOAD_OP(i64_load16_u, 1, i64)
1011 LOAD_OP(i64_load32_u, 2, i64)
1012
1013#undef LOAD_OP
1014
1015#define STORE_OP(op_name, max_align, type) \
1016 case opcodes::op_name: { \
1017 check_in_bounds(); \
1018 SYS_VM_ASSERT(_mod->memories.size() > 0, wasm_parse_exception, "store requires memory"); \
1019 uint32_t alignment = parse_varuint32(code); \
1020 uint32_t offset = parse_varuint32(code); \
1021 SYS_VM_ASSERT(alignment <= uint32_t(max_align), wasm_parse_exception, "alignment cannot be greater than size."); \
1022 SYS_VM_ASSERT(offset <= detail::get_max_memory_offset(_options), wasm_parse_exception, "store offset too large."); \
1023 op_stack.pop(types::type); \
1024 op_stack.pop(types::i32); \
1025 code_writer.emit_ ## op_name( alignment, offset ); \
1026 } break;
1027
1028 STORE_OP(i32_store, 2, i32)
1029 STORE_OP(i64_store, 3, i64)
1030 STORE_OP(f32_store, 2, f32)
1031 STORE_OP(f64_store, 3, f64)
1032 STORE_OP(i32_store8, 0, i32)
1033 STORE_OP(i32_store16, 1, i32)
1034 STORE_OP(i64_store8, 0, i64)
1035 STORE_OP(i64_store16, 1, i64)
1036 STORE_OP(i64_store32, 2, i64)
1037
1038#undef STORE_OP
1039
1040 case opcodes::current_memory:
1041 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "memory.size requires memory");
1042 op_stack.push(types::i32);
1043 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "memory.size must end with 0x00");
1044 code++;
1045 code_writer.emit_current_memory();
1046 break;
1047 case opcodes::grow_memory:
1048 check_in_bounds();
1049 SYS_VM_ASSERT(_mod->memories.size() != 0, wasm_parse_exception, "memory.grow requires memory");
1050 op_stack.pop(types::i32);
1051 op_stack.push(types::i32);
1052 SYS_VM_ASSERT(*code == 0, wasm_parse_exception, "memory.grow must end with 0x00");
1053 code++;
1054 code_writer.emit_grow_memory();
1055 break;
1056 case opcodes::i32_const: code_writer.emit_i32_const( parse_varint32(code) ); op_stack.push(types::i32); break;
1057 case opcodes::i64_const: code_writer.emit_i64_const( parse_varint64(code) ); op_stack.push(types::i64); break;
1058 case opcodes::f32_const: {
1059 code_writer.emit_f32_const( parse_raw<float>(code) );
1060 op_stack.push(types::f32);
1061 } break;
1062 case opcodes::f64_const: {
1063 code_writer.emit_f64_const( parse_raw<double>(code) );
1064 op_stack.push(types::f64);
1065 } break;
1066
1067#define UNOP(opname) \
1068 case opcodes::opname: check_in_bounds(); code_writer.emit_ ## opname(); op_stack.pop(types::A); op_stack.push(types::R); break;
1069#define BINOP(opname) \
1070 case opcodes::opname: check_in_bounds(); code_writer.emit_ ## opname(); op_stack.pop(types::A); op_stack.pop(types::A); op_stack.push(types::R); break;
1071#define CASTOP(dst, opname, src) \
1072 case opcodes::dst ## _ ## opname ## _ ## src: check_in_bounds(); code_writer.emit_ ## dst ## _ ## opname ## _ ## src(); op_stack.pop(types::src); op_stack.push(types::dst); break;
1073
1074#define R i32
1075#define A i32
1076 UNOP(i32_eqz)
1077 BINOP(i32_eq)
1078 BINOP(i32_ne)
1079 BINOP(i32_lt_s)
1080 BINOP(i32_lt_u)
1081 BINOP(i32_gt_s)
1082 BINOP(i32_gt_u)
1083 BINOP(i32_le_s)
1084 BINOP(i32_le_u)
1085 BINOP(i32_ge_s)
1086 BINOP(i32_ge_u)
1087#undef A
1088#define A i64
1089 UNOP(i64_eqz)
1090 BINOP(i64_eq)
1091 BINOP(i64_ne)
1092 BINOP(i64_lt_s)
1093 BINOP(i64_lt_u)
1094 BINOP(i64_gt_s)
1095 BINOP(i64_gt_u)
1096 BINOP(i64_le_s)
1097 BINOP(i64_le_u)
1098 BINOP(i64_ge_s)
1099 BINOP(i64_ge_u)
1100#undef A
1101#define A f32
1102 BINOP(f32_eq)
1103 BINOP(f32_ne)
1104 BINOP(f32_lt)
1105 BINOP(f32_gt)
1106 BINOP(f32_le)
1107 BINOP(f32_ge)
1108#undef A
1109#define A f64
1110 BINOP(f64_eq)
1111 BINOP(f64_ne)
1112 BINOP(f64_lt)
1113 BINOP(f64_gt)
1114 BINOP(f64_le)
1115 BINOP(f64_ge)
1116#undef A
1117#undef R
1118#define R A
1119#define A i32
1120 UNOP(i32_clz)
1121 UNOP(i32_ctz)
1122 UNOP(i32_popcnt)
1123 BINOP(i32_add)
1124 BINOP(i32_sub)
1125 BINOP(i32_mul)
1126 BINOP(i32_div_s)
1127 BINOP(i32_div_u)
1128 BINOP(i32_rem_s)
1129 BINOP(i32_rem_u)
1130 BINOP(i32_and)
1131 BINOP(i32_or)
1132 BINOP(i32_xor)
1133 BINOP(i32_shl)
1134 BINOP(i32_shr_s)
1135 BINOP(i32_shr_u)
1136 BINOP(i32_rotl)
1137 BINOP(i32_rotr)
1138#undef A
1139#define A i64
1140 UNOP(i64_clz)
1141 UNOP(i64_ctz)
1142 UNOP(i64_popcnt)
1143 BINOP(i64_add)
1144 BINOP(i64_sub)
1145 BINOP(i64_mul)
1146 BINOP(i64_div_s)
1147 BINOP(i64_div_u)
1148 BINOP(i64_rem_s)
1149 BINOP(i64_rem_u)
1150 BINOP(i64_and)
1151 BINOP(i64_or)
1152 BINOP(i64_xor)
1153 BINOP(i64_shl)
1154 BINOP(i64_shr_s)
1155 BINOP(i64_shr_u)
1156 BINOP(i64_rotl)
1157 BINOP(i64_rotr)
1158#undef A
1159#define A f32
1160 UNOP(f32_abs)
1161 UNOP(f32_neg)
1162 UNOP(f32_ceil)
1163 UNOP(f32_floor)
1164 UNOP(f32_trunc)
1165 UNOP(f32_nearest)
1166 UNOP(f32_sqrt)
1167 BINOP(f32_add)
1168 BINOP(f32_sub)
1169 BINOP(f32_mul)
1170 BINOP(f32_div)
1171 BINOP(f32_min)
1172 BINOP(f32_max)
1173 BINOP(f32_copysign)
1174#undef A
1175#define A f64
1176 UNOP(f64_abs)
1177 UNOP(f64_neg)
1178 UNOP(f64_ceil)
1179 UNOP(f64_floor)
1180 UNOP(f64_trunc)
1181 UNOP(f64_nearest)
1182 UNOP(f64_sqrt)
1183 BINOP(f64_add)
1184 BINOP(f64_sub)
1185 BINOP(f64_mul)
1186 BINOP(f64_div)
1187 BINOP(f64_min)
1188 BINOP(f64_max)
1189 BINOP(f64_copysign)
1190#undef A
1191#undef R
1192
1193 CASTOP(i32, wrap, i64)
1194 CASTOP(i32, trunc_s, f32)
1195 CASTOP(i32, trunc_u, f32)
1196 CASTOP(i32, trunc_s, f64)
1197 CASTOP(i32, trunc_u, f64)
1198 CASTOP(i64, extend_s, i32)
1199 CASTOP(i64, extend_u, i32)
1200 CASTOP(i64, trunc_s, f32)
1201 CASTOP(i64, trunc_u, f32)
1202 CASTOP(i64, trunc_s, f64)
1203 CASTOP(i64, trunc_u, f64)
1204 CASTOP(f32, convert_s, i32)
1205 CASTOP(f32, convert_u, i32)
1206 CASTOP(f32, convert_s, i64)
1207 CASTOP(f32, convert_u, i64)
1208 CASTOP(f32, demote, f64)
1209 CASTOP(f64, convert_s, i32)
1210 CASTOP(f64, convert_u, i32)
1211 CASTOP(f64, convert_s, i64)
1212 CASTOP(f64, convert_u, i64)
1213 CASTOP(f64, promote, f32)
1214 CASTOP(i32, reinterpret, f32)
1215 CASTOP(i64, reinterpret, f64)
1216 CASTOP(f32, reinterpret, i32)
1217 CASTOP(f64, reinterpret, i64)
1218
1219#undef CASTOP
1220#undef UNOP
1221#undef BINOP
1222 default: SYS_VM_ASSERT(false, wasm_parse_exception, "Illegal instruction");
1223 }
1224 }
1225 SYS_VM_ASSERT( pc_stack.empty(), wasm_parse_exception, "function body too long" );
1226 _mod->maximum_stack = std::max(_mod->maximum_stack, static_cast<uint64_t>(op_stack.maximum_operand_depth) + local_types.locals_count());
1227 }
Here is the call graph for this function:

◆ parse_global_variable() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_global_variable ( wasm_code_ptr & code,
global_variable & gv )
inline

Definition at line 456 of file parser.hpp.

456 {
457 uint8_t ct = *code++;
458 gv.type.content_type = ct;
459 SYS_VM_ASSERT(ct == types::i32 || ct == types::i64 || ct == types::f32 || ct == types::f64,
460 wasm_parse_exception, "invalid global content type");
461
462 gv.type.mutability = parse_varuint1(code);
463 if(gv.type.mutability)
465 parse_init_expr(code, gv.init, ct);
466 gv.current = gv.init;
467 }
void on_mutable_global(uint8_t type)
Definition parser.hpp:1352
static uint8_t parse_varuint1(wasm_code_ptr &code)
Definition parser.hpp:209

◆ parse_global_variable() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_global_variable ( wasm_code_ptr & code,
global_variable & gv )
inline

Definition at line 456 of file parser.hpp.

456 {
457 uint8_t ct = *code++;
458 gv.type.content_type = ct;
459 SYS_VM_ASSERT(ct == types::i32 || ct == types::i64 || ct == types::f32 || ct == types::f64,
460 wasm_parse_exception, "invalid global content type");
461
462 gv.type.mutability = parse_varuint1(code);
463 if(gv.type.mutability)
465 parse_init_expr(code, gv.init, ct);
466 gv.current = gv.init;
467 }

◆ parse_import_entry() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_import_entry ( wasm_code_ptr & code,
import_entry & entry )
inline

Definition at line 419 of file parser.hpp.

419 {
420 entry.module_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
421 entry.field_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
422 entry.kind = (external_kind)(*code++);
423 auto type = parse_varuint32(code);
424 switch ((uint8_t)entry.kind) {
425 case external_kind::Function:
426 entry.type.func_t = type;
427 SYS_VM_ASSERT(type < _mod->types.size(), wasm_parse_exception, "Invalid function type");
428 break;
429 default: SYS_VM_ASSERT(false, wasm_unsupported_import_exception, "only function imports are supported");
430 }
431 }

◆ parse_import_entry() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_import_entry ( wasm_code_ptr & code,
import_entry & entry )
inline

Definition at line 419 of file parser.hpp.

419 {
420 entry.module_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
421 entry.field_str = parse_utf8_string(code, detail::get_max_symbol_bytes(_options));
422 entry.kind = (external_kind)(*code++);
423 auto type = parse_varuint32(code);
424 switch ((uint8_t)entry.kind) {
425 case external_kind::Function:
426 entry.type.func_t = type;
427 SYS_VM_ASSERT(type < _mod->types.size(), wasm_parse_exception, "Invalid function type");
428 break;
429 default: SYS_VM_ASSERT(false, wasm_unsupported_import_exception, "only function imports are supported");
430 }
431 }

◆ parse_init_expr() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_init_expr ( wasm_code_ptr & code,
init_expr & ie,
uint8_t type )
inline

Definition at line 548 of file parser.hpp.

548 {
549 ie.opcode = *code++;
550 switch (ie.opcode) {
551 case opcodes::i32_const:
552 ie.value.i32 = parse_varint32(code);
553 SYS_VM_ASSERT(type == types::i32, wasm_parse_exception, "expected i32 initializer");
554 break;
555 case opcodes::i64_const:
556 ie.value.i64 = parse_varint64(code);
557 SYS_VM_ASSERT(type == types::i64, wasm_parse_exception, "expected i64 initializer");
558 break;
559 case opcodes::f32_const:
560 ie.value.f32 = parse_raw<uint32_t>(code);
561 SYS_VM_ASSERT(type == types::f32, wasm_parse_exception, "expected f32 initializer");
562 break;
563 case opcodes::f64_const:
564 ie.value.f64 = parse_raw<uint64_t>(code);
565 SYS_VM_ASSERT(type == types::f64, wasm_parse_exception, "expected f64 initializer");
566 break;
567 default:
568 SYS_VM_ASSERT(false, wasm_parse_exception,
569 "initializer expression can only acception i32.const, i64.const, f32.const and f64.const");
570 }
571 SYS_VM_ASSERT((*code++) == opcodes::end, wasm_parse_exception, "no end op found");
572 }

◆ parse_init_expr() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_init_expr ( wasm_code_ptr & code,
init_expr & ie,
uint8_t type )
inline

Definition at line 548 of file parser.hpp.

548 {
549 ie.opcode = *code++;
550 switch (ie.opcode) {
551 case opcodes::i32_const:
552 ie.value.i32 = parse_varint32(code);
553 SYS_VM_ASSERT(type == types::i32, wasm_parse_exception, "expected i32 initializer");
554 break;
555 case opcodes::i64_const:
556 ie.value.i64 = parse_varint64(code);
557 SYS_VM_ASSERT(type == types::i64, wasm_parse_exception, "expected i64 initializer");
558 break;
559 case opcodes::f32_const:
560 ie.value.f32 = parse_raw<uint32_t>(code);
561 SYS_VM_ASSERT(type == types::f32, wasm_parse_exception, "expected f32 initializer");
562 break;
563 case opcodes::f64_const:
564 ie.value.f64 = parse_raw<uint64_t>(code);
565 SYS_VM_ASSERT(type == types::f64, wasm_parse_exception, "expected f64 initializer");
566 break;
567 default:
568 SYS_VM_ASSERT(false, wasm_parse_exception,
569 "initializer expression can only acception i32.const, i64.const, f32.const and f64.const");
570 }
571 SYS_VM_ASSERT((*code++) == opcodes::end, wasm_parse_exception, "no end op found");
572 }

◆ parse_magic() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_magic ( wasm_code_ptr & code)
inline

Definition at line 352 of file parser.hpp.

352 {
353 return parse_raw<uint32_t>(code);
354 }

◆ parse_magic() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_magic ( wasm_code_ptr & code)
inline

Definition at line 352 of file parser.hpp.

352 {
353 return parse_raw<uint32_t>(code);
354 }

◆ parse_memory_type() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_memory_type ( wasm_code_ptr & code,
memory_type & mt )
inline

Definition at line 469 of file parser.hpp.

469 {
470 mt.limits.flags = parse_flags(code);
471 mt.limits.initial = parse_varuint32(code);
472 // Implementation limits
473 SYS_VM_ASSERT(mt.limits.initial <= detail::get_max_pages(_options), wasm_parse_exception, "initial memory out of range");
474 // WASM specification
475 SYS_VM_ASSERT(mt.limits.initial <= 65536u, wasm_parse_exception, "initial memory out of range");
476 if (mt.limits.flags) {
477 mt.limits.maximum = parse_varuint32(code);
478 SYS_VM_ASSERT(mt.limits.maximum >= mt.limits.initial, wasm_parse_exception, "maximum must be at least minimum");
479 SYS_VM_ASSERT(mt.limits.maximum <= 65536u, wasm_parse_exception, "maximum memory out of range");
480 }
481 }
uint8_t parse_flags(wasm_code_ptr &code)
Definition parser.hpp:433

◆ parse_memory_type() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_memory_type ( wasm_code_ptr & code,
memory_type & mt )
inline

Definition at line 469 of file parser.hpp.

469 {
470 mt.limits.flags = parse_flags(code);
471 mt.limits.initial = parse_varuint32(code);
472 // Implementation limits
473 SYS_VM_ASSERT(mt.limits.initial <= detail::get_max_pages(_options), wasm_parse_exception, "initial memory out of range");
474 // WASM specification
475 SYS_VM_ASSERT(mt.limits.initial <= 65536u, wasm_parse_exception, "initial memory out of range");
476 if (mt.limits.flags) {
477 mt.limits.maximum = parse_varuint32(code);
478 SYS_VM_ASSERT(mt.limits.maximum >= mt.limits.initial, wasm_parse_exception, "maximum must be at least minimum");
479 SYS_VM_ASSERT(mt.limits.maximum <= 65536u, wasm_parse_exception, "maximum memory out of range");
480 }
481 }

◆ parse_module() [1/4]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
module & sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module ( wasm_code & code,
module & mod,
DebugInfo & debug )
inline

Definition at line 292 of file parser.hpp.

292 {
293 wasm_code_ptr cp(code.data(), code.size());
294 parse_module(cp, code.size(), mod, debug);
295 return mod;
296 }
module & parse_module(wasm_code &code, module &mod, DebugInfo &debug)
Definition parser.hpp:292
bool debug
Here is the caller graph for this function:

◆ parse_module() [2/4]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
module & sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module ( wasm_code & code,
module & mod,
DebugInfo & debug )
inline

Definition at line 292 of file parser.hpp.

292 {
293 wasm_code_ptr cp(code.data(), code.size());
294 parse_module(cp, code.size(), mod, debug);
295 return mod;
296 }

◆ parse_module() [3/4]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module ( wasm_code_ptr & code_ptr,
size_t sz,
module & mod,
DebugInfo & debug )
inline

Definition at line 303 of file parser.hpp.

303 {
304 _mod = &mod;
305 SYS_VM_ASSERT(parse_magic(code_ptr) == constants::magic, wasm_parse_exception, "magic number did not match");
306 SYS_VM_ASSERT(parse_version(code_ptr) == constants::version, wasm_parse_exception,
307 "version number did not match");
308 uint8_t highest_section_id = 0;
309 for (;;) {
310 if (code_ptr.offset() == sz)
311 break;
312 auto id = parse_section_id(code_ptr);
313 auto len = parse_section_payload_len(code_ptr);
314
315 SYS_VM_ASSERT(id == 0 || id > highest_section_id, wasm_parse_exception, "section out of order");
316 highest_section_id = std::max(highest_section_id, id);
317
318 auto section_guard = code_ptr.scoped_consume_items(len);
319
320 switch (id) {
321 case section_id::custom_section: parse_custom(code_ptr); break;
322 case section_id::type_section: parse_section<section_id::type_section>(code_ptr, mod.types); break;
323 case section_id::import_section: parse_section<section_id::import_section>(code_ptr, mod.imports); break;
324 case section_id::function_section:
325 parse_section<section_id::function_section>(code_ptr, mod.functions);
326 mod.normalize_types();
327 break;
328 case section_id::table_section: parse_section<section_id::table_section>(code_ptr, mod.tables); break;
329 case section_id::memory_section:
330 parse_section<section_id::memory_section>(code_ptr, mod.memories);
331 break;
332 case section_id::global_section: parse_section<section_id::global_section>(code_ptr, mod.globals); break;
333 case section_id::export_section:
334 parse_section<section_id::export_section>(code_ptr, mod.exports);
336 break;
337 case section_id::start_section: parse_section<section_id::start_section>(code_ptr, mod.start); break;
338 case section_id::element_section:
339 parse_section<section_id::element_section>(code_ptr, mod.elements);
340 break;
341 case section_id::code_section: parse_section<section_id::code_section>(code_ptr, mod.code); break;
342 case section_id::data_section: parse_section<section_id::data_section>(code_ptr, mod.data); break;
343 default: SYS_VM_ASSERT(false, wasm_parse_exception, "error invalid section id");
344 }
345 }
346 SYS_VM_ASSERT(_mod->code.size() == _mod->functions.size(), wasm_parse_exception, "code section must have the same size as the function section" );
347
348 debug.set(std::move(imap));
349 debug.relocate(_allocator.get_code_start());
350 }
uint32_t parse_magic(wasm_code_ptr &code)
Definition parser.hpp:352
uint32_t parse_version(wasm_code_ptr &code)
Definition parser.hpp:355
void parse_section(wasm_code_ptr &code, vec< typename std::enable_if_t< id==section_id::type_section, func_type > > &elems)
Definition parser.hpp:1252
void validate_exports() const
Definition parser.hpp:1356
void parse_custom(wasm_code_ptr &code)
Definition parser.hpp:363
uint32_t parse_section_payload_len(wasm_code_ptr &code)
Definition parser.hpp:359
uint8_t parse_section_id(wasm_code_ptr &code)
Definition parser.hpp:358
const void * get_code_start() const
guarded_vector< function_body > code
Definition types.hpp:177
Here is the call graph for this function:

◆ parse_module() [4/4]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module ( wasm_code_ptr & code_ptr,
size_t sz,
module & mod,
DebugInfo & debug )
inline

Definition at line 303 of file parser.hpp.

303 {
304 _mod = &mod;
305 SYS_VM_ASSERT(parse_magic(code_ptr) == constants::magic, wasm_parse_exception, "magic number did not match");
306 SYS_VM_ASSERT(parse_version(code_ptr) == constants::version, wasm_parse_exception,
307 "version number did not match");
308 uint8_t highest_section_id = 0;
309 for (;;) {
310 if (code_ptr.offset() == sz)
311 break;
312 auto id = parse_section_id(code_ptr);
313 auto len = parse_section_payload_len(code_ptr);
314
315 SYS_VM_ASSERT(id == 0 || id > highest_section_id, wasm_parse_exception, "section out of order");
316 highest_section_id = std::max(highest_section_id, id);
317
318 auto section_guard = code_ptr.scoped_consume_items(len);
319
320 switch (id) {
321 case section_id::custom_section: parse_custom(code_ptr); break;
322 case section_id::type_section: parse_section<section_id::type_section>(code_ptr, mod.types); break;
323 case section_id::import_section: parse_section<section_id::import_section>(code_ptr, mod.imports); break;
324 case section_id::function_section:
325 parse_section<section_id::function_section>(code_ptr, mod.functions);
326 mod.normalize_types();
327 break;
328 case section_id::table_section: parse_section<section_id::table_section>(code_ptr, mod.tables); break;
329 case section_id::memory_section:
330 parse_section<section_id::memory_section>(code_ptr, mod.memories);
331 break;
332 case section_id::global_section: parse_section<section_id::global_section>(code_ptr, mod.globals); break;
333 case section_id::export_section:
334 parse_section<section_id::export_section>(code_ptr, mod.exports);
336 break;
337 case section_id::start_section: parse_section<section_id::start_section>(code_ptr, mod.start); break;
338 case section_id::element_section:
339 parse_section<section_id::element_section>(code_ptr, mod.elements);
340 break;
341 case section_id::code_section: parse_section<section_id::code_section>(code_ptr, mod.code); break;
342 case section_id::data_section: parse_section<section_id::data_section>(code_ptr, mod.data); break;
343 default: SYS_VM_ASSERT(false, wasm_parse_exception, "error invalid section id");
344 }
345 }
346 SYS_VM_ASSERT(_mod->code.size() == _mod->functions.size(), wasm_parse_exception, "code section must have the same size as the function section" );
347
348 debug.set(std::move(imap));
349 debug.relocate(_allocator.get_code_start());
350 }
Here is the call graph for this function:

◆ parse_module2() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
module & sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module2 ( wasm_code_ptr & code_ptr,
size_t sz,
module & mod,
DebugInfo & debug )
inline

Definition at line 298 of file parser.hpp.

298 {
299 parse_module(code_ptr, sz, mod, debug);
300 return mod;
301 }

◆ parse_module2() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
module & sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_module2 ( wasm_code_ptr & code_ptr,
size_t sz,
module & mod,
DebugInfo & debug )
inline

Definition at line 298 of file parser.hpp.

298 {
299 parse_module(code_ptr, sz, mod, debug);
300 return mod;
301 }

◆ parse_name_map() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_name_map ( wasm_code_ptr & code,
guarded_vector< name_assoc > & map )
inline

Definition at line 374 of file parser.hpp.

374 {
375 for(uint32_t i = 0; i < map.size(); ++i) {
376 map[i].idx = parse_varuint32(code);
377 map[i].name = parse_utf8_string(code, 0xFFFFFFFFu);
378 }
379 }

◆ parse_name_map() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_name_map ( wasm_code_ptr & code,
guarded_vector< name_assoc > & map )
inline

Definition at line 374 of file parser.hpp.

374 {
375 for(uint32_t i = 0; i < map.size(); ++i) {
376 map[i].idx = parse_varuint32(code);
377 map[i].name = parse_utf8_string(code, 0xFFFFFFFFu);
378 }
379 }

◆ parse_name_section() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_name_section ( wasm_code_ptr & code)
inline

Definition at line 381 of file parser.hpp.

381 {
382 _mod->names = _allocator.alloc<name_section>(1);
383 new (_mod->names) name_section;
384 if(code.bounds() == code.offset()) return;
385 if(*code == 0) {
386 ++code;
387 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
388 _mod->names->module_name = _allocator.alloc<guarded_vector<uint8_t>>(1);
389 new (_mod->names->module_name) guarded_vector<uint8_t>(parse_utf8_string(code, 0xFFFFFFFFu));
390 }
391 if(code.bounds() == code.offset()) return;
392 if(*code == 1) {
393 ++code;
394 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
395 uint32_t size = parse_varuint32(code);
397 new (_mod->names->function_names) guarded_vector<name_assoc>(_allocator, size);
398 parse_name_map(code, *_mod->names->function_names);
399 }
400 if(code.bounds() == code.offset()) return;
401 if(*code == 2) {
402 ++code;
403 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
404 uint32_t size = parse_varuint32(code);
406 new (_mod->names->local_names) guarded_vector<indirect_name_assoc>(_allocator, size);
407 for(uint32_t i = 0; i < size; ++i) {
408 auto& [idx,namemap] = (*_mod->names->local_names)[i];
409 idx = parse_varuint32(code);
410 uint32_t local_size = parse_varuint32(code);
411 namemap = guarded_vector<name_assoc>(_allocator, local_size);
412 parse_name_map(code, namemap);
413 }
414 }
415 if(code.bounds() == code.offset()) return;
416 SYS_VM_ASSERT(false, wasm_parse_exception, "Invalid subsection Id");
417 }
void parse_name_map(wasm_code_ptr &code, guarded_vector< name_assoc > &map)
Definition parser.hpp:374
managed_vector< T, growable_allocator > guarded_vector
Definition types.hpp:29
name_section * names
Definition types.hpp:181
guarded_vector< indirect_name_assoc > * local_names
Definition types.hpp:163
guarded_vector< name_assoc > * function_names
Definition types.hpp:162
guarded_vector< uint8_t > * module_name
Definition types.hpp:161

◆ parse_name_section() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_name_section ( wasm_code_ptr & code)
inline

Definition at line 381 of file parser.hpp.

381 {
382 _mod->names = _allocator.alloc<name_section>(1);
383 new (_mod->names) name_section;
384 if(code.bounds() == code.offset()) return;
385 if(*code == 0) {
386 ++code;
387 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
388 _mod->names->module_name = _allocator.alloc<guarded_vector<uint8_t>>(1);
389 new (_mod->names->module_name) guarded_vector<uint8_t>(parse_utf8_string(code, 0xFFFFFFFFu));
390 }
391 if(code.bounds() == code.offset()) return;
392 if(*code == 1) {
393 ++code;
394 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
395 uint32_t size = parse_varuint32(code);
397 new (_mod->names->function_names) guarded_vector<name_assoc>(_allocator, size);
398 parse_name_map(code, *_mod->names->function_names);
399 }
400 if(code.bounds() == code.offset()) return;
401 if(*code == 2) {
402 ++code;
403 auto subsection_guard = code.scoped_consume_items(parse_varuint32(code));
404 uint32_t size = parse_varuint32(code);
406 new (_mod->names->local_names) guarded_vector<indirect_name_assoc>(_allocator, size);
407 for(uint32_t i = 0; i < size; ++i) {
408 auto& [idx,namemap] = (*_mod->names->local_names)[i];
409 idx = parse_varuint32(code);
410 uint32_t local_size = parse_varuint32(code);
411 namemap = guarded_vector<name_assoc>(_allocator, local_size);
412 parse_name_map(code, namemap);
413 }
414 }
415 if(code.bounds() == code.offset()) return;
416 SYS_VM_ASSERT(false, wasm_parse_exception, "Invalid subsection Id");
417 }

◆ parse_raw() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename T >
T sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_raw ( wasm_code_ptr & code)
inline

Definition at line 283 of file parser.hpp.

283 {
284 static_assert(std::is_arithmetic_v<T>, "Can only read builtin types");
285 auto guard = code.scoped_shrink_bounds(sizeof(T));
286 T result;
287 memcpy(&result, code.raw(), sizeof(T));
288 code += sizeof(T);
289 return result;
290 }
#define T(meth, val, expected)
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:

◆ parse_raw() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename T >
T sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_raw ( wasm_code_ptr & code)
inline

Definition at line 283 of file parser.hpp.

283 {
284 static_assert(std::is_arithmetic_v<T>, "Can only read builtin types");
285 auto guard = code.scoped_shrink_bounds(sizeof(T));
286 T result;
287 memcpy(&result, code.raw(), sizeof(T));
288 code += sizeof(T);
289 return result;
290 }
Here is the call graph for this function:

◆ parse_section() [1/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
typename std::enable_if_t< id==section_id::start_section, uint32_t > & start )
inline

Definition at line 1297 of file parser.hpp.

1298 {
1299 start = parse_varuint32(code);
1300 const func_type& ft = _mod->get_function_type(start);
1301 SYS_VM_ASSERT(ft.return_count == 0 && ft.param_types.size() == 0, wasm_parse_exception, "wrong type for start");
1302 }

◆ parse_section() [2/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
typename std::enable_if_t< id==section_id::start_section, uint32_t > & start )
inline

Definition at line 1297 of file parser.hpp.

1298 {
1299 start = parse_varuint32(code);
1300 const func_type& ft = _mod->get_function_type(start);
1301 SYS_VM_ASSERT(ft.return_count == 0 && ft.param_types.size() == 0, wasm_parse_exception, "wrong type for start");
1302 }

◆ parse_section() [3/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::code_section, function_body > > & elems )
inline

Definition at line 1311 of file parser.hpp.

1312 {
1313 const void* code_start = code.raw() - code.offset();
1314 parse_section_impl(code, elems, detail::get_max_function_section_elements(_options),
1315 [&](wasm_code_ptr& code, function_body& fb, std::size_t idx) { parse_function_body(code, fb, idx); });
1316 SYS_VM_ASSERT( elems.size() == _mod->functions.size(), wasm_parse_exception, "code section must have the same size as the function section" );
1317 Writer code_writer(_allocator, code.bounds() - code.offset(), *_mod);
1318 imap.on_code_start(code_writer.get_base_addr(), code_start);
1319 for (size_t i = 0; i < _function_bodies.size(); i++) {
1320 function_body& fb = _mod->code[i];
1321 func_type& ft = _mod->types.at(_mod->functions.at(i));
1322 local_types_t local_types(ft, fb.locals);
1323 imap.on_function_start(code_writer.get_addr(), _function_bodies[i].first.raw());
1324 code_writer.emit_prologue(ft, fb.locals, i);
1325 parse_function_body_code(_function_bodies[i].first, fb.size, _function_bodies[i].second, code_writer, ft, local_types);
1326 code_writer.emit_epilogue(ft, fb.locals, i);
1327 code_writer.finalize(fb);
1328 }
1329 imap.on_code_end(code_writer.get_addr(), code.raw());
1330 }
JSON writer.
Definition writer.h:89
void parse_function_body(wasm_code_ptr &code, function_body &fb, std::size_t idx)
Definition parser.hpp:574
void parse_function_body_code(wasm_code_ptr &code, size_t bounds, const detail::max_func_local_bytes_stack_checker< Options > &local_bytes_checker, Writer &code_writer, const func_type &ft, const local_types_t &local_types)
Definition parser.hpp:734
void parse_section_impl(wasm_code_ptr &code, vec< Elem > &elems, std::uint32_t max_elements, ParseFunc &&elem_parse)
Definition parser.hpp:1244

◆ parse_section() [4/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::code_section, function_body > > & elems )
inline

Definition at line 1311 of file parser.hpp.

1312 {
1313 const void* code_start = code.raw() - code.offset();
1314 parse_section_impl(code, elems, detail::get_max_function_section_elements(_options),
1315 [&](wasm_code_ptr& code, function_body& fb, std::size_t idx) { parse_function_body(code, fb, idx); });
1316 SYS_VM_ASSERT( elems.size() == _mod->functions.size(), wasm_parse_exception, "code section must have the same size as the function section" );
1317 Writer code_writer(_allocator, code.bounds() - code.offset(), *_mod);
1318 imap.on_code_start(code_writer.get_base_addr(), code_start);
1319 for (size_t i = 0; i < _function_bodies.size(); i++) {
1320 function_body& fb = _mod->code[i];
1321 func_type& ft = _mod->types.at(_mod->functions.at(i));
1322 local_types_t local_types(ft, fb.locals);
1323 imap.on_function_start(code_writer.get_addr(), _function_bodies[i].first.raw());
1324 code_writer.emit_prologue(ft, fb.locals, i);
1325 parse_function_body_code(_function_bodies[i].first, fb.size, _function_bodies[i].second, code_writer, ft, local_types);
1326 code_writer.emit_epilogue(ft, fb.locals, i);
1327 code_writer.finalize(fb);
1328 }
1329 imap.on_code_end(code_writer.get_addr(), code.raw());
1330 }

◆ parse_section() [5/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::data_section, data_segment > > & elems )
inline

Definition at line 1332 of file parser.hpp.

1333 {
1334 parse_section_impl(code, elems, detail::get_max_data_section_elements(_options),
1335 [&](wasm_code_ptr& code, data_segment& ds, std::size_t /*idx*/) { parse_data_segment(code, ds); });
1336 }
void parse_data_segment(wasm_code_ptr &code, data_segment &ds)
Definition parser.hpp:1229

◆ parse_section() [6/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::data_section, data_segment > > & elems )
inline

Definition at line 1332 of file parser.hpp.

1333 {
1334 parse_section_impl(code, elems, detail::get_max_data_section_elements(_options),
1335 [&](wasm_code_ptr& code, data_segment& ds, std::size_t /*idx*/) { parse_data_segment(code, ds); });
1336 }

◆ parse_section() [7/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::element_section, elem_segment > > & elems )
inline

Definition at line 1305 of file parser.hpp.

1306 {
1307 parse_section_impl(code, elems, detail::get_max_element_section_elements(_options),
1308 [&](wasm_code_ptr& code, elem_segment& es, std::size_t /*idx*/) { parse_elem_segment(code, es); });
1309 }
void parse_elem_segment(wasm_code_ptr &code, elem_segment &es)
Definition parser.hpp:521

◆ parse_section() [8/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::element_section, elem_segment > > & elems )
inline

Definition at line 1305 of file parser.hpp.

1306 {
1307 parse_section_impl(code, elems, detail::get_max_element_section_elements(_options),
1308 [&](wasm_code_ptr& code, elem_segment& es, std::size_t /*idx*/) { parse_elem_segment(code, es); });
1309 }

◆ parse_section() [9/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::export_section, export_entry > > & elems )
inline

Definition at line 1291 of file parser.hpp.

1292 {
1293 parse_section_impl(code, elems, detail::get_max_export_section_elements(_options),
1294 [&](wasm_code_ptr& code, export_entry& ee, std::size_t /*idx*/) { parse_export_entry(code, ee); });
1295 }
void parse_export_entry(wasm_code_ptr &code, export_entry &entry)
Definition parser.hpp:483

◆ parse_section() [10/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::export_section, export_entry > > & elems )
inline

Definition at line 1291 of file parser.hpp.

1292 {
1293 parse_section_impl(code, elems, detail::get_max_export_section_elements(_options),
1294 [&](wasm_code_ptr& code, export_entry& ee, std::size_t /*idx*/) { parse_export_entry(code, ee); });
1295 }

◆ parse_section() [11/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::function_section, uint32_t > > & elems )
inline

Definition at line 1264 of file parser.hpp.

1265 {
1266 parse_section_impl(code, elems, detail::get_max_function_section_elements(_options),
1267 [&](wasm_code_ptr& code, uint32_t& elem, std::size_t /*idx*/) { elem = parse_varuint32(code); });
1268 }

◆ parse_section() [12/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::function_section, uint32_t > > & elems )
inline

Definition at line 1264 of file parser.hpp.

1265 {
1266 parse_section_impl(code, elems, detail::get_max_function_section_elements(_options),
1267 [&](wasm_code_ptr& code, uint32_t& elem, std::size_t /*idx*/) { elem = parse_varuint32(code); });
1268 }

◆ parse_section() [13/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::global_section, global_variable > > & elems )
inline

Definition at line 1285 of file parser.hpp.

1286 {
1287 parse_section_impl(code, elems, detail::get_max_global_section_elements(_options),
1288 [&](wasm_code_ptr& code, global_variable& gv, std::size_t /*idx*/) { parse_global_variable(code, gv); });
1289 }
void parse_global_variable(wasm_code_ptr &code, global_variable &gv)
Definition parser.hpp:456

◆ parse_section() [14/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::global_section, global_variable > > & elems )
inline

Definition at line 1285 of file parser.hpp.

1286 {
1287 parse_section_impl(code, elems, detail::get_max_global_section_elements(_options),
1288 [&](wasm_code_ptr& code, global_variable& gv, std::size_t /*idx*/) { parse_global_variable(code, gv); });
1289 }

◆ parse_section() [15/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::import_section, import_entry > > & elems )
inline

Definition at line 1258 of file parser.hpp.

1259 {
1260 parse_section_impl(code, elems, detail::get_max_import_section_elements(_options),
1261 [&](wasm_code_ptr& code, import_entry& ie, std::size_t /*idx*/) { parse_import_entry(code, ie); });
1262 }
void parse_import_entry(wasm_code_ptr &code, import_entry &entry)
Definition parser.hpp:419

◆ parse_section() [16/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::import_section, import_entry > > & elems )
inline

Definition at line 1258 of file parser.hpp.

1259 {
1260 parse_section_impl(code, elems, detail::get_max_import_section_elements(_options),
1261 [&](wasm_code_ptr& code, import_entry& ie, std::size_t /*idx*/) { parse_import_entry(code, ie); });
1262 }

◆ parse_section() [17/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::memory_section, memory_type > > & elems )
inline

Definition at line 1276 of file parser.hpp.

1277 {
1278 parse_section_impl(code, elems, 1, [&](wasm_code_ptr& code, memory_type& mt, std::size_t idx) {
1279 SYS_VM_ASSERT(idx == 0, wasm_parse_exception, "only one memory is permitted");
1280 parse_memory_type(code, mt);
1281 });
1282 }
void parse_memory_type(wasm_code_ptr &code, memory_type &mt)
Definition parser.hpp:469

◆ parse_section() [18/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::memory_section, memory_type > > & elems )
inline

Definition at line 1276 of file parser.hpp.

1277 {
1278 parse_section_impl(code, elems, 1, [&](wasm_code_ptr& code, memory_type& mt, std::size_t idx) {
1279 SYS_VM_ASSERT(idx == 0, wasm_parse_exception, "only one memory is permitted");
1280 parse_memory_type(code, mt);
1281 });
1282 }

◆ parse_section() [19/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::table_section, table_type > > & elems )
inline

Definition at line 1270 of file parser.hpp.

1271 {
1272 parse_section_impl(code, elems, 1,
1273 [&](wasm_code_ptr& code, table_type& tt, std::size_t /*idx*/) { parse_table_type(code, tt); });
1274 }
void parse_table_type(wasm_code_ptr &code, table_type &tt)
Definition parser.hpp:442

◆ parse_section() [20/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::table_section, table_type > > & elems )
inline

Definition at line 1270 of file parser.hpp.

1271 {
1272 parse_section_impl(code, elems, 1,
1273 [&](wasm_code_ptr& code, table_type& tt, std::size_t /*idx*/) { parse_table_type(code, tt); });
1274 }

◆ parse_section() [21/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::type_section, func_type > > & elems )
inline

Definition at line 1252 of file parser.hpp.

1253 {
1254 parse_section_impl(code, elems, detail::get_max_type_section_elements(_options),
1255 [&](wasm_code_ptr& code, func_type& ft, std::size_t /*idx*/) { parse_func_type(code, ft); });
1256 }
void parse_func_type(wasm_code_ptr &code, func_type &ft)
Definition parser.hpp:500

◆ parse_section() [22/22]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<uint8_t id>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section ( wasm_code_ptr & code,
vec< typename std::enable_if_t< id==section_id::type_section, func_type > > & elems )
inline

Definition at line 1252 of file parser.hpp.

1253 {
1254 parse_section_impl(code, elems, detail::get_max_type_section_elements(_options),
1255 [&](wasm_code_ptr& code, func_type& ft, std::size_t /*idx*/) { parse_func_type(code, ft); });
1256 }

◆ parse_section_id() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_id ( wasm_code_ptr & code)
inline

Definition at line 358 of file parser.hpp.

358{ return *code++; }

◆ parse_section_id() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_id ( wasm_code_ptr & code)
inline

Definition at line 358 of file parser.hpp.

358{ return *code++; }

◆ parse_section_impl() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename Elem , typename ParseFunc >
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_impl ( wasm_code_ptr & code,
vec< Elem > & elems,
std::uint32_t max_elements,
ParseFunc && elem_parse )
inline

Definition at line 1244 of file parser.hpp.

1244 {
1245 auto count = parse_varuint32(code);
1246 SYS_VM_ASSERT(count <= max_elements, wasm_parse_exception, "number of section elements exceeded limit");
1247 elems = vec<Elem>{ _allocator, count };
1248 for (size_t i = 0; i < count; i++) { elem_parse(code, elems.at(i), i); }
1249 }
guarded_vector< T > vec
Definition parser.hpp:207
Here is the call graph for this function:

◆ parse_section_impl() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename Elem , typename ParseFunc >
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_impl ( wasm_code_ptr & code,
vec< Elem > & elems,
std::uint32_t max_elements,
ParseFunc && elem_parse )
inline

Definition at line 1244 of file parser.hpp.

1244 {
1245 auto count = parse_varuint32(code);
1246 SYS_VM_ASSERT(count <= max_elements, wasm_parse_exception, "number of section elements exceeded limit");
1247 elems = vec<Elem>{ _allocator, count };
1248 for (size_t i = 0; i < count; i++) { elem_parse(code, elems.at(i), i); }
1249 }
Here is the call graph for this function:

◆ parse_section_payload_len() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_payload_len ( wasm_code_ptr & code)
inline

Definition at line 359 of file parser.hpp.

359 {
360 return parse_varuint32(code);
361 }

◆ parse_section_payload_len() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_section_payload_len ( wasm_code_ptr & code)
inline

Definition at line 359 of file parser.hpp.

359 {
360 return parse_varuint32(code);
361 }

◆ parse_table_type() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_table_type ( wasm_code_ptr & code,
table_type & tt )
inline

Definition at line 442 of file parser.hpp.

442 {
443 tt.element_type = *code++;
444 SYS_VM_ASSERT(tt.element_type == types::anyfunc, wasm_parse_exception, "table must have type anyfunc");
445 tt.limits.flags = parse_flags(code);
446 tt.limits.initial = parse_varuint32(code);
447 if (tt.limits.flags) {
448 tt.limits.maximum = parse_varuint32(code);
449 SYS_VM_ASSERT(tt.limits.initial <= tt.limits.maximum, wasm_parse_exception, "table max size less than min size");
450 }
451 SYS_VM_ASSERT(tt.limits.initial <= detail::get_max_table_elements(_options), wasm_parse_exception, "table size exceeds limit");
452 tt.table = decltype(tt.table){ _allocator, tt.limits.initial };
453 for (uint32_t i = 0; i < tt.limits.initial; i++) tt.table[i] = std::numeric_limits<uint32_t>::max();
454 }

◆ parse_table_type() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_table_type ( wasm_code_ptr & code,
table_type & tt )
inline

Definition at line 442 of file parser.hpp.

442 {
443 tt.element_type = *code++;
444 SYS_VM_ASSERT(tt.element_type == types::anyfunc, wasm_parse_exception, "table must have type anyfunc");
445 tt.limits.flags = parse_flags(code);
446 tt.limits.initial = parse_varuint32(code);
447 if (tt.limits.flags) {
448 tt.limits.maximum = parse_varuint32(code);
449 SYS_VM_ASSERT(tt.limits.initial <= tt.limits.maximum, wasm_parse_exception, "table max size less than min size");
450 }
451 SYS_VM_ASSERT(tt.limits.initial <= detail::get_max_table_elements(_options), wasm_parse_exception, "table size exceeds limit");
452 tt.table = decltype(tt.table){ _allocator, tt.limits.initial };
453 for (uint32_t i = 0; i < tt.limits.initial; i++) tt.table[i] = std::numeric_limits<uint32_t>::max();
454 }

◆ parse_utf8_string() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
guarded_vector< uint8_t > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_utf8_string ( wasm_code_ptr & code,
std::uint32_t max_size )
inline

Definition at line 272 of file parser.hpp.

272 {
273 auto len = parse_varuint32(code);
274 SYS_VM_ASSERT(len <= max_size, wasm_parse_exception, "name too long");
275 auto guard = code.scoped_shrink_bounds(len);
276 auto result = guarded_vector<uint8_t>{ _allocator, len };
277 result.copy(code.raw(), len);
279 return result;
280 }
void validate_utf8_string(wasm_code_ptr &code, uint32_t bytes)
Definition parser.hpp:266
Here is the call graph for this function:

◆ parse_utf8_string() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
guarded_vector< uint8_t > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_utf8_string ( wasm_code_ptr & code,
std::uint32_t max_size )
inline

Definition at line 272 of file parser.hpp.

272 {
273 auto len = parse_varuint32(code);
274 SYS_VM_ASSERT(len <= max_size, wasm_parse_exception, "name too long");
275 auto guard = code.scoped_shrink_bounds(len);
276 auto result = guarded_vector<uint8_t>{ _allocator, len };
277 result.copy(code.raw(), len);
279 return result;
280 }
Here is the call graph for this function:

◆ parse_varint() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<size_t N>
varint< N > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint ( const wasm_code & code,
size_t index )
inline

Definition at line 1339 of file parser.hpp.

1339 {
1340 varint<N> result(0);
1341 result.set(code, index);
1342 return result;
1343 }

◆ parse_varint() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<size_t N>
varint< N > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint ( const wasm_code & code,
size_t index )
inline

Definition at line 1339 of file parser.hpp.

1339 {
1340 varint<N> result(0);
1341 result.set(code, index);
1342 return result;
1343 }

◆ parse_varint32() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint32 ( wasm_code_ptr & code)
inlinestatic

Definition at line 217 of file parser.hpp.

217{ return varint<32>(code).to(); }
Here is the call graph for this function:

◆ parse_varint32() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint32 ( wasm_code_ptr & code)
inlinestatic

Definition at line 217 of file parser.hpp.

217{ return varint<32>(code).to(); }
Here is the call graph for this function:

◆ parse_varint64() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int64_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint64 ( wasm_code_ptr & code)
inlinestatic

Definition at line 219 of file parser.hpp.

219{ return varint<64>(code).to(); }
Here is the call graph for this function:

◆ parse_varint64() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int64_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint64 ( wasm_code_ptr & code)
inlinestatic

Definition at line 219 of file parser.hpp.

219{ return varint<64>(code).to(); }
Here is the call graph for this function:

◆ parse_varint7() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint7 ( wasm_code_ptr & code)
inlinestatic

Definition at line 215 of file parser.hpp.

215{ return varint<7>(code).to(); }
Here is the call graph for this function:

◆ parse_varint7() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static int8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varint7 ( wasm_code_ptr & code)
inlinestatic

Definition at line 215 of file parser.hpp.

215{ return varint<7>(code).to(); }
Here is the call graph for this function:

◆ parse_varuint() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<size_t N>
varuint< N > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint ( const wasm_code & code,
size_t index )
inline

Definition at line 1346 of file parser.hpp.

1346 {
1347 varuint<N> result(0);
1348 result.set(code, index);
1349 return result;
1350 }

◆ parse_varuint() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<size_t N>
varuint< N > sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint ( const wasm_code & code,
size_t index )
inline

Definition at line 1346 of file parser.hpp.

1346 {
1347 varuint<N> result(0);
1348 result.set(code, index);
1349 return result;
1350 }

◆ parse_varuint1() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint1 ( wasm_code_ptr & code)
inlinestatic

Definition at line 209 of file parser.hpp.

209{ return varuint<1>(code).to(); }
Here is the call graph for this function:

◆ parse_varuint1() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint1 ( wasm_code_ptr & code)
inlinestatic

Definition at line 209 of file parser.hpp.

209{ return varuint<1>(code).to(); }
Here is the call graph for this function:

◆ parse_varuint32() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint32 ( wasm_code_ptr & code)
inlinestatic

Definition at line 213 of file parser.hpp.

213{ return varuint<32>(code).to(); }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_varuint32() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint32 ( wasm_code_ptr & code)
inlinestatic

Definition at line 213 of file parser.hpp.

213{ return varuint<32>(code).to(); }
Here is the call graph for this function:

◆ parse_varuint7() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint7 ( wasm_code_ptr & code)
inlinestatic

Definition at line 211 of file parser.hpp.

211{ return varuint<7>(code).to(); }
Here is the call graph for this function:

◆ parse_varuint7() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_varuint7 ( wasm_code_ptr & code)
inlinestatic

Definition at line 211 of file parser.hpp.

211{ return varuint<7>(code).to(); }
Here is the call graph for this function:

◆ parse_version() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_version ( wasm_code_ptr & code)
inline

Definition at line 355 of file parser.hpp.

355 {
356 return parse_raw<uint32_t>(code);
357 }

◆ parse_version() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
uint32_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::parse_version ( wasm_code_ptr & code)
inline

Definition at line 355 of file parser.hpp.

355 {
356 return parse_raw<uint32_t>(code);
357 }

◆ validate_exports() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_exports ( ) const
inline

Definition at line 1356 of file parser.hpp.

1356 {
1357 std::vector<const guarded_vector<uint8_t>*> export_names;
1358 export_names.reserve(_mod->exports.size());
1359 for (uint32_t i = 0; i < _mod->exports.size(); ++i) {
1360 export_names.push_back(&_mod->exports[i].field_str);
1361 }
1362 std::sort(export_names.begin(), export_names.end(), [](auto* lhs, auto* rhs) {
1363 return std::lexicographical_compare(lhs->raw(), lhs->raw() + lhs->size(), rhs->raw(), rhs->raw() + rhs->size());
1364 });
1365 auto it = std::adjacent_find(export_names.begin(), export_names.end(), [](auto* lhs, auto* rhs) {
1366 return lhs->size() == rhs->size() && std::equal(lhs->raw(), lhs->raw() + lhs->size(), rhs->raw());
1367 });
1368 SYS_VM_ASSERT(it == export_names.end(), wasm_parse_exception, "duplicate export name");
1369 }
guarded_vector< export_entry > exports
Definition types.hpp:175

◆ validate_exports() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_exports ( ) const
inline

Definition at line 1356 of file parser.hpp.

1356 {
1357 std::vector<const guarded_vector<uint8_t>*> export_names;
1358 export_names.reserve(_mod->exports.size());
1359 for (uint32_t i = 0; i < _mod->exports.size(); ++i) {
1360 export_names.push_back(&_mod->exports[i].field_str);
1361 }
1362 std::sort(export_names.begin(), export_names.end(), [](auto* lhs, auto* rhs) {
1363 return std::lexicographical_compare(lhs->raw(), lhs->raw() + lhs->size(), rhs->raw(), rhs->raw() + rhs->size());
1364 });
1365 auto it = std::adjacent_find(export_names.begin(), export_names.end(), [](auto* lhs, auto* rhs) {
1366 return lhs->size() == rhs->size() && std::equal(lhs->raw(), lhs->raw() + lhs->size(), rhs->raw());
1367 });
1368 SYS_VM_ASSERT(it == export_names.end(), wasm_parse_exception, "duplicate export name");
1369 }

◆ validate_utf8_code_point() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
int sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_utf8_code_point ( wasm_code_ptr & code)
inline

Definition at line 221 of file parser.hpp.

221 {
222 unsigned char ch = *code++;
223 if (ch < 0x80) {
224 return 1;
225 } else if(ch < 0xE0) {
226 SYS_VM_ASSERT((ch & 0xC0) == 0xC0, wasm_parse_exception, "invalid utf8 encoding");
227 unsigned char b2 = *code++;
228 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
229 uint32_t code_point =
230 (static_cast<uint32_t>(ch - 0xC0u) << 6u) +
231 (static_cast<uint32_t>(b2 - 0x80u));
232 SYS_VM_ASSERT(0x80 <= code_point && code_point < 0x800, wasm_parse_exception, "invalid utf8 encoding");
233 return 2;
234 } else if(ch < 0xF0) {
235 unsigned char b2 = *code++;
236 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
237 unsigned char b3 = *code++;
238 SYS_VM_ASSERT((b3 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
239 uint32_t code_point =
240 (static_cast<uint32_t>(ch - 0xE0u) << 12u) +
241 (static_cast<uint32_t>(b2 - 0x80u) << 6u) +
242 (static_cast<uint32_t>(b3 - 0x80u));
243 SYS_VM_ASSERT((0x800 <= code_point && code_point < 0xD800) ||
244 (0xE000 <= code_point && code_point < 0x10000),
245 wasm_parse_exception, "invalid utf8 encoding");
246 return 3;
247 } else if (ch < 0xF8) {
248 unsigned char b2 = *code++;
249 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
250 unsigned char b3 = *code++;
251 SYS_VM_ASSERT((b3 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
252 unsigned char b4 = *code++;
253 SYS_VM_ASSERT((b4 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
254 uint32_t code_point =
255 (static_cast<uint32_t>(ch - 0xF0u) << 18u) +
256 (static_cast<uint32_t>(b2 - 0x80u) << 12u) +
257 (static_cast<uint32_t>(b3 - 0x80u) << 6u) +
258 (static_cast<uint32_t>(b4 - 0x80u));
259 SYS_VM_ASSERT((0x10000 <= code_point && code_point < 0x110000),
260 wasm_parse_exception, "invalid utf8 encoding");
261 return 4;
262 }
263 SYS_VM_ASSERT(false, wasm_parse_exception, "invalid utf8 encoding");
264 }
static const Reg8 ch(Operand::CH)
Here is the caller graph for this function:

◆ validate_utf8_code_point() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
int sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_utf8_code_point ( wasm_code_ptr & code)
inline

Definition at line 221 of file parser.hpp.

221 {
222 unsigned char ch = *code++;
223 if (ch < 0x80) {
224 return 1;
225 } else if(ch < 0xE0) {
226 SYS_VM_ASSERT((ch & 0xC0) == 0xC0, wasm_parse_exception, "invalid utf8 encoding");
227 unsigned char b2 = *code++;
228 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
229 uint32_t code_point =
230 (static_cast<uint32_t>(ch - 0xC0u) << 6u) +
231 (static_cast<uint32_t>(b2 - 0x80u));
232 SYS_VM_ASSERT(0x80 <= code_point && code_point < 0x800, wasm_parse_exception, "invalid utf8 encoding");
233 return 2;
234 } else if(ch < 0xF0) {
235 unsigned char b2 = *code++;
236 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
237 unsigned char b3 = *code++;
238 SYS_VM_ASSERT((b3 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
239 uint32_t code_point =
240 (static_cast<uint32_t>(ch - 0xE0u) << 12u) +
241 (static_cast<uint32_t>(b2 - 0x80u) << 6u) +
242 (static_cast<uint32_t>(b3 - 0x80u));
243 SYS_VM_ASSERT((0x800 <= code_point && code_point < 0xD800) ||
244 (0xE000 <= code_point && code_point < 0x10000),
245 wasm_parse_exception, "invalid utf8 encoding");
246 return 3;
247 } else if (ch < 0xF8) {
248 unsigned char b2 = *code++;
249 SYS_VM_ASSERT((b2 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
250 unsigned char b3 = *code++;
251 SYS_VM_ASSERT((b3 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
252 unsigned char b4 = *code++;
253 SYS_VM_ASSERT((b4 & 0xC0) == 0x80, wasm_parse_exception, "invalid utf8 encoding");
254 uint32_t code_point =
255 (static_cast<uint32_t>(ch - 0xF0u) << 18u) +
256 (static_cast<uint32_t>(b2 - 0x80u) << 12u) +
257 (static_cast<uint32_t>(b3 - 0x80u) << 6u) +
258 (static_cast<uint32_t>(b4 - 0x80u));
259 SYS_VM_ASSERT((0x10000 <= code_point && code_point < 0x110000),
260 wasm_parse_exception, "invalid utf8 encoding");
261 return 4;
262 }
263 SYS_VM_ASSERT(false, wasm_parse_exception, "invalid utf8 encoding");
264 }

◆ validate_utf8_string() [1/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_utf8_string ( wasm_code_ptr & code,
uint32_t bytes )
inline

Definition at line 266 of file parser.hpp.

266 {
267 while(bytes != 0) {
269 }
270 }
int validate_utf8_code_point(wasm_code_ptr &code)
Definition parser.hpp:221
vector< char > bytes
Definition types.hpp:243
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_utf8_string() [2/2]

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
void sysio::vm::binary_parser< Writer, Options, DebugInfo >::validate_utf8_string ( wasm_code_ptr & code,
uint32_t bytes )
inline

Definition at line 266 of file parser.hpp.

266 {
267 while(bytes != 0) {
269 }
270 }
Here is the call graph for this function:

◆ vec()

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
template<typename T >
typedef guarded_vector<T> sysio::vm::binary_parser< Writer, Options, DebugInfo >::vec

Definition at line 207 of file parser.hpp.

Member Data Documentation

◆ any_type

template<typename Writer , typename Options = default_options, typename DebugInfo = null_debug_info>
static constexpr uint8_t sysio::vm::binary_parser< Writer, Options, DebugInfo >::any_type = 0x82
staticconstexpr

Definition at line 623 of file parser.hpp.


The documentation for this class was generated from the following files: