// #target: macos-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 = malloc(Test); z.tesT(); TestProto2* w = (TestProto2*)z; w.tesT(); } /* #expect: overlap.ll @"$ct.overlap.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"$ct.dyn.overlap.Test.tesT" = global { ptr, ptr, ptr } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", ptr null }, align 8 @"$ct.dyn.overlap.Test.foo" = global { ptr, ptr, ptr } { ptr @overlap.Test.foo, ptr @"$sel.foo", ptr null }, align 8 @"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.static_initialize.0, ptr null }] ; Function Attrs: nounwind define void @overlap.main() #0 { entry: %z = alloca %"any*", align 8 %using = alloca %"any*", align 8 %error_var = alloca i64, align 8 %using1 = alloca %"any*", align 8 %self = alloca %"any*", align 8 %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %retparam = alloca ptr, align 8 %varargslots = alloca [1 x %"any*"], align 16 %indirectarg = alloca %"any*[]", align 8 %.inlinecache2 = alloca ptr, align 8 %.cachedtype3 = alloca ptr, align 8 %w = alloca %"any*", align 8 %.inlinecache11 = alloca ptr, align 8 %.cachedtype12 = alloca ptr, align 8 store ptr null, ptr %.cachedtype12, align 8 store ptr null, ptr %.cachedtype3, align 8 store ptr null, ptr %.cachedtype, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 8 %using, ptr align 8 @std.core.mem.thread_allocator, i32 16, i1 false) call void @llvm.memcpy.p0.p0.i32(ptr align 8 %using1, ptr align 8 %using, i32 16, i1 false) call void @llvm.memcpy.p0.p0.i32(ptr align 8 %self, ptr align 8 %using1, i32 16, i1 false) %0 = getelementptr inbounds %"any*", ptr %self, i32 0, i32 1 %1 = load i64, ptr %0, align 8 %2 = getelementptr inbounds %"any*", ptr %self, i32 0, i32 0 %3 = inttoptr i64 %1 to ptr %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 %5 = getelementptr inbounds %.introspect, ptr %3, i32 0, i32 2 %6 = load ptr, ptr %5, align 8 %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.acquire") store ptr %7, ptr %.inlinecache, align 8 store ptr %3, ptr %.cachedtype, align 8 br label %8 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 44, ptr @.file, i64 16, ptr @.func, i64 4, i32 28) unreachable match: ; preds = %8 %11 = load ptr, ptr %2, align 8 %12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 8, i8 zeroext 0, i64 0, 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 %12, ptr %error_var, align 8 br label %panic_block after_check: ; preds = %match %14 = load ptr, ptr %retparam, align 8 br label %noerr_block panic_block: ; preds = %assign_optional %15 = insertvalue %"any*" undef, ptr %error_var, 0 %16 = insertvalue %"any*" %15, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 %17 = getelementptr inbounds [1 x %"any*"], ptr %varargslots, i64 0, i64 0 store %"any*" %16, ptr %17, 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.2, i64 6, ptr @.func, i64 4, i32 390, ptr byval(%"any*[]") align 8 %indirectarg) unreachable noerr_block: ; preds = %after_check %19 = insertvalue %"any*" undef, ptr %14, 0 %20 = insertvalue %"any*" %19, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 store %"any*" %20, ptr %z, align 8 %21 = getelementptr inbounds %"any*", ptr %z, i32 0, i32 1 %22 = load i64, ptr %21, align 8 %23 = getelementptr inbounds %"any*", ptr %z, i32 0, i32 0 %24 = inttoptr i64 %22 to ptr %type4 = load ptr, ptr %.cachedtype3, align 8 %25 = icmp eq ptr %24, %type4 br i1 %25, label %cache_hit6, label %cache_miss5 cache_miss5: ; preds = %noerr_block %26 = getelementptr inbounds %.introspect, ptr %24, i32 0, i32 2 %27 = load ptr, ptr %26, align 8 %28 = call ptr @.dyn_search(ptr %27, ptr @"$sel.tesT") store ptr %28, ptr %.inlinecache2, align 8 store ptr %24, ptr %.cachedtype3, align 8 br label %29 cache_hit6: ; preds = %noerr_block %cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8 br label %29 29: ; preds = %cache_hit6, %cache_miss5 %fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %28, %cache_miss5 ] %30 = icmp eq ptr %fn_phi8, null br i1 %30, label %missing_function9, label %match10 missing_function9: ; preds = %29 %31 = load ptr, ptr @std.core.builtin.panic, align 8 call void %31(ptr @.panic_msg.3, i64 41, ptr @.file.4, i64 23, ptr @.func, i64 4, i32 28) unreachable match10: ; preds = %29 %32 = load ptr, ptr %23, align 8 call void %fn_phi8(ptr %32) %33 = load %"any*", ptr %z, align 8 store %"any*" %33, ptr %w, align 8 %34 = getelementptr inbounds %"any*", ptr %w, i32 0, i32 1 %35 = load i64, ptr %34, align 8 %36 = getelementptr inbounds %"any*", ptr %w, i32 0, i32 0 %37 = inttoptr i64 %35 to ptr %type13 = load ptr, ptr %.cachedtype12, align 8 %38 = icmp eq ptr %37, %type13 br i1 %38, label %cache_hit15, label %cache_miss14 cache_miss14: ; preds = %match10 %39 = getelementptr inbounds %.introspect, ptr %37, i32 0, i32 2 %40 = load ptr, ptr %39, align 8 %41 = call ptr @.dyn_search(ptr %40, ptr @"$sel.tesT") store ptr %41, ptr %.inlinecache11, align 8 store ptr %37, ptr %.cachedtype12, align 8 br label %42 cache_hit15: ; preds = %match10 %cache_hit_fn16 = load ptr, ptr %.inlinecache11, align 8 br label %42 42: ; preds = %cache_hit15, %cache_miss14 %fn_phi17 = phi ptr [ %cache_hit_fn16, %cache_hit15 ], [ %41, %cache_miss14 ] %43 = icmp eq ptr %fn_phi17, null br i1 %43, label %missing_function18, label %match19 missing_function18: ; preds = %42 %44 = load ptr, ptr @std.core.builtin.panic, align 8 call void %44(ptr @.panic_msg.3, i64 41, ptr @.file.4, i64 23, ptr @.func, i64 4, i32 30) unreachable match19: ; preds = %42 %45 = load ptr, ptr %36, align 8 call void %fn_phi17(ptr %45) ret void } define internal void @.static_initialize.0() { entry: br label %dtable_check dtable_check: ; preds = %dtable_next, %entry %dtable_ref = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.overlap.Test", i32 0, i32 2), %entry ], [ %next_dtable_ref, %dtable_next ] %dtable_ptr = load ptr, ptr %dtable_ref, align 8 %0 = icmp eq ptr %dtable_ptr, null br i1 %0, label %dtable_found, label %dtable_next dtable_next: ; preds = %dtable_check %next_dtable_ref = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr, i32 0, i32 2 br label %dtable_check dtable_found: ; preds = %dtable_check store ptr @"$ct.dyn.overlap.Test.tesT", ptr %dtable_ref, align 8 br label %dtable_check1 dtable_check1: ; preds = %dtable_next4, %dtable_found %dtable_ref2 = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.overlap.Test", i32 0, i32 2), %dtable_found ], [ %next_dtable_ref5, %dtable_next4 ] %dtable_ptr3 = load ptr, ptr %dtable_ref2, align 8 %1 = icmp eq ptr %dtable_ptr3, null br i1 %1, label %dtable_found6, label %dtable_next4 dtable_next4: ; preds = %dtable_check1 %next_dtable_ref5 = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr3, i32 0, i32 2 br label %dtable_check1 dtable_found6: ; preds = %dtable_check1 store ptr @"$ct.dyn.overlap.Test.foo", ptr %dtable_ref2, align 8 ret void }