Implement GC (Garbage Collection) feature for interpreter, AOT and LLVM-JIT (#3125)
Implement the GC (Garbage Collection) feature for interpreter mode, AOT mode and LLVM-JIT mode, and support most features of the latest spec proposal, and also enable the stringref feature. Use `cmake -DWAMR_BUILD_GC=1/0` to enable/disable the feature, and `wamrc --enable-gc` to generate the AOT file with GC supported. And update the AOT file version from 2 to 3 since there are many AOT ABI breaks, including the changes of AOT file format, the changes of AOT module/memory instance layouts, the AOT runtime APIs for the AOT code to invoke and so on.
This commit is contained in:
@ -35,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
#include "aot_orc_extra.h"
|
||||
#include "aot_comp_option.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -64,6 +65,8 @@ extern "C" {
|
||||
#undef DUMP_MODULE
|
||||
#endif
|
||||
|
||||
struct AOTValueSlot;
|
||||
|
||||
/**
|
||||
* Value in the WASM operation stack, each stack element
|
||||
* is an LLVM value
|
||||
@ -86,6 +89,53 @@ typedef struct AOTValueStack {
|
||||
AOTValue *value_list_end;
|
||||
} AOTValueStack;
|
||||
|
||||
/* Record information of a value slot of local variable or stack
|
||||
during translation */
|
||||
typedef struct AOTValueSlot {
|
||||
/* The LLVM value of this slot */
|
||||
LLVMValueRef value;
|
||||
|
||||
/* The value type of this slot */
|
||||
uint8 type;
|
||||
|
||||
/* The dirty bit of the value slot. It's set if the value in
|
||||
register is newer than the value in memory. */
|
||||
uint32 dirty : 1;
|
||||
|
||||
/* Whether the new value in register is a reference, which is valid
|
||||
only when the dirty bit is set. */
|
||||
uint32 ref : 1;
|
||||
|
||||
/* Committed reference flag:
|
||||
0: uncommitted, 1: not-reference, 2: reference */
|
||||
uint32 committed_ref : 2;
|
||||
} AOTValueSlot;
|
||||
|
||||
/* Frame information for translation */
|
||||
typedef struct AOTCompFrame {
|
||||
/* The current compilation context */
|
||||
struct AOTCompContext *comp_ctx;
|
||||
/* The current function context */
|
||||
struct AOTFuncContext *func_ctx;
|
||||
/* The current instruction pointer which is being compiled */
|
||||
const uint8 *frame_ip;
|
||||
|
||||
/* Max local slot number */
|
||||
uint32 max_local_cell_num;
|
||||
|
||||
/* Max operand stack slot number */
|
||||
uint32 max_stack_cell_num;
|
||||
|
||||
/* Size of current AOTFrame/WASMInterpFrame */
|
||||
uint32 cur_frame_size;
|
||||
|
||||
/* Stack top pointer */
|
||||
AOTValueSlot *sp;
|
||||
|
||||
/* Local variables + stack operands */
|
||||
AOTValueSlot lp[1];
|
||||
} AOTCompFrame;
|
||||
|
||||
typedef struct AOTBlock {
|
||||
struct AOTBlock *next;
|
||||
struct AOTBlock *prev;
|
||||
@ -124,6 +174,12 @@ typedef struct AOTBlock {
|
||||
uint32 result_count;
|
||||
uint8 *result_types;
|
||||
LLVMValueRef *result_phis;
|
||||
|
||||
/* The begin frame stack pointer of this block */
|
||||
AOTValueSlot *frame_sp_begin;
|
||||
/* The max frame stack pointer that br/br_if/br_table/br_on_xxx
|
||||
opcodes ever reached when they jumped to the end this block */
|
||||
AOTValueSlot *frame_sp_max_reached;
|
||||
} AOTBlock;
|
||||
|
||||
/**
|
||||
@ -176,12 +232,19 @@ typedef struct AOTFuncContext {
|
||||
|
||||
LLVMValueRef cur_exception;
|
||||
|
||||
LLVMValueRef cur_frame;
|
||||
LLVMValueRef cur_frame_ptr;
|
||||
LLVMValueRef wasm_stack_top_bound;
|
||||
LLVMValueRef wasm_stack_top_ptr;
|
||||
|
||||
bool mem_space_unchanged;
|
||||
AOTCheckedAddrList checked_addr_list;
|
||||
|
||||
LLVMBasicBlockRef got_exception_block;
|
||||
LLVMBasicBlockRef func_return_block;
|
||||
LLVMValueRef exception_id_phi;
|
||||
/* current ip when exception is thrown */
|
||||
LLVMValueRef exception_ip_phi;
|
||||
LLVMValueRef func_type_indexes;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef debug_func;
|
||||
@ -198,6 +261,7 @@ typedef struct AOTLLVMTypes {
|
||||
LLVMTypeRef int16_type;
|
||||
LLVMTypeRef int32_type;
|
||||
LLVMTypeRef int64_type;
|
||||
LLVMTypeRef intptr_t_type;
|
||||
LLVMTypeRef float32_type;
|
||||
LLVMTypeRef float64_type;
|
||||
LLVMTypeRef void_type;
|
||||
@ -207,6 +271,7 @@ typedef struct AOTLLVMTypes {
|
||||
LLVMTypeRef int16_ptr_type;
|
||||
LLVMTypeRef int32_ptr_type;
|
||||
LLVMTypeRef int64_ptr_type;
|
||||
LLVMTypeRef intptr_t_ptr_type;
|
||||
LLVMTypeRef float32_ptr_type;
|
||||
LLVMTypeRef float64_ptr_type;
|
||||
|
||||
@ -233,12 +298,15 @@ typedef struct AOTLLVMTypes {
|
||||
|
||||
LLVMTypeRef funcref_type;
|
||||
LLVMTypeRef externref_type;
|
||||
LLVMTypeRef gc_ref_type;
|
||||
LLVMTypeRef gc_ref_ptr_type;
|
||||
} AOTLLVMTypes;
|
||||
|
||||
typedef struct AOTLLVMConsts {
|
||||
LLVMValueRef i1_zero;
|
||||
LLVMValueRef i1_one;
|
||||
LLVMValueRef i8_zero;
|
||||
LLVMValueRef i8_one;
|
||||
LLVMValueRef i32_zero;
|
||||
LLVMValueRef i64_zero;
|
||||
LLVMValueRef f32_zero;
|
||||
@ -282,6 +350,8 @@ typedef struct AOTLLVMConsts {
|
||||
LLVMValueRef i32x8_zero;
|
||||
LLVMValueRef i32x4_zero;
|
||||
LLVMValueRef i32x2_zero;
|
||||
LLVMValueRef gc_ref_null;
|
||||
LLVMValueRef i8_ptr_null;
|
||||
} AOTLLVMConsts;
|
||||
|
||||
/**
|
||||
@ -339,6 +409,12 @@ typedef struct AOTCompContext {
|
||||
/* Generate auxiliary stack frame */
|
||||
bool enable_aux_stack_frame;
|
||||
|
||||
/* Function performance profiling */
|
||||
bool enable_perf_profiling;
|
||||
|
||||
/* Memory usage profiling */
|
||||
bool enable_memory_profiling;
|
||||
|
||||
/* Thread Manager */
|
||||
bool enable_thread_mgr;
|
||||
|
||||
@ -380,6 +456,11 @@ typedef struct AOTCompContext {
|
||||
/* Whether optimize the JITed code */
|
||||
bool optimize;
|
||||
|
||||
bool emit_frame_pointer;
|
||||
|
||||
/* Enable GC */
|
||||
bool enable_gc;
|
||||
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
|
||||
@ -403,7 +484,6 @@ typedef struct AOTCompContext {
|
||||
AOTLLVMConsts llvm_consts;
|
||||
|
||||
/* Function contexts */
|
||||
/* TODO: */
|
||||
AOTFuncContext **func_ctxes;
|
||||
uint32 func_ctx_count;
|
||||
char **custom_sections_wp;
|
||||
@ -428,7 +508,8 @@ typedef struct AOTCompContext {
|
||||
const char *llvm_passes;
|
||||
const char *builtin_intrinsics;
|
||||
|
||||
bool emit_frame_pointer;
|
||||
/* Current frame information for translation */
|
||||
AOTCompFrame *aot_frame;
|
||||
} AOTCompContext;
|
||||
|
||||
enum {
|
||||
@ -438,41 +519,6 @@ enum {
|
||||
AOT_LLVMIR_OPT_FILE,
|
||||
};
|
||||
|
||||
/* always sync it with AOTCompOption in aot_export.h */
|
||||
typedef struct AOTCompOption {
|
||||
bool is_jit_mode;
|
||||
bool is_indirect_mode;
|
||||
char *target_arch;
|
||||
char *target_abi;
|
||||
char *target_cpu;
|
||||
char *cpu_features;
|
||||
bool is_sgx_platform;
|
||||
bool enable_bulk_memory;
|
||||
bool enable_thread_mgr;
|
||||
bool enable_tail_call;
|
||||
bool enable_simd;
|
||||
bool enable_ref_types;
|
||||
bool enable_aux_stack_check;
|
||||
bool enable_aux_stack_frame;
|
||||
bool disable_llvm_intrinsics;
|
||||
bool disable_llvm_lto;
|
||||
bool enable_llvm_pgo;
|
||||
bool enable_stack_estimation;
|
||||
bool quick_invoke_c_api_import;
|
||||
char *use_prof_file;
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
uint32 bounds_checks;
|
||||
uint32 stack_bounds_checks;
|
||||
uint32 segue_flags;
|
||||
char **custom_sections;
|
||||
uint32 custom_sections_count;
|
||||
const char *stack_usage_file;
|
||||
const char *llvm_passes;
|
||||
const char *builtin_intrinsics;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
bool
|
||||
aot_compiler_init(void);
|
||||
|
||||
@ -498,13 +544,14 @@ void
|
||||
aot_destroy_elf_file(uint8 *elf_file);
|
||||
|
||||
void
|
||||
aot_value_stack_push(AOTValueStack *stack, AOTValue *value);
|
||||
aot_value_stack_push(const AOTCompContext *comp_ctx, AOTValueStack *stack,
|
||||
AOTValue *value);
|
||||
|
||||
AOTValue *
|
||||
aot_value_stack_pop(AOTValueStack *stack);
|
||||
aot_value_stack_pop(const AOTCompContext *comp_ctx, AOTValueStack *stack);
|
||||
|
||||
void
|
||||
aot_value_stack_destroy(AOTValueStack *stack);
|
||||
aot_value_stack_destroy(AOTCompContext *comp_ctx, AOTValueStack *stack);
|
||||
|
||||
void
|
||||
aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block);
|
||||
@ -513,13 +560,14 @@ AOTBlock *
|
||||
aot_block_stack_pop(AOTBlockStack *stack);
|
||||
|
||||
void
|
||||
aot_block_stack_destroy(AOTBlockStack *stack);
|
||||
aot_block_stack_destroy(AOTCompContext *comp_ctx, AOTBlockStack *stack);
|
||||
|
||||
void
|
||||
aot_block_destroy(AOTBlock *block);
|
||||
aot_block_destroy(AOTCompContext *comp_ctx, AOTBlock *block);
|
||||
|
||||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(const AOTLLVMTypes *llvm_types, uint8 wasm_type);
|
||||
wasm_type_to_llvm_type(const AOTCompContext *comp_ctx,
|
||||
const AOTLLVMTypes *llvm_types, uint8 wasm_type);
|
||||
|
||||
bool
|
||||
aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx,
|
||||
|
||||
Reference in New Issue
Block a user