// #target: linux-x64 module overlap; import std::io; interface TestProto { fn void tesT(); } interface TestProto2 { fn void tesT(); } fn void Test.tesT(&self) @dynamic { } fn void Test.foo(&self) @dynamic {} struct Test (TestProto, TestProto2) { void* abc; } fn void main() { TestProto z = mem::alloc(Test); z.tesT(); TestProto2 w = (TestProto2)z; w.tesT(); } /* #expect: overlap.ll %.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } %any = type { ptr, i64 } @"$ct.overlap.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 @"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", comdat, align 1 @.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 @.file = internal constant [30 x i8] c"overlapping_function_linux.c3\00", align 1 @.func = internal constant [5 x i8] c"main\00", align 1 @std.core.builtin.panic = extern_weak global ptr, align 8 @"$ct.dyn.overlap.Test.tesT" = weak global { ptr, ptr, ptr } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 @"$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: ret void } define void @overlap.Test.foo(ptr %0) #0 { entry: ret void } define void @overlap.main() #0 { entry: %z = alloca %any, align 8 %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %w = alloca %any, 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 %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 store %any %2, ptr %z, align 8 %ptradd = getelementptr inbounds i8, ptr %z, i64 8 %3 = load i64, ptr %ptradd, align 8 %4 = inttoptr i64 %3 to ptr %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 %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 %7 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 41, ptr @.file unreachable 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 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 { entry: call void @overlap.main() ret i32 0 } 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 %dtable = load ptr, ptr %dtable_ref, align 8 br label %check 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 %next_parent, label %compare next_parent: ; preds = %check %parent_ref = getelementptr inbounds %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 %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 %8 = load ptr, ptr %2, align 8 ret ptr %8 no_match: ; preds = %compare %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.overlap.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.overlap.Test.foo", ptr %dtable_ref3, align 8 store ptr null, ptr getelementptr inbounds br label %dtable_skip7 dtable_skip7: ; preds = %dtable_found6, %dtable_skip ret void }