Struct and typedef subtypes inherit dynamic functions.

This commit is contained in:
Christoffer Lerno
2025-08-23 22:31:29 +02:00
parent 48318c3ad4
commit 961aa0ef61
15 changed files with 686 additions and 470 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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;

View File

@@ -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:

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
}

View File

@@ -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);
}