Przeglądaj źródła

Fix issues in compile GC struct/array opcodes (#2652)

Wenyong Huang 2 lat temu
rodzic
commit
01627edba7

+ 12 - 10
core/iwasm/compilation/aot_compiler.c

@@ -166,7 +166,7 @@ store_value(AOTCompContext *comp_ctx, LLVMValueRef value, uint8 value_type,
             LLVMValueRef cur_frame, uint32 offset)
 {
     LLVMValueRef value_offset, value_addr, value_ptr = NULL, res;
-    LLVMTypeRef value_ptr_type;
+    LLVMTypeRef value_ptr_type = NULL;
 
     if (!(value_offset = I32_CONST(offset))) {
         aot_set_last_error("llvm build const failed");
@@ -710,15 +710,17 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                     || value_type == VALUE_TYPE_F64
                     || value_type == VALUE_TYPE_V128
                     || value_type == VALUE_TYPE_VOID
-                    || value_type == VALUE_TYPE_FUNCREF
-                    || value_type == VALUE_TYPE_EXTERNREF
-                    || value_type == REF_TYPE_STRUCTREF
-                    || value_type == REF_TYPE_ARRAYREF
-                    || value_type == REF_TYPE_I31REF
-                    || value_type == REF_TYPE_EQREF
-                    || value_type == REF_TYPE_ANYREF
-                    || value_type == REF_TYPE_HT_NULLABLE
-                    || value_type == REF_TYPE_HT_NON_NULLABLE) {
+                    || (comp_ctx->enable_ref_types
+                        && (value_type == VALUE_TYPE_FUNCREF
+                            || value_type == VALUE_TYPE_EXTERNREF))
+                    || (comp_ctx->enable_gc /* single byte type */
+                        && (value_type == REF_TYPE_FUNCREF
+                            || value_type == REF_TYPE_EXTERNREF
+                            || value_type == REF_TYPE_STRUCTREF
+                            || value_type == REF_TYPE_ARRAYREF
+                            || value_type == REF_TYPE_I31REF
+                            || value_type == REF_TYPE_EQREF
+                            || value_type == REF_TYPE_ANYREF))) {
                     param_count = 0;
                     param_types = NULL;
                     if (value_type == VALUE_TYPE_VOID) {

+ 39 - 15
core/iwasm/compilation/aot_compiler.h

@@ -79,8 +79,23 @@ typedef enum FloatArithmetic {
     FLOAT_MAX,
 } FloatArithmetic;
 
+/**
+ * Check whether a value type is a GC reference type,
+ * don't use wasm_is_type_reftype since it requires
+ * GC feature and may result in compilation error when
+ * GC feature isn't compiled
+ */
+static inline bool
+aot_is_type_gc_reftype(uint8 type)
+{
+    return (type >= (uint8)REF_TYPE_ARRAYREF && type <= (uint8)REF_TYPE_FUNCREF)
+               ? true
+               : false;
+}
+
 static inline bool
-check_type_compatible(uint8 src_type, uint8 dst_type)
+check_type_compatible(const AOTCompContext *comp_ctx, uint8 src_type,
+                      uint8 dst_type)
 {
     if (src_type == dst_type) {
         return true;
@@ -93,14 +108,16 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
 
     /* i32 <==> func.ref, i32 <==> extern.ref */
     if (src_type == VALUE_TYPE_I32
-        && (dst_type == VALUE_TYPE_EXTERNREF
-            || dst_type == VALUE_TYPE_FUNCREF)) {
+        && (comp_ctx->enable_ref_types
+            && (dst_type == VALUE_TYPE_EXTERNREF
+                || dst_type == VALUE_TYPE_FUNCREF))) {
         return true;
     }
 
     if (dst_type == VALUE_TYPE_I32
-        && (src_type == VALUE_TYPE_FUNCREF
-            || src_type == VALUE_TYPE_EXTERNREF)) {
+        && (comp_ctx->enable_ref_types
+            && (src_type == VALUE_TYPE_FUNCREF
+                || src_type == VALUE_TYPE_EXTERNREF))) {
         return true;
     }
 
@@ -426,34 +443,41 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define POP(llvm_value, value_type)                                          \
     do {                                                                     \
         AOTValue *aot_value;                                                 \
+        uint8 val_type_to_pop = value_type;                                  \
         CHECK_STACK();                                                       \
         aot_value = aot_value_stack_pop(                                     \
             comp_ctx, &func_ctx->block_stack.block_list_end->value_stack);   \
-        if (!check_type_compatible(aot_value->type, value_type)) {           \
+        if (comp_ctx->enable_gc && aot_is_type_gc_reftype(value_type))       \
+            val_type_to_pop = VALUE_TYPE_GC_REF;                             \
+        if (!check_type_compatible(comp_ctx, aot_value->type,                \
+                                   val_type_to_pop)) {                       \
             aot_set_last_error("invalid WASM stack data type.");             \
             wasm_runtime_free(aot_value);                                    \
             goto fail;                                                       \
         }                                                                    \
-        if (aot_value->type == value_type)                                   \
+        if (aot_value->type == val_type_to_pop)                              \
             llvm_value = aot_value->value;                                   \
         else {                                                               \
             if (aot_value->type == VALUE_TYPE_I1) {                          \
                 if (!(llvm_value =                                           \
                           LLVMBuildZExt(comp_ctx->builder, aot_value->value, \
                                         I32_TYPE, "i1toi32"))) {             \
-                    aot_set_last_error("invalid WASM stack "                 \
-                                       "data type.");                        \
+                    aot_set_last_error("invalid WASM stack data type.");     \
                     wasm_runtime_free(aot_value);                            \
                     goto fail;                                               \
                 }                                                            \
             }                                                                \
             else {                                                           \
-                bh_assert(aot_value->type == VALUE_TYPE_I32                  \
-                          || aot_value->type == VALUE_TYPE_FUNCREF           \
-                          || aot_value->type == VALUE_TYPE_EXTERNREF);       \
-                bh_assert(value_type == VALUE_TYPE_I32                       \
-                          || value_type == VALUE_TYPE_FUNCREF                \
-                          || value_type == VALUE_TYPE_EXTERNREF);            \
+                bh_assert(                                                   \
+                    aot_value->type == VALUE_TYPE_I32                        \
+                    || (comp_ctx->enable_ref_types                           \
+                        && (aot_value->type == VALUE_TYPE_FUNCREF            \
+                            || aot_value->type == VALUE_TYPE_EXTERNREF)));   \
+                bh_assert(                                                   \
+                    val_type_to_pop == VALUE_TYPE_I32                        \
+                    || (comp_ctx->enable_ref_types                           \
+                        && (val_type_to_pop == VALUE_TYPE_FUNCREF            \
+                            || val_type_to_pop == VALUE_TYPE_EXTERNREF)));   \
                 llvm_value = aot_value->value;                               \
             }                                                                \
         }                                                                    \

+ 160 - 84
core/iwasm/compilation/aot_emit_gc.c

@@ -287,36 +287,71 @@ fail:
     return false;
 }
 
+static void
+get_struct_field_data_types(const AOTCompContext *comp_ctx, uint8 field_type,
+                            LLVMTypeRef *p_field_data_type,
+                            LLVMTypeRef *p_field_data_ptr_type,
+                            bool *p_trunc_or_extend)
+{
+    LLVMTypeRef field_data_type = NULL, field_data_ptr_type = NULL;
+    bool trunc_or_extend = false;
+
+    if (wasm_is_type_reftype(field_type)) {
+        field_data_type = GC_REF_TYPE;
+        field_data_ptr_type = GC_REF_PTR_TYPE;
+    }
+    else {
+        switch (field_type) {
+            case VALUE_TYPE_I32:
+                field_data_type = I32_TYPE;
+                field_data_ptr_type = INT32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_I64:
+                field_data_type = I64_TYPE;
+                field_data_ptr_type = INT64_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F32:
+                field_data_type = F32_TYPE;
+                field_data_ptr_type = F32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F64:
+                field_data_type = F64_TYPE;
+                field_data_ptr_type = F64_PTR_TYPE;
+                break;
+            case PACKED_TYPE_I8:
+                field_data_type = INT8_TYPE;
+                field_data_ptr_type = INT8_PTR_TYPE;
+                trunc_or_extend = true;
+                break;
+            case PACKED_TYPE_I16:
+                field_data_type = INT16_TYPE;
+                field_data_ptr_type = INT16_PTR_TYPE;
+                trunc_or_extend = true;
+                break;
+            default:
+                bh_assert(0);
+                break;
+        }
+    }
+
+    *p_field_data_type = field_data_type;
+    *p_field_data_ptr_type = field_data_ptr_type;
+    *p_trunc_or_extend = trunc_or_extend;
+}
+
 static bool
 aot_struct_obj_set_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
                          LLVMValueRef field_offset, LLVMValueRef field_value,
-                         uint8 field_size)
+                         uint8 field_type)
 {
     bool trunc = false;
     LLVMValueRef field_data_ptr;
-    LLVMTypeRef field_data_type = NULL;
+    LLVMTypeRef field_data_type = NULL, field_data_ptr_type = NULL;
 
-    switch (field_size) {
-        case 1:
-            field_data_type = INT8_TYPE;
-            trunc = true;
-            break;
-        case 2:
-            field_data_type = INT16_TYPE;
-            trunc = true;
-            break;
-        case 4:
-            field_data_type = I32_TYPE;
-            break;
-        case 8:
-            field_data_type = I64_TYPE;
-            break;
-        default:
-            bh_assert(0);
-            break;
-    }
+    get_struct_field_data_types(comp_ctx, field_type, &field_data_type,
+                                &field_data_ptr_type, &trunc);
 
-    /* Based on field_size, trunc field_value if necessary */
+    /* Truncate field_value if necessary */
     if (trunc) {
         if (!(field_value =
                   LLVMBuildTrunc(comp_ctx->builder, field_value,
@@ -335,9 +370,9 @@ aot_struct_obj_set_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
     }
 
     /* Cast to the field data type ptr */
-    if (!(field_data_ptr = LLVMBuildBitCast(comp_ctx->builder, field_data_ptr,
-                                            LLVMPointerType(field_data_type, 0),
-                                            "field_value_ptr"))) {
+    if (!(field_data_ptr =
+              LLVMBuildBitCast(comp_ctx->builder, field_data_ptr,
+                               field_data_ptr_type, "field_value_ptr"))) {
         aot_set_last_error("llvm build bitcast failed.");
         goto fail;
     }
@@ -354,12 +389,15 @@ fail:
 
 static bool
 aot_struct_obj_get_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
-                         LLVMValueRef field_offset, LLVMValueRef *field_value,
-                         uint8 field_size, bool sign_extend)
+                         LLVMValueRef field_offset, LLVMValueRef *p_field_value,
+                         uint8 field_type, bool sign_extend)
 {
     bool extend = false;
-    LLVMValueRef field_data_ptr;
-    LLVMTypeRef field_data_type = NULL;
+    LLVMValueRef field_value, field_data_ptr;
+    LLVMTypeRef field_data_type = NULL, field_data_ptr_type = NULL;
+
+    get_struct_field_data_types(comp_ctx, field_type, &field_data_type,
+                                &field_data_ptr_type, &extend);
 
     if (!(field_data_ptr = LLVMBuildInBoundsGEP2(
               comp_ctx->builder, INT8_PTR_TYPE, struct_obj, &field_offset, 1,
@@ -368,56 +406,37 @@ aot_struct_obj_get_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
         goto fail;
     }
 
-    switch (field_size) {
-        case 1:
-            field_data_type = INT8_TYPE;
-            extend = true;
-            break;
-        case 2:
-            field_data_type = INT16_TYPE;
-            extend = true;
-            break;
-        case 4:
-            field_data_type = I32_TYPE;
-            break;
-        case 8:
-            field_data_type = I64_TYPE;
-            break;
-        default:
-            bh_assert(0);
-            break;
-    }
-
-    if (!(field_data_ptr = LLVMBuildBitCast(comp_ctx->builder, field_data_ptr,
-                                            LLVMPointerType(field_data_type, 0),
-                                            "field_value_ptr"))) {
+    if (!(field_data_ptr =
+              LLVMBuildBitCast(comp_ctx->builder, field_data_ptr,
+                               field_data_ptr_type, "field_value_ptr"))) {
         aot_set_last_error("llvm build bitcast failed.");
         goto fail;
     }
 
-    if (!(*field_value = LLVMBuildLoad2(comp_ctx->builder, field_data_type,
-                                        field_data_ptr, "field_value"))) {
+    if (!(field_value = LLVMBuildLoad2(comp_ctx->builder, field_data_type,
+                                       field_data_ptr, "field_value"))) {
         aot_set_last_error("llvm build load failed.");
         goto fail;
     }
 
     if (extend) {
         if (sign_extend) {
-            if (!(*field_value = LLVMBuildSExt(comp_ctx->builder, *field_value,
-                                               I32_TYPE, "field_value_sext"))) {
+            if (!(field_value = LLVMBuildSExt(comp_ctx->builder, field_value,
+                                              I32_TYPE, "field_value_sext"))) {
                 aot_set_last_error("llvm build signed ext failed.");
                 goto fail;
             }
         }
         else {
-            if (!(*field_value = LLVMBuildZExt(comp_ctx->builder, *field_value,
-                                               I32_TYPE, "field_value_zext"))) {
+            if (!(field_value = LLVMBuildZExt(comp_ctx->builder, field_value,
+                                              I32_TYPE, "field_value_zext"))) {
                 aot_set_last_error("llvm build unsigned ext failed.");
                 goto fail;
             }
         }
     }
 
+    *p_field_value = field_value;
     return true;
 fail:
     return false;
@@ -435,28 +454,35 @@ struct_new_canon_init_fields(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     WASMStructFieldType *fields = compile_time_struct_type->fields;
     int32 field_count = (int32)compile_time_struct_type->field_count;
     int32 field_idx;
-    uint8 field_type, field_size, field_offset;
+    uint8 field_type, field_offset;
 
     for (field_idx = field_count - 1; field_idx >= 0; field_idx--) {
         field_type = fields[field_idx].field_type;
-        field_size = fields[field_idx].field_size;
         field_offset = fields[field_idx].field_offset;
 
         if (wasm_is_type_reftype(field_type)) {
             POP_GC_REF(field_value);
         }
-        else if (field_type == VALUE_TYPE_I32 || field_type == VALUE_TYPE_F32
-                 || field_type == PACKED_TYPE_I8
+        else if (field_type == VALUE_TYPE_I32 || field_type == PACKED_TYPE_I8
                  || field_type == PACKED_TYPE_I16) {
             POP_I32(field_value);
         }
-        else {
+        else if (field_type == VALUE_TYPE_I64) {
             POP_I64(field_value);
         }
+        else if (field_type == VALUE_TYPE_F32) {
+            POP_F32(field_value);
+        }
+        else if (field_type == VALUE_TYPE_F64) {
+            POP_F64(field_value);
+        }
+        else {
+            bh_assert(0);
+        }
 
         if (!aot_struct_obj_set_field(comp_ctx, struct_obj,
                                       I32_CONST(field_offset), field_value,
-                                      field_size))
+                                      field_type))
             goto fail;
     }
 
@@ -498,6 +524,8 @@ aot_compile_op_struct_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             check_struct_obj_succ))
         goto fail;
 
+    SET_BUILDER_POS(check_struct_obj_succ);
+
     /* For WASM_OP_STRUCT_NEW_CANON, init filed with poped value */
     if (!init_with_default
         && !struct_new_canon_init_fields(comp_ctx, func_ctx, type_index,
@@ -524,11 +552,10 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     WASMStructType *compile_time_struct_type =
         (WASMStructType *)comp_ctx->comp_data->types[type_index];
     WASMStructFieldType *field;
-    uint8 field_type, field_size, field_offset;
+    uint8 field_type, field_offset;
 
     field = compile_time_struct_type->fields + field_idx;
     field_type = field->field_type;
-    field_size = field->field_size;
     field_offset = field->field_offset;
 
     if (field_idx >= compile_time_struct_type->field_count) {
@@ -547,19 +574,28 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
 
     if (!aot_struct_obj_get_field(comp_ctx, struct_obj, I32_CONST(field_offset),
-                                  &field_value, field_size, sign))
+                                  &field_value, field_type, sign))
         goto fail;
 
     if (wasm_is_type_reftype(field_type)) {
         PUSH_GC_REF(field_value);
     }
-    else if (field_type == VALUE_TYPE_I32 || field_type == VALUE_TYPE_F32
-             || field_type == PACKED_TYPE_I8 || field_type == PACKED_TYPE_I16) {
+    else if (field_type == VALUE_TYPE_I32 || field_type == PACKED_TYPE_I8
+             || field_type == PACKED_TYPE_I16) {
         PUSH_I32(field_value);
     }
-    else {
+    else if (field_type == VALUE_TYPE_I64) {
         PUSH_I64(field_value);
     }
+    else if (field_type == VALUE_TYPE_F32) {
+        PUSH_F32(field_value);
+    }
+    else if (field_type == VALUE_TYPE_F64) {
+        PUSH_F64(field_value);
+    }
+    else {
+        bh_assert(0);
+    }
 
     return true;
 fail:
@@ -577,11 +613,10 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     WASMStructType *compile_time_struct_type =
         (WASMStructType *)comp_ctx->comp_data->types[type_index];
     WASMStructFieldType *field;
-    uint8 field_type, field_size, field_offset;
+    uint8 field_type, field_offset;
 
     field = compile_time_struct_type->fields + field_idx;
     field_type = field->field_type;
-    field_size = field->field_size;
     field_offset = field->field_offset;
 
     if (field_idx >= compile_time_struct_type->field_count) {
@@ -592,13 +627,22 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     if (wasm_is_type_reftype(field_type)) {
         POP_GC_REF(field_value);
     }
-    else if (field_type == VALUE_TYPE_I32 || field_type == VALUE_TYPE_F32
-             || field_type == PACKED_TYPE_I8 || field_type == PACKED_TYPE_I16) {
+    else if (field_type == VALUE_TYPE_I32 || field_type == PACKED_TYPE_I8
+             || field_type == PACKED_TYPE_I16) {
         POP_I32(field_value);
     }
-    else {
+    else if (field_type == VALUE_TYPE_I64) {
         POP_I64(field_value);
     }
+    else if (field_type == VALUE_TYPE_F32) {
+        POP_F32(field_value);
+    }
+    else if (field_type == VALUE_TYPE_F64) {
+        POP_F64(field_value);
+    }
+    else {
+        bh_assert(0);
+    }
 
     POP_GC_REF(struct_obj);
 
@@ -611,7 +655,7 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
 
     if (!aot_struct_obj_set_field(comp_ctx, struct_obj, I32_CONST(field_offset),
-                                  field_value, field_size))
+                                  field_value, field_type))
         goto fail;
 
     return true;
@@ -1031,14 +1075,22 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             POP_GC_REF(array_elem);
         }
         else if (array_elem_type == VALUE_TYPE_I32
-                 || array_elem_type == VALUE_TYPE_F32
                  || array_elem_type == PACKED_TYPE_I8
                  || array_elem_type == PACKED_TYPE_I16) {
             POP_I32(array_elem);
         }
-        else {
+        else if (array_elem_type == VALUE_TYPE_I64) {
             POP_I64(array_elem);
         }
+        else if (array_elem_type == VALUE_TYPE_F32) {
+            POP_F32(array_elem);
+        }
+        else if (array_elem_type == VALUE_TYPE_F64) {
+            POP_F64(array_elem);
+        }
+        else {
+            bh_assert(0);
+        }
     }
     else {
         /* I64 will alloca large enough space for all union access includes
@@ -1065,14 +1117,22 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 POP_GC_REF(array_elem);
             }
             else if (array_elem_type == VALUE_TYPE_I32
-                     || array_elem_type == VALUE_TYPE_F32
                      || array_elem_type == PACKED_TYPE_I8
                      || array_elem_type == PACKED_TYPE_I16) {
                 POP_I32(array_elem);
             }
-            else {
+            else if (array_elem_type == VALUE_TYPE_I64) {
                 POP_I64(array_elem);
             }
+            else if (array_elem_type == VALUE_TYPE_F32) {
+                POP_F32(array_elem);
+            }
+            else if (array_elem_type == VALUE_TYPE_F64) {
+                POP_F64(array_elem);
+            }
+            else {
+                bh_assert(0);
+            }
 
             /* array_len - 1 - i */
             if (!(elem_idx = LLVMBuildSub(comp_ctx->builder, array_length,
@@ -1213,14 +1273,22 @@ aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         PUSH_GC_REF(array_elem);
     }
     else if (array_elem_type == VALUE_TYPE_I32
-             || array_elem_type == VALUE_TYPE_F32
              || array_elem_type == PACKED_TYPE_I8
              || array_elem_type == PACKED_TYPE_I16) {
         PUSH_I32(array_elem);
     }
-    else {
+    else if (array_elem_type == VALUE_TYPE_I64) {
         PUSH_I64(array_elem);
     }
+    else if (array_elem_type == VALUE_TYPE_F32) {
+        PUSH_F32(array_elem);
+    }
+    else if (array_elem_type == VALUE_TYPE_F64) {
+        PUSH_F64(array_elem);
+    }
+    else {
+        bh_assert(0);
+    }
 
     return true;
 fail:
@@ -1243,14 +1311,22 @@ aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         POP_GC_REF(array_elem);
     }
     else if (array_elem_type == VALUE_TYPE_I32
-             || array_elem_type == VALUE_TYPE_F32
              || array_elem_type == PACKED_TYPE_I8
              || array_elem_type == PACKED_TYPE_I16) {
         POP_I32(array_elem);
     }
-    else {
+    else if (array_elem_type == VALUE_TYPE_I64) {
         POP_I64(array_elem);
     }
+    else if (array_elem_type == VALUE_TYPE_F32) {
+        POP_F32(array_elem);
+    }
+    else if (array_elem_type == VALUE_TYPE_F64) {
+        POP_F64(array_elem);
+    }
+    else {
+        bh_assert(0);
+    }
 
     POP_I32(elem_idx);
     POP_GC_REF(array_obj);

+ 19 - 9
core/iwasm/compilation/aot_emit_variable.c

@@ -28,10 +28,8 @@ get_local_type(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                      ? aot_func->func_type->types[local_idx]
                      : aot_func->local_types[local_idx - param_count];
 
-#if WASM_ENABLE_GC != 0
-    if (comp_ctx->enable_gc && wasm_is_type_reftype(local_type))
+    if (comp_ctx->enable_gc && aot_is_type_gc_reftype(local_type))
         local_type = VALUE_TYPE_GC_REF;
-#endif
 
     return local_type;
 }
@@ -107,7 +105,11 @@ aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             case VALUE_TYPE_EXTERNREF:
                 set_local_ref(comp_ctx->aot_frame, n, value, local_type);
                 break;
-            /* TODO: handle GC ref types */
+#if WASM_ENABLE_GC != 0
+            case VALUE_TYPE_GC_REF:
+                set_local_gc_ref(comp_ctx->aot_frame, n, value, local_type);
+                break;
+#endif
             default:
                 bh_assert(0);
                 break;
@@ -184,6 +186,9 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         global_type = comp_data->globals[global_idx - import_global_count].type;
     }
 
+    if (comp_ctx->enable_gc && aot_is_type_gc_reftype(global_type))
+        global_type = VALUE_TYPE_GC_REF;
+
     offset = I32_CONST(global_offset);
     if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
                                              func_ctx->aot_inst, &offset, 1,
@@ -196,20 +201,25 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         case VALUE_TYPE_I32:
         case VALUE_TYPE_EXTERNREF:
         case VALUE_TYPE_FUNCREF:
-            ptr_type = comp_ctx->basic_types.int32_ptr_type;
+            ptr_type = INT32_PTR_TYPE;
             break;
         case VALUE_TYPE_I64:
-            ptr_type = comp_ctx->basic_types.int64_ptr_type;
+            ptr_type = INT64_PTR_TYPE;
             break;
         case VALUE_TYPE_F32:
-            ptr_type = comp_ctx->basic_types.float32_ptr_type;
+            ptr_type = F32_PTR_TYPE;
             break;
         case VALUE_TYPE_F64:
-            ptr_type = comp_ctx->basic_types.float64_ptr_type;
+            ptr_type = F64_PTR_TYPE;
             break;
         case VALUE_TYPE_V128:
-            ptr_type = comp_ctx->basic_types.v128_ptr_type;
+            ptr_type = V128_PTR_TYPE;
+            break;
+#if WASM_ENABLE_GC != 0
+        case VALUE_TYPE_GC_REF:
+            ptr_type = GC_REF_PTR_TYPE;
             break;
+#endif
         default:
             bh_assert("unknown type");
             break;

+ 21 - 5
core/iwasm/compilation/aot_llvm.c

@@ -589,10 +589,7 @@ check_wasm_type(AOTCompContext *comp_ctx, uint8 type)
         else
             return true;
     }
-    else if (type == REF_TYPE_STRUCTREF || type == REF_TYPE_ARRAYREF
-             || type == REF_TYPE_I31REF || type == REF_TYPE_EQREF
-             || type == REF_TYPE_ANYREF || type == REF_TYPE_HT_NULLABLE
-             || type == REF_TYPE_HT_NON_NULLABLE) {
+    else if (aot_is_type_gc_reftype(type)) {
         if (!comp_ctx->enable_gc) {
             aot_set_last_error("GC reference type was found, "
                                "try adding --enable-gc option.");
@@ -3456,8 +3453,27 @@ aot_build_zero_function_ret(const AOTCompContext *comp_ctx,
                 break;
             case VALUE_TYPE_FUNCREF:
             case VALUE_TYPE_EXTERNREF:
-                ret = LLVMBuildRet(comp_ctx->builder, REF_NULL);
+                if (comp_ctx->enable_ref_types)
+                    ret = LLVMBuildRet(comp_ctx->builder, REF_NULL);
+#if WASM_ENABLE_GC != 0
+                else if (comp_ctx->enable_gc)
+                    ret = LLVMBuildRet(comp_ctx->builder, GC_REF_NULL);
+#endif
+                else
+                    bh_assert(0);
+                break;
+#if WASM_ENABLE_GC != 0
+            case REF_TYPE_STRUCTREF:
+            case REF_TYPE_ARRAYREF:
+            case REF_TYPE_I31REF:
+            case REF_TYPE_EQREF:
+            case REF_TYPE_ANYREF:
+            case REF_TYPE_HT_NULLABLE:
+            case REF_TYPE_HT_NON_NULLABLE:
+                bh_assert(comp_ctx->enable_gc);
+                ret = LLVMBuildRet(comp_ctx->builder, GC_REF_NULL);
                 break;
+#endif
             default:
                 bh_assert(0);
         }