Переглянути джерело

Fix GC AOT on 32bit target (#2814)

Xu Jun 2 роки тому
батько
коміт
c4010b0d3a

+ 2 - 3
core/iwasm/aot/aot_runtime.c

@@ -3151,9 +3151,8 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index)
             }
         }
 
-        if (func_type->param_count == 0) {
-            /* We reserve at least two cells for native frame */
-            frame_ref[0] = frame_ref[1] = 0;
+        for (j = func_type->param_cell_num; j < 2; j++) {
+            frame_ref[j] = 0;
         }
     }
 #endif

+ 74 - 15
core/iwasm/compilation/aot.c

@@ -334,13 +334,16 @@ aot_destroy_funcs(AOTFunc **funcs, uint32 count)
     uint32 i;
 
     for (i = 0; i < count; i++)
-        if (funcs[i])
+        if (funcs[i]) {
+            if (funcs[i]->local_offsets)
+                wasm_runtime_free(funcs[i]->local_offsets);
             wasm_runtime_free(funcs[i]);
+        }
     wasm_runtime_free(funcs);
 }
 
 static AOTFunc **
-aot_create_funcs(const WASMModule *module)
+aot_create_funcs(const WASMModule *module, uint32 pointer_size)
 {
     AOTFunc **funcs;
     uint64 size;
@@ -358,29 +361,70 @@ aot_create_funcs(const WASMModule *module)
     /* Create each function */
     for (i = 0; i < module->function_count; i++) {
         WASMFunction *func = module->functions[i];
+        AOTFuncType *func_type = NULL;
+        AOTFunc *aot_func = NULL;
+        uint64 total_size;
+        uint32 offset = 0;
+
         size = sizeof(AOTFunc);
-        if (!(funcs[i] = wasm_runtime_malloc((uint32)size))) {
+        if (!(aot_func = funcs[i] = wasm_runtime_malloc((uint32)size))) {
             aot_set_last_error("allocate memory failed.");
             goto fail;
         }
+        memset(aot_func, 0, sizeof(AOTFunc));
 
-        funcs[i]->func_type = func->func_type;
+        func_type = aot_func->func_type = func->func_type;
 
         /* Resolve function type index */
-        for (j = 0; j < module->type_count; j++)
-            if (func->func_type == (WASMFuncType *)module->types[j]) {
-                funcs[i]->func_type_index = j;
+        for (j = 0; j < module->type_count; j++) {
+            if (func_type == (WASMFuncType *)module->types[j]) {
+                aot_func->func_type_index = j;
                 break;
             }
+        }
+
+        total_size = sizeof(uint16)
+                     * ((uint64)func_type->param_count + func->local_count);
+        if ((total_size > 0)
+            && (total_size >= UINT32_MAX
+                || !(aot_func->local_offsets =
+                         wasm_runtime_malloc((uint32)total_size)))) {
+            aot_set_last_error("allocate memory failed.");
+            goto fail;
+        }
 
         /* Resolve local variable info and code info */
-        funcs[i]->local_count = func->local_count;
-        funcs[i]->local_types = func->local_types;
-        funcs[i]->param_cell_num = func->param_cell_num;
-        funcs[i]->local_cell_num = func->local_cell_num;
-        funcs[i]->max_stack_cell_num = func->max_stack_cell_num;
-        funcs[i]->code = func->code;
-        funcs[i]->code_size = func->code_size;
+        aot_func->local_count = func->local_count;
+        aot_func->local_types_wp = func->local_types;
+        aot_func->code = func->code;
+        aot_func->code_size = func->code_size;
+
+        /* Resolve local offsets */
+        for (j = 0; j < func_type->param_count; j++) {
+            aot_func->local_offsets[j] = (uint16)offset;
+            offset += wasm_value_type_cell_num_internal(func_type->types[j],
+                                                        pointer_size);
+        }
+        aot_func->param_cell_num = offset;
+
+        for (j = 0; j < func->local_count; j++) {
+            aot_func->local_offsets[func_type->param_count + j] =
+                (uint16)offset;
+            offset += wasm_value_type_cell_num_internal(func->local_types[j],
+                                                        pointer_size);
+        }
+        aot_func->local_cell_num = offset - aot_func->param_cell_num;
+
+        aot_func->max_stack_cell_num = func->max_stack_cell_num;
+        /* We use max_stack_cell_num calculated from wasm_loader, which is based
+         * on wamrc's target type.
+         *  - If the wamrc is compiled as 64bit, then the number is enough for
+         *      both 32bit and 64bit runtime target
+         *  - If the wamrc is compiled as 32bit, then we multiply this number by
+         *      two to avoid overflow on 64bit runtime target  */
+        if (sizeof(uintptr_t) == 4) {
+            aot_func->max_stack_cell_num *= 2;
+        }
     }
 
     return funcs;
@@ -448,6 +492,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0, i, j;
     uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
     uint64 size;
+    bool is_64bit_target = false;
 #if WASM_ENABLE_GC != 0
     bool is_target_x86 = false;
 #endif
@@ -466,6 +511,18 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     }
 #endif
 
+    if (!target_arch) {
+#if UINTPTR_MAX == UINT64_MAX
+        is_64bit_target = true;
+#endif
+    }
+    else {
+        /* All 64bit targets contains "64" string in their target name */
+        if (strstr(target_arch, "64") != NULL) {
+            is_64bit_target = true;
+        }
+    }
+
     /* Allocate memory */
     if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
         aot_set_last_error("create compile data failed.\n");
@@ -622,7 +679,9 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
 
     /* Create functions */
     comp_data->func_count = module->function_count;
-    if (comp_data->func_count && !(comp_data->funcs = aot_create_funcs(module)))
+    if (comp_data->func_count
+        && !(comp_data->funcs =
+                 aot_create_funcs(module, is_64bit_target ? 8 : 4)))
         goto fail;
 
 #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0

+ 4 - 1
core/iwasm/compilation/aot.h

@@ -244,12 +244,15 @@ typedef struct AOTFunc {
     AOTFuncType *func_type;
     uint32 func_type_index;
     uint32 local_count;
-    uint8 *local_types;
+    uint8 *local_types_wp;
     uint16 param_cell_num;
     uint16 local_cell_num;
     uint32 max_stack_cell_num;
     uint32 code_size;
     uint8 *code;
+    /* offset of each local, including function parameters
+       and local variables */
+    uint16 *local_offsets;
 } AOTFunc;
 
 typedef struct AOTCompData {

+ 3 - 6
core/iwasm/compilation/aot_compiler.c

@@ -557,8 +557,8 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, const AOTValueSlot *sp,
     bool is_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
 
     if (!comp_ctx->is_jit_mode) {
-        offset_ip = (uint32)sizeof(uintptr_t) * 4;
-        offset_sp = (uint32)sizeof(uintptr_t) * 5;
+        offset_ip = frame->comp_ctx->pointer_size * 4;
+        offset_sp = frame->comp_ctx->pointer_size * 5;
     }
     else {
         offset_ip = offsetof(WASMInterpFrame, ip);
@@ -699,9 +699,6 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     memset(aot_frame, 0, (uint32)total_size);
 
     aot_frame->cur_wasm_module = wasm_module;
-    aot_frame->cur_wasm_func = wasm_module->functions[func_idx];
-    aot_frame->cur_wasm_func_idx =
-        func_idx + wasm_module->import_function_count;
     aot_frame->comp_ctx = comp_ctx;
     aot_frame->func_ctx = func_ctx;
 
@@ -794,7 +791,7 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Set all locals dirty since they were set to llvm value but
        haven't been committed to the AOT/JIT stack frame */
     for (i = 0; i < aot_func->local_count; i++) {
-        local_type = aot_func->local_types[i];
+        local_type = aot_func->local_types_wp[i];
 
         switch (local_type) {
             case VALUE_TYPE_I32:

+ 12 - 8
core/iwasm/compilation/aot_emit_function.c

@@ -246,7 +246,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
         LLVMSetAlignment(res, 1);
 
-        cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
+        cell_num += wasm_value_type_cell_num_internal(aot_func_type->types[i],
+                                                      comp_ctx->pointer_size);
     }
 
     func_param_values[0] = func_ctx->exec_env;
@@ -745,7 +746,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 goto fail;
             }
             param_values[param_count + 1 + i] = ext_ret_ptr;
-            cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
+            cell_num += wasm_value_type_cell_num_internal(
+                ext_ret_types[i], comp_ctx->pointer_size);
         }
     }
 
@@ -1127,7 +1129,8 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
         LLVMSetAlignment(res, 1);
 
-        cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
+        cell_num += wasm_value_type_cell_num_internal(aot_func_type->types[i],
+                                                      comp_ctx->pointer_size);
     }
 
     func_param_values[0] = func_ctx->exec_env;
@@ -1174,7 +1177,8 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             aot_set_last_error("llvm build load failed.");
             return false;
         }
-        cell_num += wasm_value_type_cell_num(wasm_ret_types[i]);
+        cell_num += wasm_value_type_cell_num_internal(wasm_ret_types[i],
+                                                      comp_ctx->pointer_size);
     }
 
     *p_res = res;
@@ -1553,8 +1557,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
 
         param_values[func_param_count + i] = ext_ret_ptr;
-        ext_cell_num +=
-            wasm_value_type_cell_num(func_type->types[func_param_count + i]);
+        ext_cell_num += wasm_value_type_cell_num_internal(
+            func_type->types[func_param_count + i], comp_ctx->pointer_size);
     }
 
     if (ext_cell_num > 64) {
@@ -2054,8 +2058,8 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
 
         param_values[func_param_count + i] = ext_ret_ptr;
-        ext_cell_num +=
-            wasm_value_type_cell_num(func_type->types[func_param_count + i]);
+        ext_cell_num += wasm_value_type_cell_num_internal(
+            func_type->types[func_param_count + i], comp_ctx->pointer_size);
     }
 
     if (ext_cell_num > 64) {

+ 2 - 2
core/iwasm/compilation/aot_emit_variable.c

@@ -26,7 +26,7 @@ get_local_type(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     local_type = local_idx < param_count
                      ? aot_func->func_type->types[local_idx]
-                     : aot_func->local_types[local_idx - param_count];
+                     : aot_func->local_types_wp[local_idx - param_count];
 
     if (comp_ctx->enable_gc && aot_is_type_gc_reftype(local_type))
         local_type = VALUE_TYPE_GC_REF;
@@ -83,7 +83,7 @@ aot_compile_op_set_or_tee_local(AOTCompContext *comp_ctx,
 
     if (comp_ctx->aot_frame) {
         /* Get the slot index */
-        n = comp_ctx->aot_frame->cur_wasm_func->local_offsets[local_idx];
+        n = func_ctx->aot_func->local_offsets[local_idx];
         bh_assert(comp_ctx->aot_frame->lp[n].type == local_type);
 
         switch (local_type) {

+ 2 - 2
core/iwasm/compilation/aot_llvm.c

@@ -1064,14 +1064,14 @@ create_local_variables(const AOTCompData *comp_data,
         LLVMValueRef local_value = NULL;
         snprintf(local_name, sizeof(local_name), "l%d",
                  aot_func_type->param_count + i);
-        local_type = TO_LLVM_TYPE(func->local_types[i]);
+        local_type = TO_LLVM_TYPE(func->local_types_wp[i]);
         func_ctx->locals[aot_func_type->param_count + i] =
             LLVMBuildAlloca(comp_ctx->builder, local_type, local_name);
         if (!func_ctx->locals[aot_func_type->param_count + i]) {
             aot_set_last_error("llvm build alloca failed.");
             return false;
         }
-        switch (func->local_types[i]) {
+        switch (func->local_types_wp[i]) {
             case VALUE_TYPE_I32:
                 local_value = I32_ZERO;
                 break;

+ 0 - 4
core/iwasm/compilation/aot_llvm.h

@@ -114,10 +114,6 @@ typedef struct AOTValueSlot {
 typedef struct AOTCompFrame {
     /* The current wasm module */
     WASMModule *cur_wasm_module;
-    /* The current wasm function */
-    WASMFunction *cur_wasm_func;
-    /* The current wasm function index */
-    uint32 cur_wasm_func_idx;
     /* The current compilation context */
     struct AOTCompContext *comp_ctx;
     /* The current function context */

+ 27 - 3
core/iwasm/interpreter/wasm.h

@@ -1030,10 +1030,13 @@ wasm_string_equal(const char *s1, const char *s2)
 }
 
 /**
- * Return the byte size of value type.
+ * Return the byte size of value type with specific pointer size.
+ *
+ * Note: Please use wasm_value_type_size for interpreter, only aot compiler
+ * can use this API directly to calculate type size for different target
  */
 inline static uint32
-wasm_value_type_size(uint8 value_type)
+wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
 {
     if (value_type == VALUE_TYPE_VOID)
         return 0;
@@ -1058,7 +1061,7 @@ wasm_value_type_size(uint8 value_type)
         value_type >= (uint8)REF_TYPE_NULLREF /* 0x65 */
 #endif
         && value_type <= (uint8)REF_TYPE_FUNCREF /* 0x70 */)
-        return sizeof(uintptr_t);
+        return pointer_size;
 #endif
     else {
         bh_assert(0);
@@ -1066,6 +1069,27 @@ wasm_value_type_size(uint8 value_type)
     return 0;
 }
 
+/**
+ * Return the cell num of value type with specific pointer size.
+ *
+ * Note: Please use wasm_value_type_cell_num for interpreter, only aot compiler
+ * can use this API directly to calculate type cell num for different target
+ */
+inline static uint16
+wasm_value_type_cell_num_internal(uint8 value_type, uint8 pointer_size)
+{
+    return wasm_value_type_size_internal(value_type, pointer_size) / 4;
+}
+
+/**
+ * Return the byte size of value type.
+ */
+inline static uint32
+wasm_value_type_size(uint8 value_type)
+{
+    return wasm_value_type_size_internal(value_type, sizeof(uintptr_t));
+}
+
 inline static uint16
 wasm_value_type_cell_num(uint8 value_type)
 {