/* * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #ifndef _AOT_RUNTIME_H_ #define _AOT_RUNTIME_H_ #include "bh_platform.h" #include "../common/wasm_runtime_common.h" #include "../interpreter/wasm_runtime.h" #include "../compilation/aot.h" #ifdef __cplusplus extern "C" { #endif typedef enum AOTSectionType { AOT_SECTION_TYPE_TARGET_INFO = 0, AOT_SECTION_TYPE_INIT_DATA = 1, AOT_SECTION_TYPE_TEXT = 2, AOT_SECTION_TYPE_FUNCTION = 3, AOT_SECTION_TYPE_EXPORT = 4, AOT_SECTION_TYPE_RELOCATION = 5, AOT_SECTION_TYPE_SIGANATURE = 6, AOT_SECTION_TYPE_CUSTOM = 100, } AOTSectionType; typedef enum AOTCustomSectionType { AOT_CUSTOM_SECTION_RAW = 0, AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1, AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2, AOT_CUSTOM_SECTION_NAME = 3, } AOTCustomSectionType; typedef struct AOTObjectDataSection { char *name; uint8 *data; uint32 size; } AOTObjectDataSection; /* Relocation info */ typedef struct AOTRelocation { uint64 relocation_offset; int64 relocation_addend; uint32 relocation_type; char *symbol_name; /* index in the symbol offset field */ uint32 symbol_index; } AOTRelocation; /* Relocation Group */ typedef struct AOTRelocationGroup { char *section_name; /* index in the symbol offset field */ uint32 name_index; uint32 relocation_count; AOTRelocation *relocations; } AOTRelocationGroup; /* AOT function instance */ typedef struct AOTFunctionInstance { char *func_name; uint32 func_index; bool is_import_func; union { struct { AOTFuncType *func_type; /* function pointer linked */ void *func_ptr; } func; AOTImportFunc *func_import; } u; } AOTFunctionInstance; typedef struct AOTModuleInstanceExtra { CApiFuncImport *c_api_func_imports; } AOTModuleInstanceExtra; #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) /* clang-format off */ typedef struct AOTUnwindInfo { uint8 Version : 3; uint8 Flags : 5; uint8 SizeOfProlog; uint8 CountOfCodes; uint8 FrameRegister : 4; uint8 FrameOffset : 4; struct { struct { uint8 CodeOffset; uint8 UnwindOp : 4; uint8 OpInfo : 4; }; uint16 FrameOffset; } UnwindCode[1]; } AOTUnwindInfo; /* clang-format on */ /* size of mov instruction and jmp instruction */ #define PLT_ITEM_SIZE 12 #endif typedef struct AOTModule { uint32 module_type; /* import memories */ uint32 import_memory_count; AOTImportMemory *import_memories; /* memory info */ uint32 memory_count; AOTMemory *memories; /* init data */ uint32 mem_init_data_count; AOTMemInitData **mem_init_data_list; /* native symbol */ void **native_symbol_list; /* import tables */ uint32 import_table_count; AOTImportTable *import_tables; /* tables */ uint32 table_count; AOTTable *tables; /* table init data info */ uint32 table_init_data_count; AOTTableInitData **table_init_data_list; /* function type info */ uint32 func_type_count; AOTFuncType **func_types; /* import global variable info */ uint32 import_global_count; AOTImportGlobal *import_globals; /* global variable info */ uint32 global_count; AOTGlobal *globals; /* total global variable size */ uint32 global_data_size; /* import function info */ uint32 import_func_count; AOTImportFunc *import_funcs; /* function info */ uint32 func_count; /* func pointers of AOTed (un-imported) functions */ void **func_ptrs; /* func type indexes of AOTed (un-imported) functions */ uint32 *func_type_indexes; /* export info */ uint32 export_count; AOTExport *exports; /* start function index, -1 denotes no start function */ uint32 start_func_index; /* start function, point to AOTed function */ void *start_function; uint32 malloc_func_index; uint32 free_func_index; uint32 retain_func_index; /* AOTed code */ void *code; uint32 code_size; /* literal for AOTed code */ uint8 *literal; uint32 literal_size; #if defined(BH_PLATFORM_WINDOWS) /* extra plt data area for __ymm, __xmm and __real constants in Windows platform */ uint8 *extra_plt_data; uint32 extra_plt_data_size; uint32 ymm_plt_count; uint32 xmm_plt_count; uint32 real_plt_count; uint32 float_plt_count; #endif #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) /* dynamic function table to be added by RtlAddFunctionTable(), used to unwind the call stack and register exception handler for AOT functions */ RUNTIME_FUNCTION *rtl_func_table; bool rtl_func_table_registered; #endif /* data sections in AOT object file, including .data, .rodata and .rodata.cstN. */ AOTObjectDataSection *data_sections; uint32 data_section_count; /* constant string set */ HashMap *const_str_set; /* the index of auxiliary __data_end global, -1 means unexported */ uint32 aux_data_end_global_index; /* auxiliary __data_end exported by wasm app */ uint32 aux_data_end; /* the index of auxiliary __heap_base global, -1 means unexported */ uint32 aux_heap_base_global_index; /* auxiliary __heap_base exported by wasm app */ uint32 aux_heap_base; /* the index of auxiliary stack top global, -1 means unexported */ uint32 aux_stack_top_global_index; /* auxiliary stack bottom resolved */ uint32 aux_stack_bottom; /* auxiliary stack size resolved */ uint32 aux_stack_size; /* is indirect mode or not */ bool is_indirect_mode; #if WASM_ENABLE_LIBC_WASI != 0 WASIArguments wasi_args; bool import_wasi_api; #endif #if WASM_ENABLE_DEBUG_AOT != 0 void *elf_hdr; uint32 elf_size; #endif #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 const char **aux_func_names; uint32 *aux_func_indexes; uint32 aux_func_name_count; #endif #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 WASMCustomSection *custom_section_list; #endif } AOTModule; #define AOTMemoryInstance WASMMemoryInstance #define AOTTableInstance WASMTableInstance #define AOTModuleInstance WASMModuleInstance /* Target info, read from ELF header of object file */ typedef struct AOTTargetInfo { /* Binary type, elf32l/elf32b/elf64l/elf64b */ uint16 bin_type; /* ABI type */ uint16 abi_type; /* Object file type */ uint16 e_type; /* Architecture */ uint16 e_machine; /* Object file version */ uint32 e_version; /* Processor-specific flags */ uint32 e_flags; /* Reserved */ uint32 reserved; /* Arch name */ char arch[16]; } AOTTargetInfo; typedef struct AOTFuncPerfProfInfo { /* total execution time */ uint64 total_exec_time; /* total execution count */ uint32 total_exec_cnt; } AOTFuncPerfProfInfo; /* AOT auxiliary call stack */ typedef struct AOTFrame { struct AOTFrame *prev_frame; uint32 func_index; #if WASM_ENABLE_PERF_PROFILING != 0 uint64 time_started; AOTFuncPerfProfInfo *func_perf_prof_info; #endif } AOTFrame; /** * Load a AOT module from aot file buffer * @param buf the byte buffer which contains the AOT file data * @param size the size of the buffer * @param error_buf output of the error info * @param error_buf_size the size of the error string * * @return return AOT module loaded, NULL if failed */ AOTModule * aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size); /** * Load a AOT module from a specified AOT section list. * * @param section_list the section list which contains each section data * @param error_buf output of the error info * @param error_buf_size the size of the error string * * @return return AOT module loaded, NULL if failed */ AOTModule * aot_load_from_sections(AOTSection *section_list, char *error_buf, uint32 error_buf_size); /** * Unload a AOT module. * * @param module the module to be unloaded */ void aot_unload(AOTModule *module); /** * Instantiate a AOT module. * * @param module the AOT module to instantiate * @param is_sub_inst the flag of sub instance * @param heap_size the default heap size of the module instance, a heap will * be created besides the app memory space. Both wasm app and native * function can allocate memory from the heap. If heap_size is 0, the * default heap size will be used. * @param error_buf buffer to output the error info if failed * @param error_buf_size the size of the error buffer * * @return return the instantiated AOT module instance, NULL if failed */ AOTModuleInstance * aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); /** * Deinstantiate a AOT module instance, destroy the resources. * * @param module_inst the AOT module instance to destroy * @param is_sub_inst the flag of sub instance */ void aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); /** * Lookup an exported function in the AOT module instance. * * @param module_inst the module instance * @param name the name of the function * @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64" * to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32" * * @return the function instance found */ AOTFunctionInstance * aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, const char *signature); /** * Call the given AOT function of a AOT module instance with * arguments. * * @param exec_env the execution environment * @param function the function to be called * @param argc the number of arguments * @param argv the arguments. If the function method has return value, * the first (or first two in case 64-bit return value) element of * argv stores the return value of the called AOT function after this * function returns. * * @return true if success, false otherwise and exception will be thrown, * the caller can call aot_get_exception to get exception info. */ bool aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, unsigned argc, uint32 argv[]); bool aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, AOTFunctionInstance *function, unsigned argc, uint32 argv[]); /** * Set AOT module instance exception with exception string * * @param module the AOT module instance * * @param exception current exception string */ void aot_set_exception(AOTModuleInstance *module_inst, const char *exception); void aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id); /** * Get exception info of the AOT module instance. * * @param module_inst the AOT module instance * * @return the exception string */ const char * aot_get_exception(AOTModuleInstance *module_inst); uint32 aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, void **p_native_addr); uint32 aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, void **p_native_addr); void aot_module_free(AOTModuleInstance *module_inst, uint32 ptr); uint32 aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, uint32 size); bool aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); /** * Invoke native function from aot code */ bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, uint32 *argv); bool aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, uint32 argc, uint32 *argv); /** * Check whether the app address and the buf is inside the linear memory, * and convert the app address into native address */ bool aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str, uint32 app_buf_addr, uint32 app_buf_size, void **p_native_addr); uint32 aot_get_plt_table_size(); void * aot_memmove(void *dest, const void *src, size_t n); void * aot_memset(void *s, int c, size_t n); double aot_sqrt(double x); float aot_sqrtf(float x); #if WASM_ENABLE_BULK_MEMORY != 0 bool aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, uint32 len, uint32 dst); bool aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index); #endif #if WASM_ENABLE_THREAD_MGR != 0 bool aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size); bool aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size); #endif void aot_get_module_mem_consumption(const AOTModule *module, WASMModuleMemConsumption *mem_conspn); void aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, WASMModuleInstMemConsumption *mem_conspn); #if WASM_ENABLE_REF_TYPES != 0 void aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx); void aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 tbl_seg_idx, uint32 length, uint32 src_offset, uint32 dst_offset); void aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, uint32 dst_tbl_idx, uint32 length, uint32 src_offset, uint32 dst_offset); void aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, uint32 val, uint32 data_offset); uint32 aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 inc_entries, uint32 init_val); #endif bool aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index); void aot_free_frame(WASMExecEnv *exec_env); bool aot_create_call_stack(struct WASMExecEnv *exec_env); /** * @brief Dump wasm call stack or get the size * * @param exec_env the execution environment * @param print whether to print to stdout or not * @param buf buffer to store the dumped content * @param len length of the buffer * * @return when print is true, return the bytes printed out to stdout; when * print is false and buf is NULL, return the size required to store the * callstack content; when print is false and buf is not NULL, return the size * dumped to the buffer, 0 means error and data in buf may be invalid */ uint32 aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len); void aot_dump_perf_profiling(const AOTModuleInstance *module_inst); const uint8 * aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_RUNTIME_H_ */