/* * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #ifndef _WASM_H_ #define _WASM_H_ #include "bh_platform.h" #include "bh_hashmap.h" #include "bh_assert.h" #ifdef __cplusplus extern "C" { #endif /** Value Type */ #define VALUE_TYPE_I32 0x7F #define VALUE_TYPE_I64 0X7E #define VALUE_TYPE_F32 0x7D #define VALUE_TYPE_F64 0x7C #define VALUE_TYPE_VOID 0x40 /* Used by AOT */ #define VALUE_TYPE_I1 0x41 /* Used by loader to represent any type of i32/i64/f32/f64 */ #define VALUE_TYPE_ANY 0x42 /* Table Element Type */ #define TABLE_ELEM_TYPE_ANY_FUNC 0x70 #define DEFAULT_NUM_BYTES_PER_PAGE 65536 #define INIT_EXPR_TYPE_I32_CONST 0x41 #define INIT_EXPR_TYPE_I64_CONST 0x42 #define INIT_EXPR_TYPE_F32_CONST 0x43 #define INIT_EXPR_TYPE_F64_CONST 0x44 #define INIT_EXPR_TYPE_GET_GLOBAL 0x23 #define INIT_EXPR_TYPE_ERROR 0xff #define WASM_MAGIC_NUMBER 0x6d736100 #define WASM_CURRENT_VERSION 1 #define SECTION_TYPE_USER 0 #define SECTION_TYPE_TYPE 1 #define SECTION_TYPE_IMPORT 2 #define SECTION_TYPE_FUNC 3 #define SECTION_TYPE_TABLE 4 #define SECTION_TYPE_MEMORY 5 #define SECTION_TYPE_GLOBAL 6 #define SECTION_TYPE_EXPORT 7 #define SECTION_TYPE_START 8 #define SECTION_TYPE_ELEM 9 #define SECTION_TYPE_CODE 10 #define SECTION_TYPE_DATA 11 #if WASM_ENABLE_BULK_MEMORY != 0 #define SECTION_TYPE_DATACOUNT 12 #endif #define IMPORT_KIND_FUNC 0 #define IMPORT_KIND_TABLE 1 #define IMPORT_KIND_MEMORY 2 #define IMPORT_KIND_GLOBAL 3 #define EXPORT_KIND_FUNC 0 #define EXPORT_KIND_TABLE 1 #define EXPORT_KIND_MEMORY 2 #define EXPORT_KIND_GLOBAL 3 #define BLOCK_TYPE_BLOCK 0 #define BLOCK_TYPE_LOOP 1 #define BLOCK_TYPE_IF 2 #define BLOCK_TYPE_FUNCTION 3 typedef struct WASMModule WASMModule; typedef struct WASMFunction WASMFunction; typedef struct WASMGlobal WASMGlobal; typedef union WASMValue { int32 i32; uint32 u32; int64 i64; uint64 u64; float32 f32; float64 f64; uintptr_t addr; } WASMValue; typedef struct InitializerExpression { /* type of INIT_EXPR_TYPE_XXX */ uint8 init_expr_type; union { int32 i32; int64 i64; float32 f32; float64 f64; uint32 global_index; } u; } InitializerExpression; typedef struct WASMType { uint32 param_count; /* only one result is supported currently */ uint32 result_count; /* types of params and results */ uint8 types[1]; } WASMType; typedef struct WASMTable { uint8 elem_type; uint32 flags; uint32 init_size; /* specified if (flags & 1), else it is 0x10000 */ uint32 max_size; } WASMTable; typedef struct WASMMemory { uint32 flags; uint32 num_bytes_per_page; uint32 init_page_count; uint32 max_page_count; } WASMMemory; typedef struct WASMTableImport { char *module_name; char *field_name; uint8 elem_type; uint32 flags; uint32 init_size; /* specified if (flags & 1), else it is 0x10000 */ uint32 max_size; #if WASM_ENABLE_MULTI_MODULE != 0 WASMModule *import_module; WASMTable *import_table_linked; #endif } WASMTableImport; typedef struct WASMMemoryImport { char *module_name; char *field_name; uint32 flags; uint32 num_bytes_per_page; uint32 init_page_count; uint32 max_page_count; #if WASM_ENABLE_MULTI_MODULE != 0 WASMModule *import_module; WASMMemory *import_memory_linked; #endif } WASMMemoryImport; typedef struct WASMFunctionImport { char *module_name; char *field_name; /* function type */ WASMType *func_type; /* native function pointer after linked */ void *func_ptr_linked; /* signature from registered native symbols */ const char *signature; /* attachment */ void *attachment; bool call_conv_raw; #if WASM_ENABLE_MULTI_MODULE != 0 WASMModule *import_module; WASMFunction *import_func_linked; #endif } WASMFunctionImport; typedef struct WASMGlobalImport { char *module_name; char *field_name; uint8 type; bool is_mutable; /* global data after linked */ WASMValue global_data_linked; #if WASM_ENABLE_MULTI_MODULE != 0 /* imported function pointer after linked */ // TODO: remove if not necessary WASMModule *import_module; WASMGlobal *import_global_linked; #endif } WASMGlobalImport; typedef struct WASMImport { uint8 kind; union { WASMFunctionImport function; WASMTableImport table; WASMMemoryImport memory; WASMGlobalImport global; struct { char *module_name; char *field_name; } names; } u; } WASMImport; typedef struct WASMFunction { /* the type of function */ WASMType *func_type; uint32 local_count; uint8 *local_types; /* cell num of parameters */ uint16 param_cell_num; /* cell num of return type */ uint16 ret_cell_num; /* cell num of local variables */ uint16 local_cell_num; /* offset of each local, including function paramameters and local variables */ uint16 *local_offsets; uint32 max_stack_cell_num; uint32 max_block_num; /* Whether function has opcode memory.grow */ bool has_op_memory_grow; /* Whether function has opcode call or call_indirect */ bool has_op_func_call; uint32 code_size; uint8 *code; #if WASM_ENABLE_FAST_INTERP != 0 uint32 code_compiled_size; uint8 *code_compiled; uint8 *consts; uint32 const_cell_num; #endif } WASMFunction; typedef struct WASMGlobal { uint8 type; bool is_mutable; InitializerExpression init_expr; } WASMGlobal; typedef struct WASMExport { char *name; uint8 kind; uint32 index; } WASMExport; typedef struct WASMTableSeg { uint32 table_index; InitializerExpression base_offset; uint32 function_count; uint32 *func_indexes; } WASMTableSeg; typedef struct WASMDataSeg { uint32 memory_index; InitializerExpression base_offset; uint32 data_length; #if WASM_ENABLE_BULK_MEMORY != 0 bool is_passive; #endif uint8 *data; } WASMDataSeg; typedef struct BlockAddr { const uint8 *start_addr; uint8 *else_addr; uint8 *end_addr; } BlockAddr; #if WASM_ENABLE_LIBC_WASI != 0 typedef struct WASIArguments { const char **dir_list; uint32 dir_count; const char **map_dir_list; uint32 map_dir_count; const char **env; uint32 env_count; char **argv; uint32 argc; } WASIArguments; #endif typedef struct StringNode { struct StringNode *next; char *str; } StringNode, *StringList; typedef struct WASMModule { /* Module type, for module loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; for module loaded from AOT file, this field is Wasm_Module_AoT, and this structure should be treated as AOTModule structure. */ uint32 module_type; uint32 type_count; uint32 import_count; uint32 function_count; uint32 table_count; uint32 memory_count; uint32 global_count; uint32 export_count; uint32 table_seg_count; /* data seg count read from data segment section */ uint32 data_seg_count; #if WASM_ENABLE_BULK_MEMORY != 0 /* data count read from datacount section */ uint32 data_seg_count1; #endif uint32 import_function_count; uint32 import_table_count; uint32 import_memory_count; uint32 import_global_count; WASMImport *import_functions; WASMImport *import_tables; WASMImport *import_memories; WASMImport *import_globals; WASMType **types; WASMImport *imports; WASMFunction **functions; WASMTable *tables; WASMMemory *memories; WASMGlobal *globals; WASMExport *exports; WASMTableSeg *table_segments; WASMDataSeg **data_segments; uint32 start_function; /* __data_end global exported by llvm */ uint32 llvm_aux_data_end; /* auxiliary stack bottom, or __heap_base global exported by llvm */ uint32 llvm_aux_stack_bottom; /* auxiliary stack size */ uint32 llvm_aux_stack_size; /* the index of a global exported by llvm, which is auxiliary stack top pointer */ uint32 llvm_aux_stack_global_index; /* Whether there is possible memory grow, e.g. memory.grow opcode */ bool possible_memory_grow; StringList const_str_list; #if WASM_ENABLE_LIBC_WASI != 0 WASIArguments wasi_args; bool is_wasi_module; #endif #if WASM_ENABLE_MULTI_MODULE != 0 // TODO: mutex ? mutli-threads ? bh_list import_module_list_head; bh_list *import_module_list; #endif } WASMModule; typedef struct WASMBranchBlock { uint8 block_type; uint8 return_type; uint8 *target_addr; uint32 *frame_sp; } WASMBranchBlock; /* Execution environment, e.g. stack info */ /** * Align an unsigned value on a alignment boundary. * * @param v the value to be aligned * @param b the alignment boundary (2, 4, 8, ...) * * @return the aligned value */ inline static unsigned align_uint (unsigned v, unsigned b) { unsigned m = b - 1; return (v + m) & ~m; } /** * Return the hash value of c string. */ inline static uint32 wasm_string_hash(const char *str) { unsigned h = (unsigned)strlen(str); const uint8 *p = (uint8*)str; const uint8 *end = p + h; while (p != end) h = ((h << 5) - h) + *p++; return h; } /** * Whether two c strings are equal. */ inline static bool wasm_string_equal(const char *s1, const char *s2) { return strcmp(s1, s2) == 0 ? true : false; } /** * Return the byte size of value type. * */ inline static uint32 wasm_value_type_size(uint8 value_type) { switch (value_type) { case VALUE_TYPE_I32: case VALUE_TYPE_F32: return sizeof(int32); case VALUE_TYPE_I64: case VALUE_TYPE_F64: return sizeof(int64); default: bh_assert(0); } return 0; } inline static uint16 wasm_value_type_cell_num(uint8 value_type) { switch (value_type) { case VALUE_TYPE_I32: case VALUE_TYPE_F32: return 1; case VALUE_TYPE_I64: case VALUE_TYPE_F64: return 2; default: bh_assert(0); } return 0; } inline static uint16 wasm_get_cell_num(const uint8 *types, uint32 type_count) { uint32 cell_num = 0; uint32 i; for (i = 0; i < type_count; i++) cell_num += wasm_value_type_cell_num(types[i]); return (uint16)cell_num; } inline static uint16 wasm_type_param_cell_num(const WASMType *type) { return wasm_get_cell_num(type->types, type->param_count); } inline static uint16 wasm_type_return_cell_num(const WASMType *type) { return wasm_get_cell_num(type->types + type->param_count, type->result_count); } inline static bool wasm_type_equal(const WASMType *type1, const WASMType *type2) { return (type1->param_count == type2->param_count && type1->result_count == type2->result_count && memcmp(type1->types, type2->types, type1->param_count + type1->result_count) == 0) ? true : false; } #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _WASM_H_ */