|
|
@@ -241,7 +241,7 @@ aot_compile_op_ref_as_non_null(AOTCompContext *comp_ctx,
|
|
|
LLVMValueRef gc_obj, cmp_gc_obj;
|
|
|
LLVMBasicBlockRef check_gc_obj_succ;
|
|
|
|
|
|
- GET_REF_FROM_STACK(gc_obj);
|
|
|
+ GET_GC_REF_FROM_STACK(gc_obj);
|
|
|
|
|
|
/* Check if gc object is NULL */
|
|
|
BUILD_ISNULL(gc_obj, cmp_gc_obj, "cmp_gc_obj");
|
|
|
@@ -443,7 +443,7 @@ struct_new_canon_init_fields(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
field_offset = fields[field_idx].field_offset;
|
|
|
|
|
|
if (wasm_is_type_reftype(field_type)) {
|
|
|
- POP_REF(field_value);
|
|
|
+ POP_GC_REF(field_value);
|
|
|
}
|
|
|
else if (field_type == VALUE_TYPE_I32 || field_type == VALUE_TYPE_F32
|
|
|
|| field_type == PACKED_TYPE_I8
|
|
|
@@ -505,7 +505,7 @@ aot_compile_op_struct_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- PUSH_REF(struct_obj);
|
|
|
+ PUSH_GC_REF(struct_obj);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -536,7 +536,7 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- POP_REF(struct_obj);
|
|
|
+ POP_GC_REF(struct_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_struct_obj_succ, "check struct obj succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_struct_obj_succ);
|
|
|
@@ -551,7 +551,7 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
goto fail;
|
|
|
|
|
|
if (wasm_is_type_reftype(field_type)) {
|
|
|
- PUSH_REF(field_value);
|
|
|
+ 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) {
|
|
|
@@ -590,7 +590,7 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
|
|
|
if (wasm_is_type_reftype(field_type)) {
|
|
|
- POP_REF(field_value);
|
|
|
+ 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) {
|
|
|
@@ -600,7 +600,7 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
POP_I64(field_value);
|
|
|
}
|
|
|
|
|
|
- POP_REF(struct_obj);
|
|
|
+ POP_GC_REF(struct_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_struct_obj_succ, "check struct obj succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_struct_obj_succ);
|
|
|
@@ -1028,7 +1028,7 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
/* For WASM_OP_ARRAY_NEW_CANON */
|
|
|
if (!fixed_size && !init_with_default) {
|
|
|
if (wasm_is_type_reftype(array_elem_type)) {
|
|
|
- POP_REF(array_elem);
|
|
|
+ POP_GC_REF(array_elem);
|
|
|
}
|
|
|
else if (array_elem_type == VALUE_TYPE_I32
|
|
|
|| array_elem_type == VALUE_TYPE_F32
|
|
|
@@ -1062,7 +1062,7 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
if (fixed_size) {
|
|
|
for (i = 0; i < array_len; i++) {
|
|
|
if (wasm_is_type_reftype(array_elem_type)) {
|
|
|
- POP_REF(array_elem);
|
|
|
+ POP_GC_REF(array_elem);
|
|
|
}
|
|
|
else if (array_elem_type == VALUE_TYPE_I32
|
|
|
|| array_elem_type == VALUE_TYPE_F32
|
|
|
@@ -1087,7 +1087,7 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- PUSH_REF(array_obj);
|
|
|
+ PUSH_GC_REF(array_obj);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -1165,7 +1165,7 @@ aot_compile_op_array_new_data(AOTCompContext *comp_ctx,
|
|
|
array_obj, elem_size, array_length))
|
|
|
goto fail;
|
|
|
|
|
|
- PUSH_REF(array_obj);
|
|
|
+ PUSH_GC_REF(array_obj);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -1184,7 +1184,7 @@ aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
uint8 array_elem_type = compile_time_array_type->elem_type;
|
|
|
|
|
|
POP_I32(elem_idx);
|
|
|
- POP_REF(array_obj);
|
|
|
+ POP_GC_REF(array_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_array_obj_succ, "check array obj succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
|
|
|
@@ -1210,7 +1210,7 @@ aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
goto fail;
|
|
|
|
|
|
if (wasm_is_type_reftype(array_elem_type)) {
|
|
|
- PUSH_REF(array_elem);
|
|
|
+ PUSH_GC_REF(array_elem);
|
|
|
}
|
|
|
else if (array_elem_type == VALUE_TYPE_I32
|
|
|
|| array_elem_type == VALUE_TYPE_F32
|
|
|
@@ -1240,7 +1240,7 @@ aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
|
|
|
/* Get LLVM type based on array_elem_type */
|
|
|
if (wasm_is_type_reftype(array_elem_type)) {
|
|
|
- POP_REF(array_elem);
|
|
|
+ POP_GC_REF(array_elem);
|
|
|
}
|
|
|
else if (array_elem_type == VALUE_TYPE_I32
|
|
|
|| array_elem_type == VALUE_TYPE_F32
|
|
|
@@ -1253,7 +1253,7 @@ aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
|
|
|
POP_I32(elem_idx);
|
|
|
- POP_REF(array_obj);
|
|
|
+ POP_GC_REF(array_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_array_obj_succ, "check array obj succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
|
|
|
@@ -1336,9 +1336,9 @@ aot_compile_op_array_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
|
|
|
POP_I32(len);
|
|
|
POP_I32(src_offset);
|
|
|
- POP_REF(src_obj);
|
|
|
+ POP_GC_REF(src_obj);
|
|
|
POP_I32(dst_offset);
|
|
|
- POP_REF(dst_obj);
|
|
|
+ POP_GC_REF(dst_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_objs_succ, "check array objs succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_objs_succ);
|
|
|
@@ -1423,7 +1423,7 @@ aot_compile_op_array_len(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|
|
LLVMValueRef array_obj, cmp, array_len;
|
|
|
LLVMBasicBlockRef check_array_obj_succ;
|
|
|
|
|
|
- POP_REF(array_obj);
|
|
|
+ POP_GC_REF(array_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_array_obj_succ, "check array obj succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
|
|
|
@@ -1452,28 +1452,34 @@ aot_compile_op_i31_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|
|
|
|
|
/* Equivalent to wasm_i31_obj_new: ((i31_value << 1) | 1) */
|
|
|
if (!(i31_obj = LLVMBuildShl(comp_ctx->builder, i31_val, I32_ONE,
|
|
|
- "i31_value << 1"))) {
|
|
|
+ "i31_val_shl"))) {
|
|
|
aot_set_last_error("llvm build shl failed.");
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- if (!(i31_obj = LLVMBuildOr(comp_ctx->builder, i31_obj, I32_ONE,
|
|
|
- "((i31_value << 1) | 1)"))) {
|
|
|
+ if (!(i31_obj =
|
|
|
+ LLVMBuildOr(comp_ctx->builder, i31_obj, I32_ONE, "i31_val_or"))) {
|
|
|
aot_set_last_error("llvm build or failed.");
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
/* if uintptr_t is 64 bits, extend i32 to i64, equivalent to:
|
|
|
- * (WASMI31ObjectRef)((i31_value << 1) | 1) */
|
|
|
+ (WASMI31ObjectRef)((i31_value << 1) | 1) */
|
|
|
if (comp_ctx->pointer_size == sizeof(uint64)) {
|
|
|
if (!(i31_obj = LLVMBuildZExt(comp_ctx->builder, i31_obj, I64_TYPE,
|
|
|
- "extend i32 to uintptr_t"))) {
|
|
|
+ "i31_val_zext"))) {
|
|
|
aot_set_last_error("llvm build zext failed.");
|
|
|
goto fail;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- PUSH_REF(i31_obj);
|
|
|
+ if (!(i31_obj = LLVMBuildIntToPtr(comp_ctx->builder, i31_obj, GC_REF_TYPE,
|
|
|
+ "i31_obj"))) {
|
|
|
+ aot_set_last_error("llvm build bit cast failed.");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ PUSH_GC_REF(i31_obj);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -1488,7 +1494,7 @@ aot_compile_op_i31_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
i31_sign_val;
|
|
|
LLVMBasicBlockRef check_i31_obj_succ;
|
|
|
|
|
|
- POP_REF(i31_obj);
|
|
|
+ POP_GC_REF(i31_obj);
|
|
|
|
|
|
ADD_BASIC_BLOCK(check_i31_obj_succ, "check_i31_obj_succ");
|
|
|
MOVE_BLOCK_AFTER_CURR(check_i31_obj_succ);
|
|
|
@@ -1548,83 +1554,125 @@ fail:
|
|
|
|
|
|
bool
|
|
|
aot_compile_op_ref_test(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
- int32 heap_type, bool nullable, bool cast)
|
|
|
+ int32 heap_type, bool nullable)
|
|
|
{
|
|
|
- LLVMValueRef gc_obj, cmp, castable;
|
|
|
- LLVMBasicBlockRef gc_obj_null, gc_obj_non_null, end_block;
|
|
|
+ LLVMValueRef gc_obj, ref_test_phi, cmp, castable;
|
|
|
+ LLVMBasicBlockRef block_curr, block_obj_non_null, block_end;
|
|
|
|
|
|
- GET_REF_FROM_STACK(gc_obj);
|
|
|
+ POP_GC_REF(gc_obj);
|
|
|
|
|
|
- /* Create if block */
|
|
|
- ADD_BASIC_BLOCK(gc_obj_null, "gc_obj_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(gc_obj_null);
|
|
|
+ block_curr = CURR_BLOCK();
|
|
|
|
|
|
- /* Create else block */
|
|
|
- ADD_BASIC_BLOCK(gc_obj_non_null, "gc_obj_non_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(gc_obj_non_null);
|
|
|
+ /* Create non-null object block */
|
|
|
+ ADD_BASIC_BLOCK(block_obj_non_null, "non_null_obj");
|
|
|
+ MOVE_BLOCK_AFTER_CURR(block_obj_non_null);
|
|
|
|
|
|
/* Create end block */
|
|
|
- ADD_BASIC_BLOCK(end_block, "end_block");
|
|
|
- MOVE_BLOCK_AFTER_CURR(end_block);
|
|
|
+ ADD_BASIC_BLOCK(block_end, "ref_test_end");
|
|
|
+ MOVE_BLOCK_AFTER(block_end, block_obj_non_null);
|
|
|
+
|
|
|
+ /* Create ref test result phi */
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ if (!(ref_test_phi =
|
|
|
+ LLVMBuildPhi(comp_ctx->builder, INT1_TYPE, "ref_test_res"))) {
|
|
|
+ aot_set_last_error("llvm build phi failed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
/* Check if gc object is NULL */
|
|
|
+ SET_BUILDER_POS(block_curr);
|
|
|
BUILD_ISNULL(gc_obj, cmp, "cmp_gc_obj");
|
|
|
- BUILD_COND_BR(cmp, gc_obj_null, gc_obj_non_null);
|
|
|
+ BUILD_COND_BR(cmp, block_end, block_obj_non_null);
|
|
|
|
|
|
- /* Move builder to gc_obj NULL block */
|
|
|
- SET_BUILDER_POS(gc_obj_null);
|
|
|
- if (!cast) {
|
|
|
- /* For WASM_OP_REF_TEST and WASM_OP_REF_TEST_NULLABLE */
|
|
|
- if (nullable)
|
|
|
- PUSH_I32(I32_ONE);
|
|
|
- else
|
|
|
- PUSH_I32(I32_ZERO);
|
|
|
- }
|
|
|
- else {
|
|
|
- /* For WASM_OP_REF_CAST, exception */
|
|
|
- if (!nullable
|
|
|
- && !aot_emit_exception(comp_ctx, func_ctx, EXCE_TYPE_NONCASTABLE,
|
|
|
- false, NULL, NULL))
|
|
|
- goto fail;
|
|
|
- /* For WASM_OP_REF_CAST_NULLABLE, do nothing */
|
|
|
- }
|
|
|
+ if (nullable)
|
|
|
+ LLVMAddIncoming(ref_test_phi, &I1_ZERO, &block_curr, 1);
|
|
|
+ else
|
|
|
+ LLVMAddIncoming(ref_test_phi, &I1_ONE, &block_curr, 1);
|
|
|
|
|
|
- BUILD_BR(end_block);
|
|
|
+ /* Move builder to non-null object block */
|
|
|
+ SET_BUILDER_POS(block_obj_non_null);
|
|
|
|
|
|
- /* Move builder to gc_obj not NULL block */
|
|
|
- SET_BUILDER_POS(gc_obj_non_null);
|
|
|
if (heap_type >= 0) {
|
|
|
if (!aot_call_aot_obj_is_instance_of(comp_ctx, func_ctx, gc_obj,
|
|
|
I32_CONST(heap_type), &castable))
|
|
|
- goto fail;
|
|
|
+ return false;
|
|
|
}
|
|
|
else {
|
|
|
if (!aot_call_wasm_obj_is_type_of(comp_ctx, func_ctx, gc_obj,
|
|
|
I32_CONST(heap_type), &castable))
|
|
|
- goto fail;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- if (!(castable = LLVMBuildZExt(comp_ctx->builder, castable, I32_TYPE,
|
|
|
- "castable_i32"))) {
|
|
|
- aot_set_last_error("llvm build zext failed.");
|
|
|
- goto fail;
|
|
|
+ if (!(castable = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, castable,
|
|
|
+ I8_ZERO, "castable"))) {
|
|
|
+ aot_set_last_error("llvm build icmp failed.");
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- if (!cast) {
|
|
|
- /* For WASM_OP_REF_TEST and WASM_OP_REF_TEST_NULLABLE */
|
|
|
- PUSH_I32(castable);
|
|
|
- BUILD_BR(end_block);
|
|
|
+ BUILD_BR(block_end);
|
|
|
+ LLVMAddIncoming(ref_test_phi, &castable, &block_obj_non_null, 1);
|
|
|
+
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ PUSH_COND(ref_test_phi);
|
|
|
+
|
|
|
+ return true;
|
|
|
+fail:
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool
|
|
|
+aot_compile_op_ref_cast(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
+ int32 heap_type, bool nullable)
|
|
|
+{
|
|
|
+ LLVMValueRef gc_obj, cmp, castable;
|
|
|
+ LLVMBasicBlockRef block_obj_non_null, block_end;
|
|
|
+
|
|
|
+ GET_GC_REF_FROM_STACK(gc_obj);
|
|
|
+
|
|
|
+ /* Create non null block */
|
|
|
+ ADD_BASIC_BLOCK(block_obj_non_null, "non_null_obj");
|
|
|
+ MOVE_BLOCK_AFTER_CURR(block_obj_non_null);
|
|
|
+
|
|
|
+ /* Create end block */
|
|
|
+ ADD_BASIC_BLOCK(block_end, "ref_cast_end");
|
|
|
+ MOVE_BLOCK_AFTER(block_end, block_obj_non_null);
|
|
|
+
|
|
|
+ BUILD_ISNULL(gc_obj, cmp, "obj_is_null");
|
|
|
+ if (nullable) {
|
|
|
+ BUILD_COND_BR(cmp, block_end, block_obj_non_null);
|
|
|
}
|
|
|
else {
|
|
|
- /* For WASM_OP_REF_CAST and WASM_OP_REF_CAST_NULLABLE */
|
|
|
- BUILD_ICMP(LLVMIntEQ, castable, I32_ZERO, cmp, "cmp_castable");
|
|
|
if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_TYPE_NONCASTABLE, true,
|
|
|
- cmp, end_block))
|
|
|
- goto fail;
|
|
|
+ cmp, block_obj_non_null)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- /* Move builder to end block */
|
|
|
- SET_BUILDER_POS(end_block);
|
|
|
+ SET_BUILDER_POS(block_obj_non_null);
|
|
|
+
|
|
|
+ if (heap_type >= 0) {
|
|
|
+ if (!aot_call_aot_obj_is_instance_of(comp_ctx, func_ctx, gc_obj,
|
|
|
+ I32_CONST(heap_type), &castable))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (!aot_call_wasm_obj_is_type_of(comp_ctx, func_ctx, gc_obj,
|
|
|
+ I32_CONST(heap_type), &castable))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, castable, I8_ZERO,
|
|
|
+ "is_uncastable"))) {
|
|
|
+ aot_set_last_error("llvm build not failed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_TYPE_NONCASTABLE, true,
|
|
|
+ cmp, block_end)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -1664,42 +1712,47 @@ bool
|
|
|
aot_compile_op_extern_internalize(AOTCompContext *comp_ctx,
|
|
|
AOTFuncContext *func_ctx)
|
|
|
{
|
|
|
- LLVMValueRef externref_obj, gc_obj, cmp;
|
|
|
- LLVMBasicBlockRef obj_null, obj_non_null, end_block;
|
|
|
+ LLVMValueRef externref_obj, gc_obj, cmp, internal_obj_phi;
|
|
|
+ LLVMBasicBlockRef block_curr, block_obj_non_null, block_end;
|
|
|
|
|
|
- POP_REF(externref_obj);
|
|
|
+ POP_GC_REF(externref_obj);
|
|
|
|
|
|
- /* Create if block */
|
|
|
- ADD_BASIC_BLOCK(obj_null, "obj_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(obj_null);
|
|
|
+ block_curr = CURR_BLOCK();
|
|
|
|
|
|
- /* Create else block */
|
|
|
- ADD_BASIC_BLOCK(obj_non_null, "obj_non_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(obj_non_null);
|
|
|
+ /* Create non-null object block */
|
|
|
+ ADD_BASIC_BLOCK(block_obj_non_null, "non_null_obj");
|
|
|
+ MOVE_BLOCK_AFTER_CURR(block_obj_non_null);
|
|
|
|
|
|
/* Create end block */
|
|
|
- ADD_BASIC_BLOCK(end_block, "end_block");
|
|
|
- MOVE_BLOCK_AFTER_CURR(end_block);
|
|
|
+ ADD_BASIC_BLOCK(block_end, "internalize_end");
|
|
|
+ MOVE_BLOCK_AFTER(block_end, block_obj_non_null);
|
|
|
+
|
|
|
+ /* Create internalized object phi */
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ if (!(internal_obj_phi =
|
|
|
+ LLVMBuildPhi(comp_ctx->builder, GC_REF_TYPE, "internal_obj"))) {
|
|
|
+ aot_set_last_error("llvm build phi failed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
/* Check if externref object is NULL */
|
|
|
+ SET_BUILDER_POS(block_curr);
|
|
|
BUILD_ISNULL(externref_obj, cmp, "cmp_externref_obj");
|
|
|
- BUILD_COND_BR(cmp, obj_null, obj_non_null);
|
|
|
-
|
|
|
- /* Move builder to obj NULL block */
|
|
|
- SET_BUILDER_POS(obj_null);
|
|
|
- PUSH_REF(GC_REF_NULL);
|
|
|
- BUILD_BR(end_block);
|
|
|
+ BUILD_COND_BR(cmp, block_end, block_obj_non_null);
|
|
|
+ LLVMAddIncoming(internal_obj_phi, &GC_REF_NULL, &block_curr, 1);
|
|
|
|
|
|
- /* Move builder to obj not NULL block */
|
|
|
- SET_BUILDER_POS(obj_non_null);
|
|
|
+ /* Move builder to non-null object block */
|
|
|
+ SET_BUILDER_POS(block_obj_non_null);
|
|
|
if (!aot_call_wasm_externref_obj_to_internal_obj(comp_ctx, func_ctx,
|
|
|
- externref_obj, &gc_obj))
|
|
|
- goto fail;
|
|
|
- PUSH_REF(gc_obj);
|
|
|
- BUILD_BR(end_block);
|
|
|
+ externref_obj, &gc_obj)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ BUILD_BR(block_end);
|
|
|
+ LLVMAddIncoming(internal_obj_phi, &gc_obj, &block_obj_non_null, 1);
|
|
|
|
|
|
/* Move builder to end block */
|
|
|
- SET_BUILDER_POS(end_block);
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ PUSH_GC_REF(internal_obj_phi);
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
@@ -1719,7 +1772,7 @@ aot_call_wasm_internal_obj_to_external_obj(AOTCompContext *comp_ctx,
|
|
|
param_types[1] = GC_REF_TYPE;
|
|
|
ret_type = GC_REF_TYPE;
|
|
|
|
|
|
- GET_AOT_FUNCTION(wasm_internal_obj_to_externref_obj, 1);
|
|
|
+ GET_AOT_FUNCTION(wasm_internal_obj_to_externref_obj, 2);
|
|
|
|
|
|
/* Call function wasm_internal_obj_to_externref_obj() */
|
|
|
param_values[0] = func_ctx->exec_env;
|
|
|
@@ -1741,48 +1794,55 @@ bool
|
|
|
aot_compile_op_extern_externalize(AOTCompContext *comp_ctx,
|
|
|
AOTFuncContext *func_ctx)
|
|
|
{
|
|
|
- LLVMValueRef gc_obj, externref_obj, cmp;
|
|
|
- LLVMBasicBlockRef obj_null, obj_non_null, end_block, externalize_succ;
|
|
|
+ LLVMValueRef gc_obj, cmp, external_obj_phi, externref_obj;
|
|
|
+ LLVMBasicBlockRef block_curr, block_obj_non_null, block_end;
|
|
|
|
|
|
- POP_REF(gc_obj);
|
|
|
+ POP_GC_REF(gc_obj);
|
|
|
|
|
|
- /* Create if block */
|
|
|
- ADD_BASIC_BLOCK(obj_null, "obj_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(obj_null);
|
|
|
+ block_curr = CURR_BLOCK();
|
|
|
|
|
|
- /* Create else block */
|
|
|
- ADD_BASIC_BLOCK(obj_non_null, "obj_non_null");
|
|
|
- MOVE_BLOCK_AFTER_CURR(obj_non_null);
|
|
|
- ADD_BASIC_BLOCK(externalize_succ, "externalized_succ");
|
|
|
- MOVE_BLOCK_AFTER(externalize_succ, obj_non_null);
|
|
|
+ /* Create non-null object block */
|
|
|
+ ADD_BASIC_BLOCK(block_obj_non_null, "non_null_obj");
|
|
|
+ MOVE_BLOCK_AFTER_CURR(block_obj_non_null);
|
|
|
|
|
|
/* Create end block */
|
|
|
- ADD_BASIC_BLOCK(end_block, "end_block");
|
|
|
- MOVE_BLOCK_AFTER_CURR(end_block);
|
|
|
+ ADD_BASIC_BLOCK(block_end, "externalize_end");
|
|
|
+ MOVE_BLOCK_AFTER(block_end, block_obj_non_null);
|
|
|
+
|
|
|
+ /* Create externalized object phi */
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ if (!(external_obj_phi =
|
|
|
+ LLVMBuildPhi(comp_ctx->builder, GC_REF_TYPE, "external_obj"))) {
|
|
|
+ aot_set_last_error("llvm build phi failed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
/* Check if gc object is NULL */
|
|
|
+ SET_BUILDER_POS(block_curr);
|
|
|
BUILD_ISNULL(gc_obj, cmp, "cmp_gc_obj");
|
|
|
- BUILD_COND_BR(cmp, obj_null, obj_non_null);
|
|
|
+ BUILD_COND_BR(cmp, block_end, block_obj_non_null);
|
|
|
+ LLVMAddIncoming(external_obj_phi, &GC_REF_NULL, &block_curr, 1);
|
|
|
|
|
|
- /* Move builder to obj NULL block */
|
|
|
- SET_BUILDER_POS(obj_null);
|
|
|
- PUSH_REF(GC_REF_NULL);
|
|
|
- BUILD_BR(end_block);
|
|
|
+ /* Move builder to non-null object block */
|
|
|
+ SET_BUILDER_POS(block_obj_non_null);
|
|
|
|
|
|
- /* Move builder to obj not NULL block */
|
|
|
- SET_BUILDER_POS(obj_non_null);
|
|
|
if (!aot_call_wasm_internal_obj_to_external_obj(comp_ctx, func_ctx, gc_obj,
|
|
|
- &externref_obj))
|
|
|
- goto fail;
|
|
|
+ &externref_obj)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check whether failed to externalize */
|
|
|
BUILD_ISNULL(externref_obj, cmp, "cmp_externref_obj");
|
|
|
- if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
|
|
|
- externalize_succ))
|
|
|
- goto fail;
|
|
|
- PUSH_REF(externref_obj);
|
|
|
- BUILD_BR(end_block);
|
|
|
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_GC_OBJ,
|
|
|
+ true, cmp, block_end)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ LLVMAddIncoming(external_obj_phi, &externref_obj, &block_obj_non_null, 1);
|
|
|
|
|
|
/* Move builder to end block */
|
|
|
- SET_BUILDER_POS(end_block);
|
|
|
+ SET_BUILDER_POS(block_end);
|
|
|
+ PUSH_GC_REF(external_obj_phi);
|
|
|
|
|
|
return true;
|
|
|
fail:
|