blob: c8d4fea682c748b782635890b349cd7537831ef2 [file] [log] [blame]
// RUN: rm -rf %t && mkdir -p %t
// RUN: %utils/chex.py < %s > %t/generic_structs.sil
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %t/generic_structs.sil -emit-ir | %FileCheck %t/generic_structs.sil
// 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: @"$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, flags, stride
// CHECK-SAME: i8* null, i8* null, i8* null
// -- extra inhabitants
// CHECK-SAME: i8* null,
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S15generic_structs13SingleDynamicVwxs" to i8*),
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S15generic_structs13SingleDynamicVwxg" to i8*)]
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00"
// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\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,
// -- field names
// CHECK-SAME: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
// -- generic parameter vector offset
// CHECK-SAME: i32 2,
// -- generic params, requirements, key args, extra args
// CHECK-SAME: i32 1, i32 0, i32 1, i32 0
// -- generic parameters
// CHECK-SAME: <i8 0x80>
// CHECK-SAME: }>
// CHECK: @"$S15generic_structs13SingleDynamicVMP" = internal global <{ {{.*}} }> <{
// -- template header
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
// CHECK-SAME: i32 48, i16 1, i16 16, [{{[0-9]+}} x i8*] zeroinitializer,
// -- vwtable pointer
// CHECK-SAME: @"$S15generic_structs13SingleDynamicVWV"
// -- address point
// CHECK-SAME: i64 1, {{.*}}* @"$S15generic_structs13SingleDynamicVMn"
// -- field offset vector; generic parameter vector
// CHECK-SAME: %swift.type* null, i64 0 }>
// -- 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: [[DYNAMICWITHREQUIREMENTS_FIELDS:@.*]] = private constant [5 x i8] c"x\00y\00\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,
// -- field names
// CHECK-SAME: [5 x i8]* [[DYNAMICWITHREQUIREMENTS_FIELDS]]
// -- generic parameter vector offset
// CHECK-SAME: i32 2,
// -- generic params, requirements, key args, extra args
// CHECK-SAME: i32 2, i32 2, i32 2, i32 2,
// -- generic parameters
// CHECK-SAME: <i8 0x80>, <i8 0x80>,
// -- generic requirement
// -- protocol requirement with extra arg
// CHECK-SAME: i32 64
// -- param 0
// CHECK-SAME: i32 0
// -- protocol Req1
// CHECK-SAME: %swift.protocol* @"$S15generic_structs4Req1Mp"
// -- protocol requirement with extra arg
// CHECK-SAME: i32 64
// -- param 1
// CHECK-SAME: i32 2
// -- protocol Req2
// CHECK-SAME: %swift.protocol* @"$S15generic_structs4Req2Mp"
// CHECK-SAME: }>
// CHECK: @"$S15generic_structs23DynamicWithRequirementsVMP" = internal global <{ {{.*}} }> <{
// -- field offset vector; generic parameter vector
// CHECK: %swift.type* null, %swift.type* null, i8** null, i8** null, i64 0, i64 0 }>
// -- Fixed-layout struct metadata contains fixed field offsets
// CHECK: @"$S15generic_structs6IntishVMf" = internal constant <{ {{.*}} i64 }> <{
// CHECK-SAME: i64 0
// CHECK-SAME: }>
// CHECK: @"$S15generic_structs7CharethVMf" = internal constant <{ {{.*}} i64 }> <{
// CHECK-SAME: i64 0
// CHECK-SAME: }>
// CHECK: @"$S15generic_structs8StringlyVMf" = internal constant <{ {{.*}} i64, i64, i64 }> <{
// CHECK-SAME: i64 0, i64 8, i64 16
// CHECK-SAME: }>
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{{( 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<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{{( 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 i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 4
// 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<A, B>, #ComplexDynamic.b
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 4
// 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<A, B>, #ComplexDynamic.c
%c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 4
// 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<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 that we directly delegate buffer witnesses to a single dynamic field:
// initializeBufferWithCopyOfBuffer
// CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @"$S15generic_structs13SingleDynamicVwCP"([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
// 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 %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]]
// initializeBufferWithTakeOfBuffer
// CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @"$S15generic_structs13SingleDynamicVwTK"([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
// 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 6
// 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]* 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]]
// 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]], i64 2
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
// CHECK: store i8* [[T0]], i8** [[T1]], align 8
// Lay out fields.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 3
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
// CHECK: call void @swift_initStructMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[TYPES]], i64* [[T1]])
// CHECK: ret %swift.type* [[METADATA]]
// CHECK: }
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 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_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.ParentHasAssociatedType, i32 1
// CHECK: [[T0:%.*]] = load i8*, i8** [[T0_GEP]]
// CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i8**
// CHECK: [[T2_GEP:%.*]] = getelementptr inbounds i8*, i8** [[T1]], i32 1
// CHECK: [[T2:%.*]] = load i8*, i8** [[T2_GEP]], 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 3
// 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_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.Assoc.HasAssociatedType, i32 1
// CHECK: [[T0:%.*]] = load i8*, i8** [[T0_GEP]]
// 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)