| // RUN: %empty-directory(%t) |
| // RUN: %{python} %utils/chex.py < %s > %t/generic_structs.sil |
| // RUN: %target-swift-frontend -disable-type-layout -disable-generic-metadata-prespecialization %t/generic_structs.sil -emit-ir | %FileCheck %t/generic_structs.sil |
| |
| // REQUIRES: CPU=x86_64 |
| |
| import Builtin |
| |
| // -- Generic structs with fixed layout should have no completion function |
| // and emit the field offset vector as part of the pattern. |
| // CHECK: [[PATTERN:@.*]] = internal constant <{ i32, i32, i32, [4 x i8] }> <{ i32 0, i32 1, i32 8, [4 x i8] zeroinitializer }>, align 8 |
| // CHECK-LABEL: @"$s15generic_structs18FixedLayoutGenericVMP" = internal constant <{ {{.*}} }> <{ |
| // -- instantiation function |
| // CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s15generic_structs18FixedLayoutGenericVMi" |
| // -- completion function |
| // CHECK-SAME: i32 0, |
| // -- pattern flags |
| // CHECK-SAME: <i32 0x4000_0001>, |
| // -- vwtable pointer |
| // CHECK-SAME: @"$s15generic_structs18FixedLayoutGenericVWV" |
| // -- extra data pattern |
| // CHECK-SAME: <{ i32, i32, i32, [4 x i8] }>* [[PATTERN]] |
| // CHECK-SAME: i16 1, |
| // CHECK-SAME: i16 2 }> |
| |
| // -- Generic structs with dynamic layout contain the vwtable pattern as part |
| // of the metadata pattern, and no independent vwtable symbol |
| // CHECK: @"$s15generic_structs13SingleDynamicVWV" = internal constant |
| // CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$s15generic_structs13SingleDynamicVwCP" to i8*), |
| // -- ... |
| // -- placeholder for size, stride, flags |
| // CHECK-SAME: i64 0, |
| // CHECK-SAME: i64 0, |
| // CHECK-SAME: i32 4194304, |
| // CHECK-SAME: i32 0 } |
| |
| // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 |
| // CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00" |
| // CHECK: @"$s15generic_structs13SingleDynamicVMn" = hidden constant |
| // -- flags: struct, unique, generic |
| // CHECK-SAME: <i32 0x0000_00D1> |
| // -- name |
| // CHECK-SAME: [14 x i8]* [[SINGLEDYNAMIC_NAME]] |
| // -- field count |
| // CHECK-SAME: i32 1, |
| // -- field offset vector offset |
| // CHECK-SAME: i32 3, |
| // -- generic instantiation info |
| // CHECK-SAME: [{{[0-9]+}} x i8*]* @"$s15generic_structs13SingleDynamicVMI" |
| // CHECK-SAME: @"$s15generic_structs13SingleDynamicVMP" |
| // -- generic params, requirements, key args, extra args |
| // CHECK-SAME: i16 1, i16 0, i16 1, i16 0 |
| // -- generic parameters |
| // CHECK-SAME: <i8 0x80> |
| // CHECK-SAME: }> |
| // CHECK: @"$s15generic_structs13SingleDynamicVMP" = internal constant <{ {{.*}} }> <{ |
| // -- instantiation function |
| // CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s15generic_structs13SingleDynamicVMi" |
| // -- vwtable pointer |
| // CHECK-SAME: @"$s15generic_structs13SingleDynamicVWV" |
| |
| // -- Nominal type descriptor for generic struct with protocol requirements |
| // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 |
| // CHECK: [[DYNAMICWITHREQUIREMENTS_NAME:@.*]] = private constant [24 x i8] c"DynamicWithRequirements\00" |
| // CHECK: @"$s15generic_structs23DynamicWithRequirementsVMn" = hidden constant <{ {{.*}} i32 }> <{ |
| // -- flags: struct, unique, generic |
| // CHECK-SAME: <i32 0x0000_00D1> |
| // -- name |
| // CHECK-SAME: [24 x i8]* [[DYNAMICWITHREQUIREMENTS_NAME]] |
| // -- field count |
| // CHECK-SAME: i32 2, |
| // -- field offset vector offset |
| // CHECK-SAME: i32 6, |
| // -- generic params, requirements, key args, extra args |
| // CHECK-SAME: i16 2, i16 2, i16 4, i16 0, |
| // -- generic parameters |
| // CHECK-SAME: <i8 0x80>, <i8 0x80>, |
| // -- generic requirement |
| // -- protocol requirement with key arg |
| // CHECK-SAME: i32 128 |
| // -- param 0 |
| // CHECK-SAME: i32 0 |
| // -- protocol Req1 |
| // CHECK-SAME: @"$s15generic_structs4Req1Mp" |
| |
| // -- protocol requirement with key arg |
| // CHECK-SAME: i32 128 |
| // -- param 1 |
| // CHECK-SAME: i32 2 |
| // -- protocol Req2 |
| // CHECK-SAME: @"$s15generic_structs4Req2Mp" |
| // CHECK-SAME: }> |
| |
| // CHECK: @"$s15generic_structs23DynamicWithRequirementsVMP" = internal constant <{ {{.*}} }> <{ |
| |
| // -- Fixed-layout struct metadata contains fixed field offsets |
| // CHECK: @"$s15generic_structs6IntishVMf" = internal constant <{ {{.*}} i32, [4 x i8] }> <{ |
| // CHECK-SAME: i32 0 |
| // CHECK-SAME: }> |
| // CHECK: @"$s15generic_structs7CharethVMf" = internal constant <{ {{.*}} i32, [4 x i8] }> <{ |
| // CHECK-SAME: i32 0 |
| // CHECK-SAME: }> |
| // CHECK: @"$s15generic_structs8StringlyVMf" = internal constant <{ {{.*}} i32, i32, i32, [4 x i8] }> <{ |
| // CHECK-SAME: i32 0, i32 8, i32 16, [4 x i8] zeroinitializer |
| // CHECK-SAME: }> |
| |
| struct FixedLayoutGeneric<T> { |
| var x: Byteful |
| var y: Byteful |
| var z: Intish |
| } |
| |
| struct SingleDynamic<T> { |
| var x : T |
| } |
| |
| protocol Req1 { associatedtype Assoc1 } |
| protocol Req2 {} |
| |
| struct DynamicWithRequirements<T: Req1, U: Req2> { |
| 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{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i32 } @concrete_instances(i64 %0, i32 %1) {{.*}} { |
| // 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<Intish>, SingleDynamic<Chareth>) -> (Intish, Chareth) { |
| entry(%0 : $SingleDynamic<Intish>, %1 : $SingleDynamic<Chareth>): |
| %a = struct_extract %0 : $SingleDynamic<Intish>, #SingleDynamic.x |
| %b = struct_extract %1 : $SingleDynamic<Chareth>, #SingleDynamic.x |
| %c = tuple (%a : $Intish, %b : $Chareth) |
| return %c : $(Intish, Chareth) |
| } |
| |
| struct ComplexDynamic<U, V> { |
| var a, a2 : Byteful |
| var b : U |
| var c : SingleDynamic<V> |
| var d : Chareth |
| } |
| |
| // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @explode_complex_dynamic |
| sil @explode_complex_dynamic : $<A, B> (@in ComplexDynamic<A, B>, @inout Byteful, @inout A, @inout B, @inout Chareth) -> () { |
| entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Chareth): |
| %a = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.a2 |
| |
| // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32* |
| // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 10 |
| // CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8 |
| // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* |
| // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]] |
| // CHECK: bitcast i8* [[BYTE_OFFSET]] to %swift.opaque* |
| %b = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.b |
| |
| // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32* |
| // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 11 |
| // CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8 |
| // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* |
| // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]] |
| // CHECK: bitcast i8* [[BYTE_OFFSET]] to %T15generic_structs13SingleDynamicV |
| %5 = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.c |
| %c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x |
| |
| // CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32* |
| // CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 12 |
| // CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8 |
| // CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8* |
| // CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]] |
| // CHECK: bitcast i8* [[BYTE_OFFSET]] to %T15generic_structs7CharethV |
| %d = struct_element_addr %0 : $*ComplexDynamic<A, B>, #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-LABEL: define{{( protected)?}} internal %swift.type* @"$s15generic_structs13SingleDynamicVMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) |
| // 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_descriptor* %0, i8** %1, i8* %2, i64 16) |
| // CHECK-NEXT: ret %swift.type* [[METADATA]] |
| // CHECK: } |
| |
| // CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s15generic_structs13SingleDynamicVMr" |
| // CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8* %0, i8** %1) {{.*}} { |
| // Lay out fields. |
| // CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i32* |
| // CHECK: [[T1:%.*]] = getelementptr inbounds i32, i32* [[T0]], i64 6 |
| // CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0 |
| // CHECK: call void @swift_initStructMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[TYPES]], i32* [[T1]]) |
| // CHECK: ret %swift.metadata_response |
| // CHECK: } |
| |
| // Check that we directly delegate buffer witnesses to a single dynamic field: |
| |
| // initializeBufferWithCopyOfBuffer |
| // CHECK-LABEL: define internal %swift.opaque* @"$s15generic_structs13SingleDynamicVwCP"([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %"SingleDynamic<T>") {{.*}} { |
| // CHECK: %T = load %swift.type*, |
| // CHECK: [[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 %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* |
| // CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* noalias %dest, [24 x i8]* noalias %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]] |
| |
| |
| protocol HasAssociatedType { |
| associatedtype Assoc |
| } |
| protocol ParentHasAssociatedType : HasAssociatedType { |
| associatedtype Assoc : HasAssociatedType |
| } |
| |
| struct GenericLayoutWithAssocType<T: ParentHasAssociatedType> { |
| var x: T.Assoc |
| var y: T.Assoc.Assoc |
| } |
| // CHECK-LABEL: define internal %swift.type* @"$s15generic_structs26GenericLayoutWithAssocTypeVMi"( |
| // 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-LABEL: define internal swiftcc %swift.metadata_response @"$s15generic_structs26GenericLayoutWithAssocTypeVMr"( |
| |
| // CHECK: [[T0_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.ParentHasAssociatedType, i32 1 |
| // CHECK: [[T0:%.*]] = load i8*, i8** [[T0_GEP]] |
| // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i8** |
| // CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, i8** %T.HasAssociatedType, %swift.type* %T, %swift.protocol_requirement* @"$s15generic_structs17HasAssociatedTypeTL", %swift.protocol_requirement* @"$s5Assoc15generic_structs17HasAssociatedTypePTl") |
| |
| // CHECK: %T.Assoc = extractvalue %swift.metadata_response [[T4]], 0 |
| // CHECK: %T.Assoc.HasAssociatedType = call swiftcc i8** @swift_getAssociatedConformanceWitness(i8** %T.ParentHasAssociatedType, %swift.type* %T, %swift.type* %T.Assoc, |
| |
| // CHECK: [[T2:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, i8** %T.Assoc.HasAssociatedType, %swift.type* %T.Assoc, %swift.protocol_requirement* @"$s15generic_structs17HasAssociatedTypeTL", %swift.protocol_requirement* @"$s5Assoc15generic_structs17HasAssociatedTypePTl") |
| // CHECK: %T.Assoc.Assoc = extractvalue %swift.metadata_response [[T2]], 0 |