diff --git a/releasenotes.md b/releasenotes.md index c9387f676..68d7303cf 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - Add `@safeinfer` to allow `var` to be used locally. - Types converts to typeid implicitly. - Allow `$defined` take declarations: `$defined(int x = y)` +- Struct and typedef subtypes inherit dynamic functions. ### Fixes - List.remove_at would incorrectly trigger ASAN. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index bc68462e3..2c2c82197 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -5519,15 +5519,29 @@ static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id LLVMBasicBlockRef entry; LLVMBuilderRef builder = llvm_create_function_entry(c, func, &entry); - LLVMValueRef dtable_ptr_in = LLVMGetParam(func, 0); + LLVMValueRef typeid_ptr_in = LLVMGetParam(func, 0); LLVMValueRef func_ref = LLVMGetParam(func, 1); + LLVMBasicBlockRef get_dtable = llvm_basic_block_new(c, "get_dtable"); LLVMBasicBlockRef check = llvm_basic_block_new(c, "check"); + LLVMBasicBlockRef next_parent = llvm_basic_block_new(c, "next_parent"); LLVMBasicBlockRef missing_function = llvm_basic_block_new(c, "missing_function"); LLVMBasicBlockRef compare = llvm_basic_block_new(c, "compare"); LLVMBasicBlockRef match = llvm_basic_block_new(c, "match"); LLVMBasicBlockRef no_match = llvm_basic_block_new(c, "no_match"); + LLVMBuildBr(builder, get_dtable); + + LLVMAppendExistingBasicBlock(func, get_dtable); + LLVMPositionBuilderAtEnd(builder, get_dtable); + + LLVMValueRef typeid = LLVMBuildPhi(builder, c->ptr_type, "typeid"); + LLVMAddIncoming(typeid, &typeid_ptr_in, &entry, 1); + + LLVMValueRef dtable_ref = LLVMBuildStructGEP2(builder, c->introspect_type, typeid, INTROSPECT_INDEX_DTABLE, "dtable_ref"); + LLVMValueRef dtable_ptr_start = LLVMBuildLoad2(builder, c->ptr_type, dtable_ref, "dtable"); + LLVMSetAlignment(dtable_ptr_start, type_abi_alignment(type_voidptr)); + LLVMBuildBr(builder, check); // check: dtable_ptr = phi @@ -5538,12 +5552,27 @@ static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id // dtable_ptr == null LLVMValueRef cmp = LLVMBuildICmp(builder, LLVMIntEQ, dtable_ptr, LLVMConstNull(c->ptr_type), ""); - // if (cmp) goto missing_function else compare - LLVMBuildCondBr(builder, cmp, missing_function, compare); + // if (cmp) goto next_parent else compare + LLVMBuildCondBr(builder, cmp, next_parent, compare); + + LLVMAppendExistingBasicBlock(func, next_parent); + LLVMPositionBuilderAtEnd(builder, next_parent); + + LLVMValueRef parent_ref = LLVMBuildStructGEP2(builder, c->introspect_type, typeid, INTROSPECT_INDEX_PARENTOF, "parent_ref"); + LLVMValueRef parent_ptr = LLVMBuildLoad2(builder, c->typeid_type, parent_ref, "parent"); + LLVMSetAlignment(parent_ptr, type_abi_alignment(type_voidptr)); + parent_ptr = LLVMBuildIntToPtr(builder, parent_ptr, c->ptr_type, "parent_ptr"); + + LLVMValueRef cmp2 = LLVMBuildICmp(builder, LLVMIntEQ, parent_ptr, LLVMConstNull(c->ptr_type), ""); + + // if (cmp) goto missing_function else get_dtable + LLVMAddIncoming(typeid, &parent_ptr, &next_parent, 1); + LLVMBuildCondBr(builder, cmp2, missing_function, get_dtable); // missing_function: return null LLVMAppendExistingBasicBlock(func, missing_function); LLVMPositionBuilderAtEnd(builder, missing_function); + LLVMBuildRet(builder, LLVMConstNull(c->ptr_type)); // function_type = dtable_ptr.function_type @@ -5579,7 +5608,7 @@ static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id // goto check LLVMBuildBr(builder, check); - llvm_set_phi(dtable_ptr, dtable_ptr_in, entry, next, no_match); + llvm_set_phi(dtable_ptr, dtable_ptr_start, get_dtable, next, no_match); LLVMDisposeBuilder(builder); } // Insert cache. @@ -5604,15 +5633,7 @@ static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id LLVMValueRef compare = LLVMBuildICmp(c->builder, LLVMIntEQ, type_id_ptr, cached_type_id, ""); llvm_emit_cond_br_raw(c, compare, cache_hit, cache_miss); llvm_emit_block(c, cache_miss); - AlignSize align; - LLVMValueRef dtable_ref = llvm_emit_struct_gep_raw(c, - type_id_ptr, - c->introspect_type, - INTROSPECT_INDEX_DTABLE, - llvm_abi_alignment(c, c->introspect_type), - &align); - LLVMValueRef dtable_ptr = llvm_load(c, c->ptr_type, dtable_ref, align, ""); - LLVMValueRef params[2] = { dtable_ptr, selector }; + LLVMValueRef params[2] = { type_id_ptr, selector }; LLVMValueRef call = LLVMBuildCall2(c->builder, type, func, params, 2, ""); // Store in cache. llvm_store_to_ptr_raw(c, cache_fn_ptr, call, type_voidptr); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index cf0628d92..1b76966c8 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1187,14 +1187,20 @@ RETRY:; if (result != BOOL_FALSE) return result == BOOL_TRUE; if (!decl->is_substruct) return false; Type *inner; - if (decl->decl_kind == DECL_DISTINCT) + switch (decl->decl_kind) { - inner = decl->distinct->type->canonical; - } - else - { - ASSERT(decl->decl_kind == DECL_STRUCT); - inner = decl->strukt.members[0]->type->canonical; + case DECL_DISTINCT: + inner = decl->distinct->type->canonical; + break; + case DECL_STRUCT: + inner = decl->strukt.members[0]->type->canonical; + break; + case DECL_ENUM: + case DECL_CONST_ENUM: + // Could be made to work. + return false; + default: + UNREACHABLE } if (!type_may_implement_interface(inner)) return false; decl = inner->decl; diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 51c0cf92b..560ecf15d 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -608,9 +608,15 @@ RETRY: FALLTHROUGH; case DECL_CONST_ENUM: case DECL_BITSTRUCT: - case DECL_STRUCT: - case DECL_UNION: case DECL_INTERFACE: + case DECL_UNION: + sema_trace_decl_dynamic_methods(decl); + return; + case DECL_STRUCT: + if (decl->is_substruct) + { + sema_trace_type_liveness(decl->strukt.members[0]->type); + } sema_trace_decl_dynamic_methods(decl); return; case DECL_ENUM_CONSTANT: diff --git a/test/test_suite/any/interface_optional_try.c3t b/test/test_suite/any/interface_optional_try.c3t index ff2fbb702..dfd148887 100644 --- a/test/test_suite/any/interface_optional_try.c3t +++ b/test/test_suite/any/interface_optional_try.c3t @@ -74,31 +74,29 @@ after_check2: ; preds = %after_assign br i1 %6, label %cache_hit, label %cache_miss cache_miss: ; preds = %after_check2 - %ptradd = getelementptr inbounds i8, ptr %5, i64 16 - %7 = load ptr, ptr %ptradd, align 8 - %8 = call ptr @.dyn_search(ptr %7, ptr @"$sel.do_something") - store ptr %8, ptr %.inlinecache, align 8 + %7 = call ptr @.dyn_search(ptr %5, ptr @"$sel.do_something") + store ptr %7, ptr %.inlinecache, align 8 store ptr %5, ptr %.cachedtype, align 8 - br label %9 + br label %8 cache_hit: ; preds = %after_check2 %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %9 + br label %8 -9: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %8, %cache_miss ] +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] store ptr %fn_phi, ptr %x, align 8 br label %phi_try_catch catch_landing: ; preds = %after_assign br label %phi_try_catch -phi_try_catch: ; preds = %catch_landing, %9 - %val = phi i1 [ true, %9 ], [ false, %catch_landing ] +phi_try_catch: ; preds = %catch_landing, %8 + %val = phi i1 [ true, %8 ], [ false, %catch_landing ] br i1 %val, label %if.exit, label %if.else if.else: ; preds = %phi_try_catch - %10 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.1, i64 39, ptr null, i64 0) + %9 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.1, i64 39, ptr null, i64 0) br label %if.exit if.exit: ; preds = %if.else, %phi_try_catch diff --git a/test/test_suite/debug_symbols/defer_macro.c3t b/test/test_suite/debug_symbols/defer_macro.c3t index b2f559a01..a01da5987 100644 --- a/test/test_suite/debug_symbols/defer_macro.c3t +++ b/test/test_suite/debug_symbols/defer_macro.c3t @@ -379,7 +379,7 @@ entry: %arg = alloca ptr, align 8 %len = alloca i64, align 8 %ptr = alloca ptr, align 8 - %len16 = alloca i64, align 8 + %len15 = alloca i64, align 8 store ptr null, ptr %.cachedtype, align 8 store i32 %0, ptr %.anon, align 4 @@ -426,132 +426,130 @@ if.exit: ; preds = %entry br i1 %14, label %cache_hit, label %cache_miss cache_miss: ; preds = %if.exit - %ptradd12 = getelementptr inbounds i8, ptr %13, i64 16 - %15 = load ptr, ptr %ptradd12, align 8 - %16 = call ptr @.dyn_search(ptr %15, ptr @"$sel.acquire") - store ptr %16, ptr %.inlinecache, align 8 + %15 = call ptr @.dyn_search(ptr %13, ptr @"$sel.acquire") + store ptr %15, ptr %.inlinecache, align 8 store ptr %13, ptr %.cachedtype, align 8 - br label %17 + br label %16 cache_hit: ; preds = %if.exit %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %17 + br label %16 -17: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %16, %cache_miss ] - %18 = icmp eq ptr %fn_phi, null - br i1 %18, label %missing_function, label %match +16: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %15, %cache_miss ] + %17 = icmp eq ptr %fn_phi, null + br i1 %17, label %missing_function, label %match -missing_function: ; preds = %17 - %19 = load ptr, ptr @std.core.builtin.panic, align 8, !dbg !167 - call void %19(ptr @.panic_msg, i64 44, ptr @.file, +missing_function: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8, !dbg !167 + call void %18(ptr @.panic_msg, i64 44, ptr @.file, unreachable, !dbg !167 -match: ; preds = %17 - %20 = load ptr, ptr %allocator10, align 8 - %21 = load i64, ptr %size, align 8 - %22 = call i64 %fn_phi(ptr %retparam, ptr %20, i64 %21, i32 0, i64 0), !dbg !167 - %not_err = icmp eq i64 %22, 0, !dbg !167 - %23 = call i1 @llvm.expect.i1(i1 %not_err, i1 true), !dbg !167 - br i1 %23, label %after_check, label %assign_optional, !dbg !167 +match: ; preds = %16 + %19 = load ptr, ptr %allocator10, align 8 + %20 = load i64, ptr %size, align 8 + %21 = call i64 %fn_phi(ptr %retparam, ptr %19, i64 %20, i32 0, i64 0), !dbg !167 + %not_err = icmp eq i64 %21, 0, !dbg !167 + %22 = call i1 @llvm.expect.i1(i1 %not_err, i1 true), !dbg !167 + br i1 %22, label %after_check, label %assign_optional, !dbg !167 assign_optional: ; preds = %match - store i64 %22, ptr %error_var, align 8, !dbg !167 + store i64 %21, ptr %error_var, align 8, !dbg !167 br label %panic_block, !dbg !167 after_check: ; preds = %match - %24 = load ptr, ptr %retparam, align 8, !dbg !167 - store ptr %24, ptr %blockret11, align 8, !dbg !167 + %23 = load ptr, ptr %retparam, align 8, !dbg !167 + store ptr %23, ptr %blockret11, align 8, !dbg !167 br label %expr_block.exit, !dbg !167 expr_block.exit: ; preds = %after_check, %if.then - %25 = load ptr, ptr %blockret11, align 8, !dbg !167 - %26 = load i64, ptr %elements8, align 8, !dbg !168 - %add = add i64 0, %26, !dbg !168 - %size13 = sub i64 %add, 0, !dbg !168 - %27 = insertvalue %"char[][]" undef, ptr %25, 0, !dbg !168 - %28 = insertvalue %"char[][]" %27, i64 %size13, 1, !dbg !168 + %24 = load ptr, ptr %blockret11, align 8, !dbg !167 + %25 = load i64, ptr %elements8, align 8, !dbg !168 + %add = add i64 0, %25, !dbg !168 + %size12 = sub i64 %add, 0, !dbg !168 + %26 = insertvalue %"char[][]" undef, ptr %24, 0, !dbg !168 + %27 = insertvalue %"char[][]" %26, i64 %size12, 1, !dbg !168 br label %noerr_block, !dbg !168 panic_block: ; preds = %assign_optional - %29 = insertvalue %any undef, ptr %error_var, 0, !dbg !168 - %30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.fault" to i64), 1, !dbg !168 - store %any %30, ptr %varargslots, align 16 - %31 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %31, i64 1, 1 + %28 = insertvalue %any undef, ptr %error_var, 0, !dbg !168 + %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.fault" to i64), 1, !dbg !168 + store %any %29, ptr %varargslots, align 16 + %30 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %30, i64 1, 1 store %"any[]" %"$$temp", ptr %indirectarg, align 8 call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 16, ptr @.func, i64 6, i32 287, ptr byval(%"any[]") align 8 %indirectarg) #5, !dbg !157 unreachable, !dbg !157 noerr_block: ; preds = %expr_block.exit - store %"char[][]" %28, ptr %list5, align 8, !dbg !157 + store %"char[][]" %27, ptr %list5, align 8, !dbg !157 store i32 0, ptr %i, align 4, !dbg !172 br label %loop.cond, !dbg !172 loop.cond: ; preds = %loop.exit, %noerr_block - %32 = load i32, ptr %i, align 4, !dbg !173 - %33 = load i32, ptr %argc2, align 4, !dbg !174 - %lt = icmp slt i32 %32, %33, !dbg !173 - br i1 %lt, label %loop.body, label %loop.exit26, !dbg !173 + %31 = load i32, ptr %i, align 4, !dbg !173 + %32 = load i32, ptr %argc2, align 4, !dbg !174 + %lt = icmp slt i32 %31, %32, !dbg !173 + br i1 %lt, label %loop.body, label %loop.exit25, !dbg !173 loop.body: ; preds = %loop.cond - %34 = load ptr, ptr %argv3, align 8, !dbg !178 - %35 = load i32, ptr %i, align 4, !dbg !179 - %sext14 = sext i32 %35 to i64, !dbg !179 - %ptroffset = getelementptr inbounds [8 x i8], ptr %34, i64 %sext14, !dbg !179 - %36 = load ptr, ptr %ptroffset, align 8, !dbg !179 - store ptr %36, ptr %arg, align 8, !dbg !179 + %33 = load ptr, ptr %argv3, align 8, !dbg !178 + %34 = load i32, ptr %i, align 4, !dbg !179 + %sext13 = sext i32 %34 to i64, !dbg !179 + %ptroffset = getelementptr inbounds [8 x i8], ptr %33, i64 %sext13, !dbg !179 + %35 = load ptr, ptr %ptroffset, align 8, !dbg !179 + store ptr %35, ptr %arg, align 8, !dbg !179 store i64 0, ptr %len, align 8, !dbg !182 - %37 = load ptr, ptr %arg, align 8, !dbg !183 - %38 = load ptr, ptr %arg, align 8 - store ptr %38, ptr %ptr, align 8 - store i64 0, ptr %len16, align 8, !dbg !188 - br label %loop.cond17, !dbg !189 + %36 = load ptr, ptr %arg, align 8, !dbg !183 + %37 = load ptr, ptr %arg, align 8 + store ptr %37, ptr %ptr, align 8 + store i64 0, ptr %len15, align 8, !dbg !188 + br label %loop.cond16, !dbg !189 -loop.cond17: ; preds = %loop.body19, %loop.body - %39 = load ptr, ptr %ptr, align 8, !dbg !190 - %40 = load i64, ptr %len16, align 8, !dbg !192 - %ptradd18 = getelementptr inbounds i8, ptr %39, i64 %40, !dbg !192 - %41 = load i8, ptr %ptradd18, align 1, !dbg !192 - %i2b = icmp ne i8 %41, 0, !dbg !192 - br i1 %i2b, label %loop.body19, label %loop.exit, !dbg !192 +loop.cond16: ; preds = %loop.body18, %loop.body + %38 = load ptr, ptr %ptr, align 8, !dbg !190 + %39 = load i64, ptr %len15, align 8, !dbg !192 + %ptradd17 = getelementptr inbounds i8, ptr %38, i64 %39, !dbg !192 + %40 = load i8, ptr %ptradd17, align 1, !dbg !192 + %i2b = icmp ne i8 %40, 0, !dbg !192 + br i1 %i2b, label %loop.body18, label %loop.exit, !dbg !192 -loop.body19: ; preds = %loop.cond17 - %42 = load i64, ptr %len16, align 8, !dbg !193 - %add20 = add i64 %42, 1, !dbg !193 - store i64 %add20, ptr %len16, align 8, !dbg !193 - br label %loop.cond17, !dbg !193 +loop.body18: ; preds = %loop.cond16 + %41 = load i64, ptr %len15, align 8, !dbg !193 + %add19 = add i64 %41, 1, !dbg !193 + store i64 %add19, ptr %len15, align 8, !dbg !193 + br label %loop.cond16, !dbg !193 -loop.exit: ; preds = %loop.cond17 - %43 = load i64, ptr %len16, align 8, !dbg !194 - %add21 = add i64 0, %43, !dbg !194 - %size22 = sub i64 %add21, 0, !dbg !194 - %44 = insertvalue %"char[]" undef, ptr %37, 0, !dbg !194 - %45 = insertvalue %"char[]" %44, i64 %size22, 1, !dbg !194 - %46 = load ptr, ptr %list5, align 8, !dbg !195 - %47 = load i32, ptr %i, align 4, !dbg !196 - %sext23 = sext i32 %47 to i64, !dbg !196 - %ptroffset24 = getelementptr inbounds [16 x i8], ptr %46, i64 %sext23, !dbg !196 - store %"char[]" %45, ptr %ptroffset24, align 8, !dbg !196 - %48 = load i32, ptr %i, align 4, !dbg !197 - %add25 = add i32 %48, 1, !dbg !197 - store i32 %add25, ptr %i, align 4, !dbg !197 +loop.exit: ; preds = %loop.cond16 + %42 = load i64, ptr %len15, align 8, !dbg !194 + %add20 = add i64 0, %42, !dbg !194 + %size21 = sub i64 %add20, 0, !dbg !194 + %43 = insertvalue %"char[]" undef, ptr %36, 0, !dbg !194 + %44 = insertvalue %"char[]" %43, i64 %size21, 1, !dbg !194 + %45 = load ptr, ptr %list5, align 8, !dbg !195 + %46 = load i32, ptr %i, align 4, !dbg !196 + %sext22 = sext i32 %46 to i64, !dbg !196 + %ptroffset23 = getelementptr inbounds [16 x i8], ptr %45, i64 %sext22, !dbg !196 + store %"char[]" %44, ptr %ptroffset23, align 8, !dbg !196 + %47 = load i32, ptr %i, align 4, !dbg !197 + %add24 = add i32 %47, 1, !dbg !197 + store i32 %add24, ptr %i, align 4, !dbg !197 br label %loop.cond, !dbg !197 -loop.exit26: ; preds = %loop.cond +loop.exit25: ; preds = %loop.cond call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list, ptr align 8 %list5, i32 16, i1 false), !dbg !198 %lo = load ptr, ptr %list, align 8, !dbg !199 - %ptradd27 = getelementptr inbounds i8, ptr %list, i64 8, !dbg !199 - %hi = load i64, ptr %ptradd27, align 8, !dbg !199 - %49 = call i32 @test.main(ptr %lo, i64 %hi), !dbg !200 - store i32 %49, ptr %blockret, align 4, !dbg !200 - %50 = load ptr, ptr %list, align 8, !dbg !201 - call void @std.core.mem.free(ptr %50) #4, !dbg !203 - br label %expr_block.exit28, !dbg !203 + %ptradd26 = getelementptr inbounds i8, ptr %list, i64 8, !dbg !199 + %hi = load i64, ptr %ptradd26, align 8, !dbg !199 + %48 = call i32 @test.main(ptr %lo, i64 %hi), !dbg !200 + store i32 %48, ptr %blockret, align 4, !dbg !200 + %49 = load ptr, ptr %list, align 8, !dbg !201 + call void @std.core.mem.free(ptr %49) #4, !dbg !203 + br label %expr_block.exit27, !dbg !203 -expr_block.exit28: ; preds = %loop.exit26 - %51 = load i32, ptr %blockret, align 4, !dbg !203 - ret i32 %51, !dbg !203 +expr_block.exit27: ; preds = %loop.exit25 + %50 = load i32, ptr %blockret, align 4, !dbg !203 + ret i32 %50, !dbg !203 } declare { i32, ptr } @attach.to_scope() #0 @@ -572,29 +570,42 @@ declare void @arena_scratch_end(ptr, i64) #0 define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { entry: + br label %get_dtable + +get_dtable: ; preds = %next_parent, %entry + %typeid = phi ptr [ %0, %entry ], [ %parent_ptr, %next_parent ] + %dtable_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 2 + %dtable = load ptr, ptr %dtable_ref, align 8 br label %check -check: ; preds = %no_match, %entry - %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] +check: ; preds = %no_match, %get_dtable + %2 = phi ptr [ %dtable, %get_dtable ], [ %10, %no_match ] %3 = icmp eq ptr %2, null - br i1 %3, label %missing_function, label %compare + br i1 %3, label %next_parent, label %compare -missing_function: ; preds = %check +next_parent: ; preds = %check + %parent_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 1 + %parent = load i64, ptr %parent_ref, align 8 + %parent_ptr = inttoptr i64 %parent to ptr + %4 = icmp eq ptr %parent_ptr, null + br i1 %4, label %missing_function, label %get_dtable + +missing_function: ; preds = %next_parent ret ptr null compare: ; preds = %check - %4 = getelementptr inbounds - %5 = load ptr, ptr %4, align 8 - %6 = icmp eq ptr %5, %1 - br i1 %6, label %match, label %no_match + %5 = getelementptr inbounds + %6 = load ptr, ptr %5, align 8 + %7 = icmp eq ptr %6, %1 + br i1 %7, label %match, label %no_match match: ; preds = %compare - %7 = load ptr, ptr %2, align 8 - ret ptr %7 + %8 = load ptr, ptr %2, align 8 + ret ptr %8 no_match: ; preds = %compare - %8 = getelementptr inbounds - %9 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds + %10 = load ptr, ptr %9, align 8 br label %check } diff --git a/test/test_suite/defer/defer_catch_mix.c3t b/test/test_suite/defer/defer_catch_mix.c3t index ae2b9d42e..879b06cea 100644 --- a/test/test_suite/defer/defer_catch_mix.c3t +++ b/test/test_suite/defer/defer_catch_mix.c3t @@ -292,16 +292,16 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %taddr = alloca %"char[]", align 8 + %taddr3 = alloca %"char[]", align 8 %taddr4 = alloca %"char[]", align 8 - %taddr5 = alloca %"char[]", align 8 %retparam = alloca ptr, align 8 + %taddr5 = alloca %"char[]", align 8 %taddr6 = alloca %"char[]", align 8 %taddr7 = alloca %"char[]", align 8 - %taddr8 = alloca %"char[]", align 8 %varargslots = alloca [1 x %any], align 8 - %taddr9 = alloca %"any[]", align 8 - %retparam13 = alloca %"char[]", align 8 - %taddr14 = alloca %"char[]", align 8 + %taddr8 = alloca %"any[]", align 8 + %retparam12 = alloca %"char[]", align 8 + %taddr13 = alloca %"char[]", align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @llvm.threadlocal.address.p0(ptr @std.core.mem.allocator.thread_allocator) call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator, ptr align 8 %0, i32 16, i1 false) @@ -318,98 +318,96 @@ if.exit: ; preds = %entry br i1 %3, label %cache_hit, label %cache_miss cache_miss: ; preds = %if.exit - %ptradd3 = getelementptr inbounds i8, ptr %2, i64 16 - %4 = load ptr, ptr %ptradd3, align 8 - %5 = call ptr @.dyn_search(ptr %4, ptr @"$sel.acquire") - store ptr %5, ptr %.inlinecache, align 8 + %4 = call ptr @.dyn_search(ptr %2, ptr @"$sel.acquire") + store ptr %4, ptr %.inlinecache, align 8 store ptr %2, ptr %.cachedtype, align 8 - br label %6 + br label %5 cache_hit: ; preds = %if.exit %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %6 + br label %5 -6: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %5, %cache_miss ] - %7 = icmp eq ptr %fn_phi, null - br i1 %7, label %missing_function, label %match +5: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %4, %cache_miss ] + %6 = icmp eq ptr %fn_phi, null + br i1 %6, label %missing_function, label %match -missing_function: ; preds = %6 +missing_function: ; preds = %5 store %"char[]" { ptr @.panic_msg, i64 44 }, ptr %taddr, align 8 - %8 = load [2 x i64], ptr %taddr, align 8 - store %"char[]" { ptr @.file, i64 16 }, ptr %taddr4, align 8 + %7 = load [2 x i64], ptr %taddr, align 8 + store %"char[]" { ptr @.file, i64 16 }, ptr %taddr3, align 8 + %8 = load [2 x i64], ptr %taddr3, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr4, align 8 %9 = load [2 x i64], ptr %taddr4, align 8 - store %"char[]" { ptr @.func, i64 4 }, ptr %taddr5, align 8 - %10 = load [2 x i64], ptr %taddr5, align 8 - %11 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %11([2 x i64] %8, [2 x i64] %9, [2 x i64] %10, i32 98) #4 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10([2 x i64] %7, [2 x i64] %8, [2 x i64] %9, i32 98) #4 unreachable -match: ; preds = %6 - %12 = load ptr, ptr %allocator2, align 8 - %13 = call i64 %fn_phi(ptr %retparam, ptr %12, i64 12, i32 1, i64 0) - %not_err = icmp eq i64 %13, 0 - %14 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %14, label %after_check, label %assign_optional +match: ; preds = %5 + %11 = load ptr, ptr %allocator2, align 8 + %12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 12, i32 1, i64 0) + %not_err = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %13, label %after_check, label %assign_optional assign_optional: ; preds = %match - store i64 %13, ptr %error_var, align 8 + store i64 %12, ptr %error_var, align 8 br label %panic_block after_check: ; preds = %match - %15 = load ptr, ptr %retparam, align 8 - %16 = insertvalue %"char[]" undef, ptr %15, 0 - %17 = insertvalue %"char[]" %16, i64 12, 1 + %14 = load ptr, ptr %retparam, align 8 + %15 = insertvalue %"char[]" undef, ptr %14, 0 + %16 = insertvalue %"char[]" %15, i64 12, 1 br label %noerr_block panic_block: ; preds = %assign_optional - %18 = insertvalue %any undef, ptr %error_var, 0 - %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 - store %"char[]" { ptr @.panic_msg.4, i64 36 }, ptr %taddr6, align 8 + %17 = insertvalue %any undef, ptr %error_var, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 + store %"char[]" { ptr @.panic_msg.4, i64 36 }, ptr %taddr5, align 8 + %19 = load [2 x i64], ptr %taddr5, align 8 + store %"char[]" { ptr @.file, i64 16 }, ptr %taddr6, align 8 %20 = load [2 x i64], ptr %taddr6, align 8 - store %"char[]" { ptr @.file, i64 16 }, ptr %taddr7, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr7, align 8 %21 = load [2 x i64], ptr %taddr7, align 8 - store %"char[]" { ptr @.func, i64 4 }, ptr %taddr8, align 8 - %22 = load [2 x i64], ptr %taddr8, align 8 - store %any %19, ptr %varargslots, align 8 - %23 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %23, i64 1, 1 - store %"any[]" %"$$temp", ptr %taddr9, align 8 - %24 = load [2 x i64], ptr %taddr9, align 8 - call void @std.core.builtin.panicf([2 x i64] %20, [2 x i64] %21, [2 x i64] %22, i32 262, [2 x i64] %24) #4 + store %any %18, ptr %varargslots, align 8 + %22 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %22, i64 1, 1 + store %"any[]" %"$$temp", ptr %taddr8, align 8 + %23 = load [2 x i64], ptr %taddr8, align 8 + call void @std.core.builtin.panicf([2 x i64] %19, [2 x i64] %20, [2 x i64] %21, i32 262, [2 x i64] %23) #4 unreachable noerr_block: ; preds = %after_check - store %"char[]" %17, ptr %buffer, align 8 + store %"char[]" %16, ptr %buffer, align 8 store i64 0, ptr %buffer.f, align 8 %optval = load i64, ptr %buffer.f, align 8 - %not_err10 = icmp eq i64 %optval, 0 - %25 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) - br i1 %25, label %after_check12, label %assign_optional11 + %not_err9 = icmp eq i64 %optval, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %24, label %after_check11, label %assign_optional10 -assign_optional11: ; preds = %noerr_block +assign_optional10: ; preds = %noerr_block store i64 %optval, ptr %buffer.f, align 8 br label %after_assign -after_check12: ; preds = %noerr_block - store %"char[]" { ptr @.str.5, i64 13 }, ptr %taddr14, align 8 - %26 = load [2 x i64], ptr %taddr14, align 8 - %27 = load [2 x i64], ptr %buffer, align 8 - %28 = call i64 @test.fileReader(ptr %retparam13, [2 x i64] %26, [2 x i64] %27) - %not_err15 = icmp eq i64 %28, 0 - %29 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true) - br i1 %29, label %after_check17, label %assign_optional16 +after_check11: ; preds = %noerr_block + store %"char[]" { ptr @.str.5, i64 13 }, ptr %taddr13, align 8 + %25 = load [2 x i64], ptr %taddr13, align 8 + %26 = load [2 x i64], ptr %buffer, align 8 + %27 = call i64 @test.fileReader(ptr %retparam12, [2 x i64] %25, [2 x i64] %26) + %not_err14 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err14, i1 true) + br i1 %28, label %after_check16, label %assign_optional15 -assign_optional16: ; preds = %after_check12 - store i64 %28, ptr %buffer.f, align 8 +assign_optional15: ; preds = %after_check11 + store i64 %27, ptr %buffer.f, align 8 br label %after_assign -after_check17: ; preds = %after_check12 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %buffer, ptr align 8 %retparam13, i32 16, i1 false) +after_check16: ; preds = %after_check11 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %buffer, ptr align 8 %retparam12, i32 16, i1 false) store i64 0, ptr %buffer.f, align 8 br label %after_assign -after_assign: ; preds = %after_check17, %assign_optional16, %assign_optional11 +after_assign: ; preds = %after_check16, %assign_optional15, %assign_optional10 ret void } diff --git a/test/test_suite/dynamic/inherit_linux.c3t b/test/test_suite/dynamic/inherit_linux.c3t index 3ce011da0..c13093e4e 100644 --- a/test/test_suite/dynamic/inherit_linux.c3t +++ b/test/test_suite/dynamic/inherit_linux.c3t @@ -69,9 +69,9 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %w = alloca %any, align 8 - %.inlinecache3 = alloca ptr, align 8 - %.cachedtype4 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype4, align 8 + %.inlinecache2 = alloca ptr, align 8 + %.cachedtype3 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype3, align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @std.core.mem.malloc(i64 8) #1 %1 = insertvalue %any undef, ptr %0, 0 @@ -83,56 +83,62 @@ entry: %type = load ptr, ptr %.cachedtype, align 8 %5 = icmp eq ptr %4, %type br i1 %5, label %cache_hit, label %cache_miss + cache_miss: ; preds = %entry - %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 - %6 = load ptr, ptr %ptradd1, align 8 - %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") - store ptr %7, ptr %.inlinecache, align 8 + %6 = call ptr @.dyn_search(ptr %4, ptr @"$sel.tesT") + store ptr %6, ptr %.inlinecache, align 8 store ptr %4, ptr %.cachedtype, align 8 - br label %8 + br label %7 + cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %8 -8: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] - %9 = icmp eq ptr %fn_phi, null - br i1 %9, label %missing_function, label %match -missing_function: ; preds = %8 - %10 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %10(ptr @.panic_msg, i64 41, ptr @.file + br label %7 + +7: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] + %8 = icmp eq ptr %fn_phi, null + br i1 %8, label %missing_function, label %match + +missing_function: ; preds = %7 + %9 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %9(ptr @.panic_msg, i64 41, ptr @.file unreachable -match: ; preds = %8 - %11 = load ptr, ptr %z, align 8 - call void %fn_phi(ptr %11) - %12 = load %any, ptr %z, align 8 - store %any %12, ptr %w, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 - %13 = load i64, ptr %ptradd2, align 8 - %14 = inttoptr i64 %13 to ptr - %type5 = load ptr, ptr %.cachedtype4, align 8 - %15 = icmp eq ptr %14, %type5 - br i1 %15, label %cache_hit8, label %cache_miss6 -cache_miss6: ; preds = %match - %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 - %16 = load ptr, ptr %ptradd7, align 8 - %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") - store ptr %17, ptr %.inlinecache3, align 8 - store ptr %14, ptr %.cachedtype4, align 8 - br label %18 -cache_hit8: ; preds = %match - %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 - br label %18 -18: ; preds = %cache_hit8, %cache_miss6 - %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] - %19 = icmp eq ptr %fn_phi10, null - br i1 %19, label %missing_function11, label %match12 -missing_function11: ; preds = %18 - %20 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %20(ptr @.panic_msg, i64 41, ptr @.file, i64 16, ptr @.func, i64 4, i32 36) + +match: ; preds = %7 + %10 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %10) + %11 = load %any, ptr %z, align 8 + store %any %11, ptr %w, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %w, i64 8 + %12 = load i64, ptr %ptradd1, align 8 + %13 = inttoptr i64 %12 to ptr + %type4 = load ptr, ptr %.cachedtype3, align 8 + %14 = icmp eq ptr %13, %type4 + br i1 %14, label %cache_hit6, label %cache_miss5 + +cache_miss5: ; preds = %match + %15 = call ptr @.dyn_search(ptr %13, ptr @"$sel.tesT") + store ptr %15, ptr %.inlinecache2, align 8 + store ptr %13, ptr %.cachedtype3, align 8 + br label %16 + +cache_hit6: ; preds = %match + %cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8 + br label %16 + +16: ; preds = %cache_hit6, %cache_miss5 + %fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %15, %cache_miss5 ] + %17 = icmp eq ptr %fn_phi8, null + br i1 %17, label %missing_function9, label %match10 + +missing_function9: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %18(ptr @.panic_msg, i64 41, ptr @.file, i64 16, ptr @.func, i64 4, i32 36) #2 unreachable -match12: ; preds = %18 - %21 = load ptr, ptr %w, align 8 - call void %fn_phi10(ptr %21) + +match10: ; preds = %16 + %19 = load ptr, ptr %w, align 8 + call void %fn_phi8(ptr %19) ret void } define i32 @main(i32 %0, ptr %1) #0 { @@ -143,55 +149,80 @@ entry: define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr comdat { entry: + br label %get_dtable + +get_dtable: ; preds = %next_parent, %entry + %typeid = phi ptr [ %0, %entry ], [ %parent_ptr, %next_parent ] + %dtable_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 2 + %dtable = load ptr, ptr %dtable_ref, align 8 br label %check -check: ; preds = %no_match, %entry - %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + +check: ; preds = %no_match, %get_dtable + %2 = phi ptr [ %dtable, %get_dtable ], [ %10, %no_match ] %3 = icmp eq ptr %2, null - br i1 %3, label %missing_function, label %compare -missing_function: ; preds = %check + br i1 %3, label %next_parent, label %compare + +next_parent: ; preds = %check + %parent_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 1 + %parent = load i64, ptr %parent_ref, align 8 + %parent_ptr = inttoptr i64 %parent to ptr + %4 = icmp eq ptr %parent_ptr, null + br i1 %4, label %missing_function, label %get_dtable + +missing_function: ; preds = %next_parent ret ptr null + compare: ; preds = %check - %4 = getelementptr inbounds - %5 = load ptr, ptr %4, align 8 - %6 = icmp eq ptr %5, %1 - br i1 %6, label %match, label %no_match + %5 = getelementptr inbounds + %6 = load ptr, ptr %5, align 8 + %7 = icmp eq ptr %6, %1 + br i1 %7, label %match, label %no_match + match: ; preds = %compare - %7 = load ptr, ptr %2, align 8 - ret ptr %7 + %8 = load ptr, ptr %2, align 8 + ret ptr %8 + no_match: ; preds = %compare - %8 = getelementptr inbounds - %9 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds + %10 = load ptr, ptr %9, align 8 br label %check } + define internal void @.c3_dynamic_register() align 8 { entry: %next_val = load ptr, ptr getelementptr inbounds %0 = icmp eq ptr %next_val, inttoptr (i64 -1 to ptr) br i1 %0, label %dtable_check, label %dtable_skip + dtable_check: ; preds = %dtable_check, %entry %dtable_ref = phi ptr [ getelementptr inbounds %dtable_ptr = load ptr, ptr %dtable_ref, align 8 %1 = icmp eq ptr %dtable_ptr, null %next_dtable_ref = getelementptr inbounds br i1 %1, label %dtable_found, label %dtable_check + dtable_found: ; preds = %dtable_check store ptr @"$ct.dyn.inherit.Test.tesT", ptr %dtable_ref, align 8 store ptr null, ptr getelementptr inbounds br label %dtable_skip + dtable_skip: ; preds = %dtable_found, %entry %next_val1 = load ptr, ptr getelementptr inbounds %2 = icmp eq ptr %next_val1, inttoptr (i64 -1 to ptr) br i1 %2, label %dtable_check2, label %dtable_skip7 + dtable_check2: ; preds = %dtable_check2, %dtable_skip %dtable_ref3 = phi ptr [ getelementptr inbounds %dtable_ptr4 = load ptr, ptr %dtable_ref3, align 8 %3 = icmp eq ptr %dtable_ptr4, null %next_dtable_ref5 = getelementptr inbounds br i1 %3, label %dtable_found6, label %dtable_check2 + dtable_found6: ; preds = %dtable_check2 store ptr @"$ct.dyn.inherit.Test.hello", ptr %dtable_ref3, align 8 store ptr null, ptr getelementptr inbounds br label %dtable_skip7 + dtable_skip7: ; preds = %dtable_found6, %dtable_skip ret void } \ No newline at end of file diff --git a/test/test_suite/dynamic/inherit_macos.c3t b/test/test_suite/dynamic/inherit_macos.c3t index 792f9b960..10d315966 100644 --- a/test/test_suite/dynamic/inherit_macos.c3t +++ b/test/test_suite/dynamic/inherit_macos.c3t @@ -66,9 +66,9 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %w = alloca %any, align 8 - %.inlinecache3 = alloca ptr, align 8 - %.cachedtype4 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype4, align 8 + %.inlinecache2 = alloca ptr, align 8 + %.cachedtype3 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype3, align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @std.core.mem.malloc(i64 8) #1 %1 = insertvalue %any undef, ptr %0, 0 @@ -82,64 +82,60 @@ entry: br i1 %5, label %cache_hit, label %cache_miss cache_miss: ; preds = %entry - %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 - %6 = load ptr, ptr %ptradd1, align 8 - %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") - store ptr %7, ptr %.inlinecache, align 8 + %6 = call ptr @.dyn_search(ptr %4, ptr @"$sel.tesT") + store ptr %6, ptr %.inlinecache, align 8 store ptr %4, ptr %.cachedtype, align 8 - br label %8 + br label %7 cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %8 + br label %7 -8: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] - %9 = icmp eq ptr %fn_phi, null - br i1 %9, label %missing_function, label %match +7: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] + %8 = icmp eq ptr %fn_phi, null + br i1 %8, label %missing_function, label %match -missing_function: ; preds = %8 - %10 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %10(ptr @.panic_msg, i64 41, +missing_function: ; preds = %7 + %9 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %9(ptr @.panic_msg, i64 41, unreachable -match: ; preds = %8 - %11 = load ptr, ptr %z, align 8 - call void %fn_phi(ptr %11) - %12 = load %any, ptr %z, align 8 - store %any %12, ptr %w, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 - %13 = load i64, ptr %ptradd2, align 8 - %14 = inttoptr i64 %13 to ptr - %type5 = load ptr, ptr %.cachedtype4, align 8 - %15 = icmp eq ptr %14, %type5 - br i1 %15, label %cache_hit8, label %cache_miss6 +match: ; preds = %7 + %10 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %10) + %11 = load %any, ptr %z, align 8 + store %any %11, ptr %w, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %w, i64 8 + %12 = load i64, ptr %ptradd1, align 8 + %13 = inttoptr i64 %12 to ptr + %type4 = load ptr, ptr %.cachedtype3, align 8 + %14 = icmp eq ptr %13, %type4 + br i1 %14, label %cache_hit6, label %cache_miss5 -cache_miss6: ; preds = %match - %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 - %16 = load ptr, ptr %ptradd7, align 8 - %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") - store ptr %17, ptr %.inlinecache3, align 8 - store ptr %14, ptr %.cachedtype4, align 8 - br label %18 +cache_miss5: ; preds = %match + %15 = call ptr @.dyn_search(ptr %13, ptr @"$sel.tesT") + store ptr %15, ptr %.inlinecache2, align 8 + store ptr %13, ptr %.cachedtype3, align 8 + br label %16 -cache_hit8: ; preds = %match - %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 - br label %18 +cache_hit6: ; preds = %match + %cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8 + br label %16 -18: ; preds = %cache_hit8, %cache_miss6 - %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] - %19 = icmp eq ptr %fn_phi10, null - br i1 %19, label %missing_function11, label %match12 +16: ; preds = %cache_hit6, %cache_miss5 + %fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %15, %cache_miss5 ] + %17 = icmp eq ptr %fn_phi8, null + br i1 %17, label %missing_function9, label %match10 -missing_function11: ; preds = %18 - %20 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %20(ptr @.panic_msg, i64 41 +missing_function9: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %18(ptr @.panic_msg, i64 41 unreachable -match12: ; preds = %18 - %21 = load ptr, ptr %w, align 8 - call void %fn_phi10(ptr %21) +match10: ; preds = %16 + %19 = load ptr, ptr %w, align 8 + call void %fn_phi8(ptr %19) ret void } define i32 @main(i32 %0, ptr %1) #0 { @@ -149,28 +145,41 @@ entry: } define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { entry: + br label %get_dtable + +get_dtable: ; preds = %next_parent, %entry + %typeid = phi ptr [ %0, %entry ], [ %parent_ptr, %next_parent ] + %dtable_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 2 + %dtable = load ptr, ptr %dtable_ref, align 8 br label %check -check: ; preds = %no_match, %entry - %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] +check: ; preds = %no_match, %get_dtable + %2 = phi ptr [ %dtable, %get_dtable ], [ %10, %no_match ] %3 = icmp eq ptr %2, null - br i1 %3, label %missing_function, label %compare + br i1 %3, label %next_parent, label %compare -missing_function: ; preds = %check +next_parent: ; preds = %check + %parent_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 1 + %parent = load i64, ptr %parent_ref, align 8 + %parent_ptr = inttoptr i64 %parent to ptr + %4 = icmp eq ptr %parent_ptr, null + br i1 %4, label %missing_function, label %get_dtable + +missing_function: ; preds = %next_parent ret ptr null compare: ; preds = %check - %4 = getelementptr inbounds - %5 = load ptr, ptr %4, align 8 - %6 = icmp eq ptr %5, %1 - br i1 %6, label %match, label %no_match + %5 = getelementptr inbounds + %6 = load ptr, ptr %5, align 8 + %7 = icmp eq ptr %6, %1 + br i1 %7, label %match, label %no_match match: ; preds = %compare - %7 = load ptr, ptr %2, align 8 - ret ptr %7 + %8 = load ptr, ptr %2, align 8 + ret ptr %8 no_match: ; preds = %compare - %8 = getelementptr inbounds - %9 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds + %10 = load ptr, ptr %9, align 8 br label %check } diff --git a/test/test_suite/dynamic/overlapping_function_linux.c3t b/test/test_suite/dynamic/overlapping_function_linux.c3t index 872f9f5be..f517bc854 100644 --- a/test/test_suite/dynamic/overlapping_function_linux.c3t +++ b/test/test_suite/dynamic/overlapping_function_linux.c3t @@ -46,6 +46,7 @@ fn void main() @"$ct.dyn.overlap.Test.foo" = weak global { ptr, ptr, ptr } { ptr @overlap.Test.foo, ptr @"$sel.foo", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 @"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", comdat, align 1 @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_register, ptr null }] + ; Function Attrs: nounwind uwtable define void @overlap.Test.tesT(ptr %0) #0 { entry: @@ -63,9 +64,9 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %w = alloca %any, align 8 - %.inlinecache3 = alloca ptr, align 8 - %.cachedtype4 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype4, align 8 + %.inlinecache2 = alloca ptr, align 8 + %.cachedtype3 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype3, align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @std.core.mem.malloc(i64 8) #1 %1 = insertvalue %any undef, ptr %0, 0 @@ -77,56 +78,62 @@ entry: %type = load ptr, ptr %.cachedtype, align 8 %5 = icmp eq ptr %4, %type br i1 %5, label %cache_hit, label %cache_miss + cache_miss: ; preds = %entry - %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 - %6 = load ptr, ptr %ptradd1, align 8 - %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") - store ptr %7, ptr %.inlinecache, align 8 + %6 = call ptr @.dyn_search(ptr %4, ptr @"$sel.tesT") + store ptr %6, ptr %.inlinecache, align 8 store ptr %4, ptr %.cachedtype, align 8 - br label %8 + br label %7 + cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %8 -8: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] - %9 = icmp eq ptr %fn_phi, null - br i1 %9, label %missing_function, label %match -missing_function: ; preds = %8 - %10 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %10(ptr @.panic_msg, i64 41, ptr @.file + br label %7 + +7: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] + %8 = icmp eq ptr %fn_phi, null + br i1 %8, label %missing_function, label %match + +missing_function: ; preds = %7 + %9 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %9(ptr @.panic_msg, i64 41, ptr @.file unreachable -match: ; preds = %8 - %11 = load ptr, ptr %z, align 8 - call void %fn_phi(ptr %11) - %12 = load %any, ptr %z, align 8 - store %any %12, ptr %w, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 - %13 = load i64, ptr %ptradd2, align 8 - %14 = inttoptr i64 %13 to ptr - %type5 = load ptr, ptr %.cachedtype4, align 8 - %15 = icmp eq ptr %14, %type5 - br i1 %15, label %cache_hit8, label %cache_miss6 -cache_miss6: ; preds = %match - %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 - %16 = load ptr, ptr %ptradd7, align 8 - %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") - store ptr %17, ptr %.inlinecache3, align 8 - store ptr %14, ptr %.cachedtype4, align 8 - br label %18 -cache_hit8: ; preds = %match - %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 - br label %18 -18: ; preds = %cache_hit8, %cache_miss6 - %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] - %19 = icmp eq ptr %fn_phi10, null - br i1 %19, label %missing_function11, label %match12 -missing_function11: ; preds = %18 - %20 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %20(ptr @.panic_msg, i64 41, ptr @.file + +match: ; preds = %7 + %10 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %10) + %11 = load %any, ptr %z, align 8 + store %any %11, ptr %w, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %w, i64 8 + %12 = load i64, ptr %ptradd1, align 8 + %13 = inttoptr i64 %12 to ptr + %type4 = load ptr, ptr %.cachedtype3, align 8 + %14 = icmp eq ptr %13, %type4 + br i1 %14, label %cache_hit6, label %cache_miss5 + +cache_miss5: ; preds = %match + %15 = call ptr @.dyn_search(ptr %13, ptr @"$sel.tesT") + store ptr %15, ptr %.inlinecache2, align 8 + store ptr %13, ptr %.cachedtype3, align 8 + br label %16 + +cache_hit6: ; preds = %match + %cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8 + br label %16 + +16: ; preds = %cache_hit6, %cache_miss5 + %fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %15, %cache_miss5 ] + %17 = icmp eq ptr %fn_phi8, null + br i1 %17, label %missing_function9, label %match10 + +missing_function9: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %18(ptr @.panic_msg, i64 41, ptr @.file unreachable -match12: ; preds = %18 - %21 = load ptr, ptr %w, align 8 - call void %fn_phi10(ptr %21) + +match10: ; preds = %16 + %19 = load ptr, ptr %w, align 8 + call void %fn_phi8(ptr %19) ret void } @@ -137,26 +144,45 @@ entry: } define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr comdat { entry: + br label %get_dtable + +get_dtable: ; preds = %next_parent, %entry + %typeid = phi ptr [ %0, %entry ], [ %parent_ptr, %next_parent ] + %dtable_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 2 + %dtable = load ptr, ptr %dtable_ref, align 8 br label %check -check: ; preds = %no_match, %entry - %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + +check: ; preds = %no_match, %get_dtable + %2 = phi ptr [ %dtable, %get_dtable ], [ %10, %no_match ] %3 = icmp eq ptr %2, null - br i1 %3, label %missing_function, label %compare -missing_function: ; preds = %check + br i1 %3, label %next_parent, label %compare + +next_parent: ; preds = %check + %parent_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 1 + %parent = load i64, ptr %parent_ref, align 8 + %parent_ptr = inttoptr i64 %parent to ptr + %4 = icmp eq ptr %parent_ptr, null + br i1 %4, label %missing_function, label %get_dtable + +missing_function: ; preds = %next_parent ret ptr null + compare: ; preds = %check - %4 = getelementptr inbounds - %5 = load ptr, ptr %4, align 8 - %6 = icmp eq ptr %5, %1 - br i1 %6, label %match, label %no_match + %5 = getelementptr inbounds + %6 = load ptr, ptr %5, align 8 + %7 = icmp eq ptr %6, %1 + br i1 %7, label %match, label %no_match + match: ; preds = %compare - %7 = load ptr, ptr %2, align 8 - ret ptr %7 + %8 = load ptr, ptr %2, align 8 + ret ptr %8 + no_match: ; preds = %compare - %8 = getelementptr inbounds - %9 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds + %10 = load ptr, ptr %9, align 8 br label %check } + define internal void @.c3_dynamic_register() align 8 { entry: %next_val = load ptr, ptr getelementptr inbounds diff --git a/test/test_suite/dynamic/overlapping_function_macos.c3t b/test/test_suite/dynamic/overlapping_function_macos.c3t index 4d9d33473..ca63ea25b 100644 --- a/test/test_suite/dynamic/overlapping_function_macos.c3t +++ b/test/test_suite/dynamic/overlapping_function_macos.c3t @@ -61,9 +61,9 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %w = alloca %any, align 8 - %.inlinecache3 = alloca ptr, align 8 - %.cachedtype4 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype4, align 8 + %.inlinecache2 = alloca ptr, align 8 + %.cachedtype3 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype3, align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @std.core.mem.malloc(i64 8) #1 %1 = insertvalue %any undef, ptr %0, 0 @@ -77,68 +77,64 @@ entry: br i1 %5, label %cache_hit, label %cache_miss cache_miss: ; preds = %entry - %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 - %6 = load ptr, ptr %ptradd1, align 8 - %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") - store ptr %7, ptr %.inlinecache, align 8 + %6 = call ptr @.dyn_search(ptr %4, ptr @"$sel.tesT") + store ptr %6, ptr %.inlinecache, align 8 store ptr %4, ptr %.cachedtype, align 8 - br label %8 + br label %7 cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %8 + br label %7 -8: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] - %9 = icmp eq ptr %fn_phi, null - br i1 %9, label %missing_function, label %match +7: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] + %8 = icmp eq ptr %fn_phi, null + br i1 %8, label %missing_function, label %match -missing_function: ; preds = %8 - %10 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %10(ptr @.panic_msg, i64 41, ptr @.file +missing_function: ; preds = %7 + %9 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %9(ptr @.panic_msg, i64 41, ptr @.file unreachable -match: ; preds = %8 - %11 = load ptr, ptr %z, align 8 - call void %fn_phi(ptr %11) - %12 = load %any, ptr %z, align 8 - store %any %12, ptr %w, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 - %13 = load i64, ptr %ptradd2, align 8 - %14 = inttoptr i64 %13 to ptr - %type5 = load ptr, ptr %.cachedtype4, align 8 - %15 = icmp eq ptr %14, %type5 - br i1 %15, label %cache_hit8, label %cache_miss6 +match: ; preds = %7 + %10 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %10) + %11 = load %any, ptr %z, align 8 + store %any %11, ptr %w, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %w, i64 8 + %12 = load i64, ptr %ptradd1, align 8 + %13 = inttoptr i64 %12 to ptr + %type4 = load ptr, ptr %.cachedtype3, align 8 + %14 = icmp eq ptr %13, %type4 + br i1 %14, label %cache_hit6, label %cache_miss5 -cache_miss6: ; preds = %match - %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 - %16 = load ptr, ptr %ptradd7, align 8 - %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") - store ptr %17, ptr %.inlinecache3, align 8 - store ptr %14, ptr %.cachedtype4, align 8 - br label %18 +cache_miss5: ; preds = %match + %15 = call ptr @.dyn_search(ptr %13, ptr @"$sel.tesT") + store ptr %15, ptr %.inlinecache2, align 8 + store ptr %13, ptr %.cachedtype3, align 8 + br label %16 -cache_hit8: ; preds = %match - %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 - br label %18 +cache_hit6: ; preds = %match + %cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8 + br label %16 -18: ; preds = %cache_hit8, %cache_miss6 - %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] - %19 = icmp eq ptr %fn_phi10, null - br i1 %19, label %missing_function11, label %match12 +16: ; preds = %cache_hit6, %cache_miss5 + %fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %15, %cache_miss5 ] + %17 = icmp eq ptr %fn_phi8, null + br i1 %17, label %missing_function9, label %match10 -missing_function11: ; preds = %18 - %20 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %20(ptr @.panic_msg, i64 41, ptr @.file +missing_function9: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %18(ptr @.panic_msg, i64 41, ptr @.file unreachable -match12: ; preds = %18 - %21 = load ptr, ptr %w, align 8 - call void %fn_phi10(ptr %21) +match10: ; preds = %16 + %19 = load ptr, ptr %w, align 8 + call void %fn_phi8(ptr %19) ret void } -; Function Attrs: + define i32 @main(i32 %0, ptr %1) #0 { entry: call void @overlap.main() @@ -147,28 +143,41 @@ entry: define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { entry: + br label %get_dtable + +get_dtable: ; preds = %next_parent, %entry + %typeid = phi ptr [ %0, %entry ], [ %parent_ptr, %next_parent ] + %dtable_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 2 + %dtable = load ptr, ptr %dtable_ref, align 8 br label %check -check: ; preds = %no_match, %entry - %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] +check: ; preds = %no_match, %get_dtable + %2 = phi ptr [ %dtable, %get_dtable ], [ %10, %no_match ] %3 = icmp eq ptr %2, null - br i1 %3, label %missing_function, label %compare + br i1 %3, label %next_parent, label %compare -missing_function: ; preds = %check +next_parent: ; preds = %check + %parent_ref = getelementptr inbounds %.introspect, ptr %typeid, i32 0, i32 1 + %parent = load i64, ptr %parent_ref, align 8 + %parent_ptr = inttoptr i64 %parent to ptr + %4 = icmp eq ptr %parent_ptr, null + br i1 %4, label %missing_function, label %get_dtable + +missing_function: ; preds = %next_parent ret ptr null compare: ; preds = %check - %4 = getelementptr inbounds - %5 = load ptr, ptr %4, align 8 - %6 = icmp eq ptr %5, %1 - br i1 %6, label %match, label %no_match + %5 = getelementptr inbounds + %6 = load ptr, ptr %5, align 8 + %7 = icmp eq ptr %6, %1 + br i1 %7, label %match, label %no_match match: ; preds = %compare - %7 = load ptr, ptr %2, align 8 - ret ptr %7 + %8 = load ptr, ptr %2, align 8 + ret ptr %8 no_match: ; preds = %compare - %8 = getelementptr inbounds - %9 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds + %10 = load ptr, ptr %9, align 8 br label %check } diff --git a/test/test_suite/enumerations/enum_const_inline_interface.c3 b/test/test_suite/enumerations/enum_const_inline_interface.c3 new file mode 100644 index 000000000..5731012de --- /dev/null +++ b/test/test_suite/enumerations/enum_const_inline_interface.c3 @@ -0,0 +1,26 @@ +module foo; +import std; +interface Test +{ + fn void x(); +} + +typedef Foo (Test) = int; + +fn void Foo.x(&self) @dynamic +{ + io::printn("Foo!"); +} + +enum Tester : const inline Foo +{ + ABC = 1 +} + +fn int main() +{ + Tester x; + Test t = &x; // #error: but you can use an explicit cast to + t.x(); + return 0; +} \ No newline at end of file diff --git a/test/test_suite/enumerations/enum_inline_interface.c3 b/test/test_suite/enumerations/enum_inline_interface.c3 new file mode 100644 index 000000000..e4d5a6259 --- /dev/null +++ b/test/test_suite/enumerations/enum_inline_interface.c3 @@ -0,0 +1,27 @@ +module foo; +import std; +interface Test +{ + fn void x(); +} + +typedef Foo (Test) = int; + +fn void Foo.x(&self) @dynamic +{ + io::printn("Foo!"); +} + +enum Tester : inline Foo +{ + ABC +} + +fn int main() +{ + Tester x; + Test t = &x; // #error: but you can use an explicit cast to + t.x(); + return 0; +} + diff --git a/test/test_suite/macros/unifying_implicit_void.c3t b/test/test_suite/macros/unifying_implicit_void.c3t index e0973b8b6..74f49c265 100644 --- a/test/test_suite/macros/unifying_implicit_void.c3t +++ b/test/test_suite/macros/unifying_implicit_void.c3t @@ -46,70 +46,84 @@ entry: %type = load ptr, ptr %.cachedtype, align 8 %4 = icmp eq ptr %3, %type br i1 %4, label %cache_hit, label %cache_miss + cache_miss: ; preds = %entry - %ptradd1 = getelementptr inbounds i8, ptr %3, i64 16 - %5 = load ptr, ptr %ptradd1, align 8 - %6 = call ptr @.dyn_search(ptr %5, ptr @"$sel.read_byte") - store ptr %6, ptr %.inlinecache, align 8 + %5 = call ptr @.dyn_search(ptr %3, ptr @"$sel.read_byte") + store ptr %5, ptr %.inlinecache, align 8 store ptr %3, ptr %.cachedtype, align 8 - br label %7 + br label %6 + cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %7 -7: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] - %8 = icmp eq ptr %fn_phi, null - br i1 %8, label %missing_function, label %match -missing_function: ; preds = %7 - %9 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %9(ptr @.panic_msg, i64 46, ptr @.file, i64 25, ptr @.func, i64 4, i32 13) + br label %6 + +6: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %5, %cache_miss ] + %7 = icmp eq ptr %fn_phi, null + br i1 %7, label %missing_function, label %match + +missing_function: ; preds = %6 + %8 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %8(ptr @.panic_msg, i64 46, ptr @.file, i64 25, ptr @.func, i64 4, i32 13) #4 unreachable -match: ; preds = %7 - %10 = load ptr, ptr %s, align 8 - %11 = call i64 %fn_phi(ptr %retparam, ptr %10) - %not_err = icmp eq i64 %11, 0 - %12 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %12, label %after_check, label %assign_optional + +match: ; preds = %6 + %9 = load ptr, ptr %s, align 8 + %10 = call i64 %fn_phi(ptr %retparam, ptr %9) + %not_err = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %11, label %after_check, label %assign_optional + assign_optional: ; preds = %match - store i64 %11, ptr %c.f, align 8 + store i64 %10, ptr %c.f, align 8 br label %after_assign + after_check: ; preds = %match - %13 = load i8, ptr %retparam, align 1 - store i8 %13, ptr %c, align 1 + %12 = load i8, ptr %retparam, align 1 + store i8 %12, ptr %c, align 1 store i64 0, ptr %c.f, align 8 br label %after_assign + after_assign: ; preds = %after_check, %assign_optional br label %testblock + testblock: ; preds = %after_assign %optval = load i64, ptr %c.f, align 8 - %not_err2 = icmp eq i64 %optval, 0 - %14 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) - br i1 %14, label %after_check4, label %assign_optional3 -assign_optional3: ; preds = %testblock + %not_err1 = icmp eq i64 %optval, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %13, label %after_check3, label %assign_optional2 + +assign_optional2: ; preds = %testblock store i64 %optval, ptr %err, align 8 br label %end_block -after_check4: ; preds = %testblock + +after_check3: ; preds = %testblock store i64 0, ptr %err, align 8 br label %end_block -end_block: ; preds = %after_check4, %assign_optional3 - %15 = load i64, ptr %err, align 8 - %i2b = icmp ne i64 %15, 0 + +end_block: ; preds = %after_check3, %assign_optional2 + %14 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %14, 0 br i1 %i2b, label %if.then, label %if.exit + if.then: ; preds = %end_block - %16 = load i64, ptr %err, align 8 - store i64 %16, ptr %error_var, align 8 + %15 = load i64, ptr %err, align 8 + store i64 %15, ptr %error_var, align 8 br label %panic_block + if.exit: ; preds = %end_block br label %noerr_block + panic_block: ; preds = %if.then - %17 = insertvalue %any undef, ptr %error_var, 0 - %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 - store %any %18, ptr %varargslots, align 16 - %19 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %19, i64 1, 1 + %16 = insertvalue %any undef, ptr %error_var, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 + store %any %17, ptr %varargslots, align 16 + %18 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %18, i64 1, 1 store %"any[]" %"$$temp", ptr %indirectarg, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 8, ptr byval(%"any[]") align 8 %indirectarg) + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, unreachable + noerr_block: ; preds = %if.exit ret void } \ No newline at end of file diff --git a/test/unit/regression/interface_inheritance.c3 b/test/unit/regression/interface_inheritance.c3 new file mode 100644 index 000000000..e95cacc68 --- /dev/null +++ b/test/unit/regression/interface_inheritance.c3 @@ -0,0 +1,33 @@ +module inherit_interface; +import std; +interface Test +{ + fn int x(); +} + +struct Foo (Test) +{ + int z; +} + +fn int Foo.x(&self) @dynamic +{ + return 42; +} + +struct Baz +{ + inline Bar b; +} + +struct Bar +{ + inline Foo f; +} + +fn void test_inheritance() @test +{ + Baz x; + Test t = &x; + test::eq(t.x(), 42); +} \ No newline at end of file