// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s // REQUIRES: CPU=x86_64 import Builtin // -- Generic structs with dynamic layout contain the vwtable pattern as part // of the metadata pattern, and no independent vwtable symbol // CHECK-NOT: @_T015generic_structs13SingleDynamicVWV // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [34 x i8] c"15generic_structs13SingleDynamicV\00" // CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00" // CHECK: @_T015generic_structs13SingleDynamicVMn = hidden constant <{ {{.*}} i32 }> <{ // -- name // CHECK: [34 x i8]* [[SINGLEDYNAMIC_NAME]] // -- field count // CHECK: i32 1, // -- field offset vector offset // CHECK: i32 3, // -- field names // CHECK: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]] // -- generic metadata pattern, kind 1 (struct) // CHECK: i32 add ({{.*}}@_T015generic_structs13SingleDynamicVMP{{.*}}, i32 1) // -- generic parameter vector offset // CHECK: i32 4, // -- generic parameter count, primary counts; generic parameter witness counts // CHECK: i32 1, i32 1, i32 0 // CHECK: }> // CHECK: @_T015generic_structs13SingleDynamicVMP = internal global <{ {{.*}} }> <{ // -- template header // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic, // CHECK: i32 240, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer, // -- placeholder for vwtable pointer // CHECK: i8* null, // -- address point // CHECK: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn // -- field offset vector; generic parameter vector // CHECK: i64 0, %swift.type* null, // -- tail-allocated vwtable pattern // CHECK: i8* bitcast (void ([24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwXX to i8*), // -- ... // -- placeholder for size, flags, stride // CHECK: i8* null, i8* null, i8* null // -- extra inhabitants // CHECK: i8* null, // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*), // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }> // CHECK-NOT: @_T015generic_structs13SingleDynamicVWV // -- Nominal type descriptor for generic struct with protocol requirements // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[DYNAMICWITHREQUIREMENTS_NAME:@.*]] = private constant [44 x i8] c"15generic_structs23DynamicWithRequirementsV\00" // CHECK: [[DYNAMICWITHREQUIREMENTS_FIELDS:@.*]] = private constant [5 x i8] c"x\00y\00\00" // CHECK: @_T015generic_structs23DynamicWithRequirementsVMn = hidden constant <{ {{.*}} i32 }> <{ // -- name // CHECK-SAME: [44 x i8]* [[DYNAMICWITHREQUIREMENTS_NAME]] // -- field count // CHECK-SAME: i32 2, // -- field offset vector offset // CHECK-SAME: i32 3, // -- field names // CHECK-SAME: [5 x i8]* [[DYNAMICWITHREQUIREMENTS_FIELDS]] // -- generic metadata pattern // CHECK-SAME: i32 add ({{.*}}@_T015generic_structs23DynamicWithRequirementsVMP{{.*}}, i32 1) // -- generic parameter vector offset // CHECK-SAME: i32 5, // -- generic requirements count; generic arguments count; flags; generic parameter witness counts // CHECK-SAME: i32 4, i32 2, i32 0 // CHECK-SAME: }> // CHECK: @_T015generic_structs23DynamicWithRequirementsVMP = internal global <{ {{.*}} }> <{ // -- field offset vector; generic parameter vector // CHECK: i64 0, i64 0, %swift.type* null, %swift.type* null, i8** null, i8** null, // CHECK: }> // -- Fixed-layout struct metadata contains fixed field offsets // CHECK: @_T015generic_structs6IntishVMf = internal constant <{ {{.*}} i64 }> <{ // CHECK: i64 0 // CHECK: }> // CHECK: @_T015generic_structs7CharethVMf = internal constant <{ {{.*}} i64 }> <{ // CHECK: i64 0 // CHECK: }> // CHECK: @_T015generic_structs8StringlyVMf = internal constant <{ {{.*}} i64, i64, i64 }> <{ // CHECK: i64 0, i64 8, i64 16 // CHECK: }> struct SingleDynamic { var x : T } protocol Req1 { associatedtype Assoc1 } protocol Req2 {} struct DynamicWithRequirements { var x : T var y : U } struct Intish { var value : Builtin.Int64 } struct Chareth { var value : Builtin.Int21 } struct Byteful { var value : Builtin.Int8 } struct Stringly { var owner : Builtin.NativeObject var base : Builtin.RawPointer var size : Builtin.Int64 } // CHECK-LABEL: define{{( protected)?}} swiftcc { i64, i32 } @concrete_instances(i64, i32) {{.*}} { // CHECK: entry: // CHECK: %2 = trunc i32 %1 to i21 // CHECK: %3 = zext i21 %2 to i32 // CHECK: %4 = insertvalue { i64, i32 } undef, i64 %0, 0 // CHECK: %5 = insertvalue { i64, i32 } %4, i32 %3, 1 // CHECK: ret { i64, i32 } %5 // CHECK: } sil @concrete_instances : $(SingleDynamic, SingleDynamic) -> (Intish, Chareth) { entry(%0 : $SingleDynamic, %1 : $SingleDynamic): %a = struct_extract %0 : $SingleDynamic, #SingleDynamic.x %b = struct_extract %1 : $SingleDynamic, #SingleDynamic.x %c = tuple (%a : $Intish, %b : $Chareth) return %c : $(Intish, Chareth) } struct ComplexDynamic { var a, a2 : Byteful var b : U var c : SingleDynamic var d : Chareth } // CHECK-LABEL: define{{( protected)?}} swiftcc void @explode_complex_dynamic sil @explode_complex_dynamic : $ (@in ComplexDynamic, @inout Byteful, @inout A, @inout B, @inout Chareth) -> () { entry(%0 : $*ComplexDynamic, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Chareth): %a = struct_element_addr %0 : $*ComplexDynamic, #ComplexDynamic.a2 // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3 // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 2 // CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8 // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 [[FIELD_OFFSET]] // CHECK: bitcast i8* [[BYTE_OFFSET]] to %swift.opaque* %b = struct_element_addr %0 : $*ComplexDynamic, #ComplexDynamic.b // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3 // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 3 // CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8 // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 [[FIELD_OFFSET]] // CHECK: bitcast i8* [[BYTE_OFFSET]] to %T15generic_structs13SingleDynamicV %5 = struct_element_addr %0 : $*ComplexDynamic, #ComplexDynamic.c %c = struct_element_addr %5 : $*SingleDynamic, #SingleDynamic.x // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3 // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 4 // CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8 // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 [[FIELD_OFFSET]] // CHECK: bitcast i8* [[BYTE_OFFSET]] to %T15generic_structs7CharethV %d = struct_element_addr %0 : $*ComplexDynamic, #ComplexDynamic.d copy_addr %a to %1 : $*Byteful copy_addr %b to %2 : $*A copy_addr %c to %3 : $*B copy_addr %d to %4 : $*Chareth %v = tuple () return %v : $() } // Check that we directly delegate buffer witnesses to a single dynamic field: // destroyBuffer // CHECK-LABEL: define linkonce_odr hidden void @_T015generic_structs13SingleDynamicVwXX([24 x i8]* %buffer, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** %T.valueWitnesses // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to void ([24 x i8]*, %swift.type*)* // CHECK-NEXT: call void [[FN]]([24 x i8]* %buffer, %swift.type* %T) // CHECK-NEXT: ret void // initializeBufferWithCopyOfBuffer // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwCP([24 x i8]* %dest, [24 x i8]* %src, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 1 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]], // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %dest, [24 x i8]* %src, %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}} // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // projectBuffer // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwpr([24 x i8]* %buffer, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %buffer, %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}} // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // deallocateBuffer // CHECK-LABEL: define linkonce_odr hidden void @_T015generic_structs13SingleDynamicVwde([24 x i8]* %buffer, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 3 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to void ([24 x i8]*, %swift.type*)* // CHECK-NEXT: call void [[FN]]([24 x i8]* %buffer, %swift.type* %T) // CHECK-NEXT: ret void // initializeBufferWithCopy // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwCp([24 x i8]* %dest, %swift.opaque* %src, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: [[T0:%.*]] = bitcast %swift.opaque* %src to {{.*}}* // CHECK: [[SRC:%.*]] = bitcast {{.*}}* [[T0]] to %swift.opaque* // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 5 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]], // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %dest, %swift.opaque* [[SRC]], %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}}* // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}}* [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // initializeBufferWithTake // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwTk([24 x i8]* %dest, %swift.opaque* %src, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: [[T0:%.*]] = bitcast %swift.opaque* %src to {{.*}}* // CHECK: [[SRC:%.*]] = bitcast {{.*}}* [[T0]] to %swift.opaque* // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 8 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]], // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %dest, %swift.opaque* [[SRC]], %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}}* // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}}* [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // allocateBuffer // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwal([24 x i8]* %buffer, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 11 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %buffer, %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}} // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // initializeBufferWithTakeOfBuffer // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T015generic_structs13SingleDynamicVwTK([24 x i8]* %dest, [24 x i8]* %src, %swift.type* %"SingleDynamic") {{.*}} { // CHECK: %T = load %swift.type*, // CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8*** // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 12 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]], // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* %dest, [24 x i8]* %src, %swift.type* %T) // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}} // CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque* // CHECK-NEXT: ret %swift.opaque* [[T2]] // CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_SingleDynamic(%swift.type_pattern*, i8**) // CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type** // CHECK: %T = load %swift.type*, %swift.type** [[T0]], align 8 // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1) // CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8** // Fill type argument. // CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4 // CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8* // CHECK: store i8* [[T0]], i8** [[T1]], align 8 // Fill vwtable reference. // CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 6 // CHECK: [[VWTABLE_VAL:%.*]] = bitcast i8** [[VWTABLE_ADDR]] to i8* // CHECK: [[VWTABLE_SLOT_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 -1 // CHECK: store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8 // Lay out fields. // CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64* // CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i32 3 // CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0 // CHECK: call void @swift_initStructMetadata_UniversalStrategy(i64 1, i8*** [[TYPES]], i64* [[T1]], i8** [[VWTABLE_ADDR]]) // CHECK: ret %swift.type* [[METADATA]] // CHECK: } protocol HasAssociatedType { associatedtype Assoc } protocol ParentHasAssociatedType : HasAssociatedType { associatedtype Assoc : HasAssociatedType } struct GenericLayoutWithAssocType { var x: T.Assoc var y: T.Assoc.Assoc } // CHECK-LABEL: define private %swift.type* @create_generic_metadata_GenericLayoutWithAssocType( // CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type** // CHECK: %T = load %swift.type*, %swift.type** [[T0]], align 8 // CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1 // CHECK: [[T2:%.*]] = bitcast %swift.type** [[T1]] to i8*** // CHECK: %T.ParentHasAssociatedType = load i8**, i8*** [[T2]], // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata // CHECK: [[T0:%.*]] = load i8*, i8** %T.ParentHasAssociatedType // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i8** // CHECK: [[T2:%.*]] = load i8*, i8** [[T1]], align 8, !invariant.load // CHECK: [[T3:%.*]] = bitcast i8* [[T2]] to %swift.type* // CHECK: %T.Assoc = call %swift.type* [[T3]](%swift.type* %T, i8** [[T1]]) // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.ParentHasAssociatedType, i32 2 // CHECK: [[T1:%.*]] = load i8*, i8** [[T0]], // CHECK: [[T2:%.*]] = bitcast i8* [[T1]] to i8** (%swift.type*, %swift.type*, i8**)* // CHECK: %T.Assoc.HasAssociatedType = call i8** [[T2]](%swift.type* %T.Assoc, %swift.type* %T, i8** %T.ParentHasAssociatedType) // CHECK: [[T0:%.*]] = load i8*, i8** %T.Assoc.HasAssociatedType, // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to %swift.type* (%swift.type*, i8**)* // CHECK: %T.Assoc.Assoc = call %swift.type* [[T1]](%swift.type* %T.Assoc, i8** %T.Assoc.HasAssociatedType)