mirror of
git://jb55.com/damus
synced 2024-10-06 19:53:22 +00:00
a04a401292
This allows you to open and run scripts for testing purposes, but only from external links such as nostr:nscript...
851 lines
16 KiB
C
851 lines
16 KiB
C
|
|
#ifndef PROTOVERSE_WASM_H
|
|
#define PROTOVERSE_WASM_H
|
|
|
|
static const unsigned char WASM_MAGIC[] = {0,'a','s','m'};
|
|
|
|
#define WASM_VERSION 0x01
|
|
#define MAX_U32_LEB128_BYTES 5
|
|
#define MAX_U64_LEB128_BYTES 10
|
|
#define MAX_CUSTOM_SECTIONS 32
|
|
#define MAX_BUILTINS 64
|
|
#define BUILTIN_SUSPEND 42
|
|
|
|
#define FUNC_TYPE_TAG 0x60
|
|
|
|
|
|
#include "cursor.h"
|
|
#include "error.h"
|
|
|
|
#ifdef NOINLINE
|
|
#define INLINE __attribute__((noinline))
|
|
#else
|
|
#define INLINE inline
|
|
#endif
|
|
|
|
|
|
#define interp_error(p, fmt, ...) note_error(&((p)->errors), interp_codeptr(p), fmt, ##__VA_ARGS__)
|
|
#define parse_err(p, fmt, ...) note_error(&((p)->errs), &(p)->cur, fmt, ##__VA_ARGS__)
|
|
|
|
enum valtype {
|
|
val_i32 = 0x7F,
|
|
val_i64 = 0x7E,
|
|
val_f32 = 0x7D,
|
|
val_f64 = 0x7C,
|
|
val_ref_null = 0xD0,
|
|
val_ref_func = 0x70,
|
|
val_ref_extern = 0x6F,
|
|
};
|
|
|
|
enum const_instr {
|
|
ci_const_i32 = 0x41,
|
|
ci_const_i64 = 0x42,
|
|
ci_const_f32 = 0x43,
|
|
ci_const_f64 = 0x44,
|
|
ci_ref_null = 0xD0,
|
|
ci_ref_func = 0xD2,
|
|
ci_global_get = 0x23,
|
|
ci_end = 0x0B,
|
|
};
|
|
|
|
enum limit_type {
|
|
limit_min = 0x00,
|
|
limit_min_max = 0x01,
|
|
};
|
|
|
|
struct limits {
|
|
u32 min;
|
|
u32 max;
|
|
enum limit_type type;
|
|
};
|
|
|
|
enum section_tag {
|
|
section_custom,
|
|
section_type,
|
|
section_import,
|
|
section_function,
|
|
section_table,
|
|
section_memory,
|
|
section_global,
|
|
section_export,
|
|
section_start,
|
|
section_element,
|
|
section_code,
|
|
section_data,
|
|
section_data_count,
|
|
section_name,
|
|
num_sections,
|
|
};
|
|
|
|
enum name_subsection_tag {
|
|
name_subsection_module,
|
|
name_subsection_funcs,
|
|
name_subsection_locals,
|
|
num_name_subsections,
|
|
};
|
|
|
|
enum reftype {
|
|
funcref = 0x70,
|
|
externref = 0x6F,
|
|
};
|
|
|
|
struct resulttype {
|
|
unsigned char *valtypes; /* enum valtype */
|
|
u32 num_valtypes;
|
|
};
|
|
|
|
struct functype {
|
|
struct resulttype params;
|
|
struct resulttype result;
|
|
};
|
|
|
|
struct table {
|
|
enum reftype reftype;
|
|
struct limits limits;
|
|
};
|
|
|
|
struct tablesec {
|
|
struct table *tables;
|
|
u32 num_tables;
|
|
};
|
|
|
|
enum elem_mode {
|
|
elem_mode_passive,
|
|
elem_mode_active,
|
|
elem_mode_declarative,
|
|
};
|
|
|
|
struct expr {
|
|
u8 *code;
|
|
u32 code_len;
|
|
};
|
|
|
|
struct refval {
|
|
u32 addr;
|
|
};
|
|
|
|
struct table_inst {
|
|
struct refval *refs;
|
|
enum reftype reftype;
|
|
u32 num_refs;
|
|
};
|
|
|
|
struct numval {
|
|
union {
|
|
int i32;
|
|
u32 u32;
|
|
int64_t i64;
|
|
uint64_t u64;
|
|
float f32;
|
|
double f64;
|
|
};
|
|
};
|
|
|
|
struct val {
|
|
enum valtype type;
|
|
union {
|
|
struct numval num;
|
|
struct refval ref;
|
|
};
|
|
};
|
|
|
|
struct elem_inst {
|
|
struct val val;
|
|
u16 elem;
|
|
u16 init;
|
|
};
|
|
|
|
struct elem {
|
|
struct expr offset;
|
|
u32 tableidx;
|
|
struct expr *inits;
|
|
u32 num_inits;
|
|
enum elem_mode mode;
|
|
enum reftype reftype;
|
|
struct val val;
|
|
};
|
|
|
|
struct customsec {
|
|
const char *name;
|
|
unsigned char *data;
|
|
u32 data_len;
|
|
};
|
|
|
|
struct elemsec {
|
|
struct elem *elements;
|
|
u32 num_elements;
|
|
};
|
|
|
|
struct memsec {
|
|
struct limits *mems; /* memtype */
|
|
u32 num_mems;
|
|
};
|
|
|
|
struct funcsec {
|
|
u32 *type_indices;
|
|
u32 num_indices;
|
|
};
|
|
|
|
enum mut {
|
|
mut_const,
|
|
mut_var,
|
|
};
|
|
|
|
struct globaltype {
|
|
enum valtype valtype;
|
|
enum mut mut;
|
|
};
|
|
|
|
struct globalsec {
|
|
struct global *globals;
|
|
u32 num_globals;
|
|
};
|
|
|
|
struct typesec {
|
|
struct functype *functypes;
|
|
u32 num_functypes;
|
|
};
|
|
|
|
enum import_type {
|
|
import_func,
|
|
import_table,
|
|
import_mem,
|
|
import_global,
|
|
};
|
|
|
|
struct importdesc {
|
|
enum import_type type;
|
|
union {
|
|
u32 typeidx;
|
|
struct limits tabletype;
|
|
struct limits memtype;
|
|
struct globaltype globaltype;
|
|
};
|
|
};
|
|
|
|
struct import {
|
|
const char *module_name;
|
|
const char *name;
|
|
struct importdesc desc;
|
|
int resolved_builtin;
|
|
};
|
|
|
|
struct importsec {
|
|
struct import *imports;
|
|
u32 num_imports;
|
|
};
|
|
|
|
struct global {
|
|
struct globaltype type;
|
|
struct expr init;
|
|
struct val val;
|
|
};
|
|
|
|
struct local_def {
|
|
u32 num_types;
|
|
enum valtype type;
|
|
};
|
|
|
|
/* "code" */
|
|
struct wasm_func {
|
|
struct expr code;
|
|
struct local_def *local_defs;
|
|
u32 num_local_defs;
|
|
};
|
|
|
|
enum func_type {
|
|
func_type_wasm,
|
|
func_type_builtin,
|
|
};
|
|
|
|
struct func {
|
|
union {
|
|
struct wasm_func *wasm_func;
|
|
struct builtin *builtin;
|
|
};
|
|
u32 num_locals;
|
|
struct functype *functype;
|
|
enum func_type type;
|
|
const char *name;
|
|
u32 idx;
|
|
};
|
|
|
|
struct codesec {
|
|
struct wasm_func *funcs;
|
|
u32 num_funcs;
|
|
};
|
|
|
|
enum exportdesc {
|
|
export_func,
|
|
export_table,
|
|
export_mem,
|
|
export_global,
|
|
};
|
|
|
|
struct wexport {
|
|
const char *name;
|
|
u32 index;
|
|
enum exportdesc desc;
|
|
};
|
|
|
|
struct exportsec {
|
|
struct wexport *exports;
|
|
u32 num_exports;
|
|
};
|
|
|
|
struct nameassoc {
|
|
u32 index;
|
|
const char *name;
|
|
};
|
|
|
|
struct namemap {
|
|
struct nameassoc *names;
|
|
u32 num_names;
|
|
};
|
|
|
|
struct namesec {
|
|
const char *module_name;
|
|
struct namemap func_names;
|
|
int parsed;
|
|
};
|
|
|
|
struct wsection {
|
|
enum section_tag tag;
|
|
};
|
|
|
|
enum bulk_tag {
|
|
i_memory_copy = 10,
|
|
i_memory_fill = 11,
|
|
i_table_init = 12,
|
|
i_elem_drop = 13,
|
|
i_table_copy = 14,
|
|
i_table_grow = 15,
|
|
i_table_size = 16,
|
|
i_table_fill = 17,
|
|
};
|
|
|
|
enum instr_tag {
|
|
/* control instructions */
|
|
i_unreachable = 0x00,
|
|
i_nop = 0x01,
|
|
i_block = 0x02,
|
|
i_loop = 0x03,
|
|
i_if = 0x04,
|
|
i_else = 0x05,
|
|
i_end = 0x0B,
|
|
i_br = 0x0C,
|
|
i_br_if = 0x0D,
|
|
i_br_table = 0x0E,
|
|
i_return = 0x0F,
|
|
i_call = 0x10,
|
|
i_call_indirect = 0x11,
|
|
|
|
/* parametric instructions */
|
|
i_drop = 0x1A,
|
|
i_select = 0x1B,
|
|
i_selects = 0x1C,
|
|
|
|
/* variable instructions */
|
|
i_local_get = 0x20,
|
|
i_local_set = 0x21,
|
|
i_local_tee = 0x22,
|
|
i_global_get = 0x23,
|
|
i_global_set = 0x24,
|
|
i_table_get = 0x25,
|
|
i_table_set = 0x26,
|
|
|
|
/* memory instructions */
|
|
i_i32_load = 0x28,
|
|
i_i64_load = 0x29,
|
|
i_f32_load = 0x2A,
|
|
i_f64_load = 0x2B,
|
|
i_i32_load8_s = 0x2C,
|
|
i_i32_load8_u = 0x2D,
|
|
i_i32_load16_s = 0x2E,
|
|
i_i32_load16_u = 0x2F,
|
|
i_i64_load8_s = 0x30,
|
|
i_i64_load8_u = 0x31,
|
|
i_i64_load16_s = 0x32,
|
|
i_i64_load16_u = 0x33,
|
|
i_i64_load32_s = 0x34,
|
|
i_i64_load32_u = 0x35,
|
|
i_i32_store = 0x36,
|
|
i_i64_store = 0x37,
|
|
i_f32_store = 0x38,
|
|
i_f64_store = 0x39,
|
|
i_i32_store8 = 0x3A,
|
|
i_i32_store16 = 0x3B,
|
|
i_i64_store8 = 0x3C,
|
|
i_i64_store16 = 0x3D,
|
|
i_i64_store32 = 0x3E,
|
|
i_memory_size = 0x3F,
|
|
i_memory_grow = 0x40,
|
|
|
|
/* numeric instructions */
|
|
i_i32_const = 0x41,
|
|
i_i64_const = 0x42,
|
|
i_f32_const = 0x43,
|
|
i_f64_const = 0x44,
|
|
|
|
i_i32_eqz = 0x45,
|
|
i_i32_eq = 0x46,
|
|
i_i32_ne = 0x47,
|
|
i_i32_lt_s = 0x48,
|
|
i_i32_lt_u = 0x49,
|
|
i_i32_gt_s = 0x4A,
|
|
i_i32_gt_u = 0x4B,
|
|
i_i32_le_s = 0x4C,
|
|
i_i32_le_u = 0x4D,
|
|
i_i32_ge_s = 0x4E,
|
|
i_i32_ge_u = 0x4F,
|
|
|
|
i_i64_eqz = 0x50,
|
|
i_i64_eq = 0x51,
|
|
i_i64_ne = 0x52,
|
|
i_i64_lt_s = 0x53,
|
|
i_i64_lt_u = 0x54,
|
|
i_i64_gt_s = 0x55,
|
|
i_i64_gt_u = 0x56,
|
|
i_i64_le_s = 0x57,
|
|
i_i64_le_u = 0x58,
|
|
i_i64_ge_s = 0x59,
|
|
i_i64_ge_u = 0x5A,
|
|
|
|
i_f32_eq = 0x5B,
|
|
i_f32_ne = 0x5C,
|
|
i_f32_lt = 0x5D,
|
|
i_f32_gt = 0x5E,
|
|
i_f32_le = 0x5F,
|
|
i_f32_ge = 0x60,
|
|
|
|
i_f64_eq = 0x61,
|
|
i_f64_ne = 0x62,
|
|
i_f64_lt = 0x63,
|
|
i_f64_gt = 0x64,
|
|
i_f64_le = 0x65,
|
|
i_f64_ge = 0x66,
|
|
|
|
i_i32_clz = 0x67,
|
|
i_i32_ctz = 0x68,
|
|
i_i32_popcnt = 0x69,
|
|
|
|
i_i32_add = 0x6A,
|
|
i_i32_sub = 0x6B,
|
|
i_i32_mul = 0x6C,
|
|
i_i32_div_s = 0x6D,
|
|
i_i32_div_u = 0x6E,
|
|
i_i32_rem_s = 0x6F,
|
|
i_i32_rem_u = 0x70,
|
|
i_i32_and = 0x71,
|
|
i_i32_or = 0x72,
|
|
i_i32_xor = 0x73,
|
|
i_i32_shl = 0x74,
|
|
i_i32_shr_s = 0x75,
|
|
i_i32_shr_u = 0x76,
|
|
i_i32_rotl = 0x77,
|
|
i_i32_rotr = 0x78,
|
|
|
|
i_i64_clz = 0x79,
|
|
i_i64_ctz = 0x7A,
|
|
i_i64_popcnt = 0x7B,
|
|
i_i64_add = 0x7C,
|
|
i_i64_sub = 0x7D,
|
|
i_i64_mul = 0x7E,
|
|
i_i64_div_s = 0x7F,
|
|
i_i64_div_u = 0x80,
|
|
i_i64_rem_s = 0x81,
|
|
i_i64_rem_u = 0x82,
|
|
i_i64_and = 0x83,
|
|
i_i64_or = 0x84,
|
|
i_i64_xor = 0x85,
|
|
i_i64_shl = 0x86,
|
|
i_i64_shr_s = 0x87,
|
|
i_i64_shr_u = 0x88,
|
|
i_i64_rotl = 0x89,
|
|
i_i64_rotr = 0x8A,
|
|
|
|
i_f32_abs = 0x8b,
|
|
i_f32_neg = 0x8c,
|
|
i_f32_ceil = 0x8d,
|
|
i_f32_floor = 0x8e,
|
|
i_f32_trunc = 0x8f,
|
|
i_f32_nearest = 0x90,
|
|
i_f32_sqrt = 0x91,
|
|
i_f32_add = 0x92,
|
|
i_f32_sub = 0x93,
|
|
i_f32_mul = 0x94,
|
|
i_f32_div = 0x95,
|
|
i_f32_min = 0x96,
|
|
i_f32_max = 0x97,
|
|
i_f32_copysign = 0x98,
|
|
|
|
i_f64_abs = 0x99,
|
|
i_f64_neg = 0x9a,
|
|
i_f64_ceil = 0x9b,
|
|
i_f64_floor = 0x9c,
|
|
i_f64_trunc = 0x9d,
|
|
i_f64_nearest = 0x9e,
|
|
i_f64_sqrt = 0x9f,
|
|
i_f64_add = 0xa0,
|
|
i_f64_sub = 0xa1,
|
|
i_f64_mul = 0xa2,
|
|
i_f64_div = 0xa3,
|
|
i_f64_min = 0xa4,
|
|
i_f64_max = 0xa5,
|
|
i_f64_copysign = 0xa6,
|
|
|
|
i_i32_wrap_i64 = 0xa7,
|
|
i_i32_trunc_f32_s = 0xa8,
|
|
i_i32_trunc_f32_u = 0xa9,
|
|
i_i32_trunc_f64_s = 0xaa,
|
|
i_i32_trunc_f64_u = 0xab,
|
|
i_i64_extend_i32_s = 0xac,
|
|
i_i64_extend_i32_u = 0xad,
|
|
i_i64_trunc_f32_s = 0xae,
|
|
i_i64_trunc_f32_u = 0xaf,
|
|
i_i64_trunc_f64_s = 0xb0,
|
|
i_i64_trunc_f64_u = 0xb1,
|
|
i_f32_convert_i32_s = 0xb2,
|
|
i_f32_convert_i32_u = 0xb3,
|
|
i_f32_convert_i64_s = 0xb4,
|
|
i_f32_convert_i64_u = 0xb5,
|
|
i_f32_demote_f64 = 0xb6,
|
|
i_f64_convert_i32_s = 0xb7,
|
|
i_f64_convert_i32_u = 0xb8,
|
|
i_f64_convert_i64_s = 0xb9,
|
|
i_f64_convert_i64_u = 0xba,
|
|
i_f64_promote_f32 = 0xbb,
|
|
|
|
i_i32_reinterpret_f32 = 0xbc,
|
|
i_i64_reinterpret_f64 = 0xbd,
|
|
i_f32_reinterpret_i32 = 0xbe,
|
|
i_f64_reinterpret_i64 = 0xbf,
|
|
|
|
i_i32_extend8_s = 0xc0,
|
|
i_i32_extend16_s = 0xc1,
|
|
i_i64_extend8_s = 0xc2,
|
|
i_i64_extend16_s = 0xc3,
|
|
i_i64_extend32_s = 0xc4,
|
|
|
|
i_ref_null = 0xD0,
|
|
i_ref_is_null = 0xD1,
|
|
i_ref_func = 0xD2,
|
|
|
|
i_bulk_op = 0xFC,
|
|
/* TODO: more instrs */
|
|
|
|
};
|
|
|
|
enum blocktype_tag {
|
|
blocktype_empty,
|
|
blocktype_valtype,
|
|
blocktype_index,
|
|
};
|
|
|
|
struct blocktype {
|
|
enum blocktype_tag tag;
|
|
union {
|
|
enum valtype valtype;
|
|
int type_index;
|
|
};
|
|
};
|
|
|
|
struct instrs {
|
|
unsigned char *data;
|
|
u32 len;
|
|
};
|
|
|
|
struct block {
|
|
struct blocktype type;
|
|
struct expr instrs;
|
|
};
|
|
|
|
struct memarg {
|
|
u32 offset;
|
|
u32 align;
|
|
};
|
|
|
|
struct br_table {
|
|
u32 num_label_indices;
|
|
u32 label_indices[512];
|
|
u32 default_label;
|
|
};
|
|
|
|
struct call_indirect {
|
|
u32 tableidx;
|
|
u32 typeidx;
|
|
};
|
|
|
|
struct table_init {
|
|
u32 tableidx;
|
|
u32 elemidx;
|
|
};
|
|
|
|
struct table_copy {
|
|
u32 from;
|
|
u32 to;
|
|
};
|
|
|
|
struct bulk_op {
|
|
enum bulk_tag tag;
|
|
union {
|
|
struct table_init table_init;
|
|
struct table_copy table_copy;
|
|
u32 idx;
|
|
};
|
|
};
|
|
|
|
struct select_instr {
|
|
u8 *valtypes;
|
|
u32 num_valtypes;
|
|
};
|
|
|
|
struct instr {
|
|
enum instr_tag tag;
|
|
int pos;
|
|
union {
|
|
struct br_table br_table;
|
|
struct bulk_op bulk_op;
|
|
struct call_indirect call_indirect;
|
|
struct memarg memarg;
|
|
struct select_instr select;
|
|
struct block block;
|
|
struct expr else_block;
|
|
double f64;
|
|
float f32;
|
|
int i32;
|
|
u32 u32;
|
|
int64_t i64;
|
|
u64 u64;
|
|
unsigned char memidx;
|
|
enum reftype reftype;
|
|
};
|
|
};
|
|
|
|
enum datamode {
|
|
datamode_active,
|
|
datamode_passive,
|
|
};
|
|
|
|
struct wdata_active {
|
|
u32 mem_index;
|
|
struct expr offset_expr;
|
|
};
|
|
|
|
struct wdata {
|
|
struct wdata_active active;
|
|
u8 *bytes;
|
|
u32 bytes_len;
|
|
enum datamode mode;
|
|
};
|
|
|
|
struct datasec {
|
|
struct wdata *datas;
|
|
u32 num_datas;
|
|
};
|
|
|
|
struct startsec {
|
|
u32 start_fn;
|
|
};
|
|
|
|
struct module {
|
|
unsigned int parsed;
|
|
unsigned int custom_sections;
|
|
|
|
struct func *funcs;
|
|
|
|
u32 num_funcs;
|
|
|
|
struct customsec custom_section[MAX_CUSTOM_SECTIONS];
|
|
struct typesec type_section;
|
|
struct funcsec func_section;
|
|
struct importsec import_section;
|
|
struct exportsec export_section;
|
|
struct codesec code_section;
|
|
struct tablesec table_section;
|
|
struct memsec memory_section;
|
|
struct globalsec global_section;
|
|
struct startsec start_section;
|
|
struct elemsec element_section;
|
|
struct datasec data_section;
|
|
struct namesec name_section;
|
|
};
|
|
|
|
// make sure the struct is packed so that
|
|
struct label {
|
|
u32 instr_pos; // resolved status is stored in HOB of pos
|
|
u32 jump;
|
|
};
|
|
|
|
struct callframe {
|
|
struct cursor code;
|
|
struct val *locals;
|
|
struct func *func;
|
|
u16 prev_stack_items;
|
|
};
|
|
|
|
struct resolver {
|
|
u16 label;
|
|
u8 end_tag;
|
|
u8 start_tag;
|
|
};
|
|
|
|
struct global_inst {
|
|
struct val val;
|
|
};
|
|
|
|
struct module_inst {
|
|
struct table_inst *tables;
|
|
struct global_inst *globals;
|
|
struct elem_inst *elements;
|
|
|
|
u32 num_tables;
|
|
u32 num_globals;
|
|
u32 num_elements;
|
|
|
|
int start_fn;
|
|
unsigned char *globals_init;
|
|
};
|
|
|
|
struct wasi {
|
|
int argc;
|
|
const char **argv;
|
|
|
|
int environc;
|
|
const char **environ;
|
|
};
|
|
|
|
struct wasm_interp;
|
|
|
|
struct builtin {
|
|
const char *name;
|
|
int (*fn)(struct wasm_interp *);
|
|
int (*prepare_args)(struct wasm_interp *);
|
|
};
|
|
|
|
struct wasm_interp {
|
|
struct module *module;
|
|
struct module_inst module_inst;
|
|
struct wasi wasi;
|
|
void *context;
|
|
|
|
struct builtin builtins[MAX_BUILTINS];
|
|
int num_builtins;
|
|
|
|
int prev_resolvers, quitting;
|
|
|
|
struct errors errors; /* struct error */
|
|
size_t ops;
|
|
|
|
struct cursor callframes; /* struct callframe */
|
|
struct cursor stack; /* struct val */
|
|
struct cursor mem; /* u8/mixed */
|
|
|
|
struct cursor memory; /* memory pages (65536 blocks) */
|
|
|
|
struct cursor locals; /* struct val */
|
|
struct cursor labels; /* struct labels */
|
|
struct cursor num_labels;
|
|
|
|
// resolve stack for the current function. every time a control
|
|
// instruction is encountered, the label index is pushed. When an
|
|
// instruction is popped, we can resolve the label
|
|
struct cursor resolver_stack; /* struct resolver */
|
|
struct cursor resolver_offsets; /* int */
|
|
};
|
|
|
|
struct wasm_parser {
|
|
struct module module;
|
|
struct builtin *builtins;
|
|
u32 num_builtins;
|
|
struct cursor cur;
|
|
struct cursor mem;
|
|
struct errors errs;
|
|
};
|
|
|
|
|
|
int run_wasm(unsigned char *wasm, unsigned long len, int argc, const char **argv, char **env, int *retval);
|
|
int parse_wasm(struct wasm_parser *p);
|
|
int wasm_interp_init(struct wasm_interp *interp, struct module *module);
|
|
void wasm_parser_free(struct wasm_parser *parser);
|
|
void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t arena_size, struct builtin *, int num_builtins);
|
|
void wasm_interp_free(struct wasm_interp *interp);
|
|
int interp_wasm_module(struct wasm_interp *interp, int *retval);
|
|
int interp_wasm_module_resume(struct wasm_interp *interp, int *retval);
|
|
void print_error_backtrace(struct errors *errors);
|
|
void setup_wasi(struct wasm_interp *interp, int argc, const char **argv, char **env);
|
|
void print_callstack(struct wasm_interp *interp);
|
|
|
|
// builtin helpers
|
|
int get_params(struct wasm_interp *interp, struct val** vals, u32 num_vals);
|
|
int get_var_params(struct wasm_interp *interp, struct val** vals, u32 *num_vals);
|
|
u8 *interp_mem_ptr(struct wasm_interp *interp, u32 ptr, int size);
|
|
|
|
static INLINE struct callframe *top_callframe(struct cursor *cur)
|
|
{
|
|
return (struct callframe*)cursor_top(cur, sizeof(struct callframe));
|
|
}
|
|
|
|
|
|
static INLINE struct cursor *interp_codeptr(struct wasm_interp *interp)
|
|
{
|
|
struct callframe *frame;
|
|
if (unlikely(!(frame = top_callframe(&interp->callframes))))
|
|
return 0;
|
|
return &frame->code;
|
|
}
|
|
|
|
|
|
static INLINE int mem_ptr_str(struct wasm_interp *interp, u32 ptr,
|
|
const char **str)
|
|
{
|
|
// still technically unsafe if the string runs over the end of memory...
|
|
if (!(*str = (const char*)interp_mem_ptr(interp, ptr, 1))) {
|
|
return interp_error(interp, "int memptr");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static INLINE int mem_ptr_i32(struct wasm_interp *interp, u32 ptr, int **i)
|
|
{
|
|
if (!(*i = (int*)interp_mem_ptr(interp, ptr, sizeof(int))))
|
|
return interp_error(interp, "int memptr");
|
|
return 1;
|
|
}
|
|
|
|
static INLINE int cursor_pushval(struct cursor *cur, struct val *val)
|
|
{
|
|
return cursor_push(cur, (u8*)val, sizeof(*val));
|
|
}
|
|
|
|
static INLINE int cursor_push_i32(struct cursor *stack, int i)
|
|
{
|
|
struct val val;
|
|
val.type = val_i32;
|
|
val.num.i32 = i;
|
|
|
|
return cursor_pushval(stack, &val);
|
|
}
|
|
|
|
static INLINE int stack_push_i32(struct wasm_interp *interp, int i)
|
|
{
|
|
return cursor_push_i32(&interp->stack, i);
|
|
}
|
|
|
|
static INLINE struct callframe *top_callframes(struct cursor *cur, int top)
|
|
{
|
|
return (struct callframe*)cursor_topn(cur, sizeof(struct callframe), top);
|
|
}
|
|
|
|
static INLINE int was_section_parsed(struct module *module,
|
|
enum section_tag section)
|
|
{
|
|
if (section == section_custom)
|
|
return module->custom_sections > 0;
|
|
|
|
return module->parsed & (1 << section);
|
|
}
|
|
|
|
|
|
#endif /* PROTOVERSE_WASM_H */
|