mirror of
https://github.com/apple/swift.git
synced 2026-01-17 12:17:35 +01:00
This reverts commit 2262bd579a.
This information isn't necessary for field descriptor lookup,
after all. It's only the fields that need to have generic information,
which is already in the field descriptor.
332 lines
18 KiB
Plaintext
332 lines
18 KiB
Plaintext
// RUN: %target-swift-frontend %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: @_TWVV15generic_structs13SingleDynamic
|
|
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
|
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [34 x i8] c"V15generic_structs13SingleDynamic\00"
|
|
// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00"
|
|
// CHECK: @_TMnV15generic_structs13SingleDynamic = {{(protected )?}}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 ({{.*}}@_TMPV15generic_structs13SingleDynamic{{.*}}, 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: @_TMPV15generic_structs13SingleDynamic = {{(protected )?}}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, {{.*}}* @_TMnV15generic_structs13SingleDynamic
|
|
// -- 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*)* @_TwXXV15generic_structs13SingleDynamic 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*)* @_TwxsV15generic_structs13SingleDynamic to i8*),
|
|
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgV15generic_structs13SingleDynamic to i8*) }>
|
|
// CHECK-NOT: @_TWVV15generic_structs13SingleDynamic
|
|
|
|
// -- 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"V15generic_structs23DynamicWithRequirements\00"
|
|
// CHECK: [[DYNAMICWITHREQUIREMENTS_FIELDS:@.*]] = private constant [5 x i8] c"x\00y\00\00"
|
|
// CHECK: @_TMnV15generic_structs23DynamicWithRequirements = {{(protected )?}}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 ({{.*}}@_TMPV15generic_structs23DynamicWithRequirements{{.*}}, 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: @_TMPV15generic_structs23DynamicWithRequirements = {{(protected )?}}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: @_TMfV15generic_structs6Intish = internal constant <{ {{.*}} i64 }> <{
|
|
// CHECK: i64 0
|
|
// CHECK: }>
|
|
// CHECK: @_TMfV15generic_structs7Chareth = internal constant <{ {{.*}} i64 }> <{
|
|
// CHECK: i64 0
|
|
// CHECK: }>
|
|
// CHECK: @_TMfV15generic_structs8Stringly = internal constant <{ {{.*}} i64, i64, i64 }> <{
|
|
// CHECK: i64 0, i64 8, i64 16
|
|
// CHECK: }>
|
|
|
|
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)?}} { i64, i21 } @concrete_instances(i64, i21) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: %2 = insertvalue { i64, i21 } undef, i64 %0, 0
|
|
// CHECK: %3 = insertvalue { i64, i21 } %2, i21 %1, 1
|
|
// CHECK: ret { i64, i21 } %3
|
|
// 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)?}} 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]], 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 %V15generic_structs14ComplexDynamic* %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]], 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 %V15generic_structs14ComplexDynamic* %0 to i8*
|
|
// CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 [[FIELD_OFFSET]]
|
|
// CHECK: bitcast i8* [[BYTE_OFFSET]] to %V15generic_structs13SingleDynamic
|
|
%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]], 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 %V15generic_structs14ComplexDynamic* %0 to i8*
|
|
// CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 [[FIELD_OFFSET]]
|
|
// CHECK: bitcast i8* [[BYTE_OFFSET]] to %V15generic_structs7Chareth
|
|
%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:
|
|
// destroyBuffer
|
|
// CHECK-LABEL: define linkonce_odr hidden void @_TwXXV15generic_structs13SingleDynamic([24 x i8]* %buffer, %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 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* @_TwCPV15generic_structs13SingleDynamic([24 x i8]* %dest, [24 x i8]* %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 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* @_TwprV15generic_structs13SingleDynamic([24 x i8]* %buffer, %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 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 @_TwdeV15generic_structs13SingleDynamic([24 x i8]* %buffer, %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 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* @_TwCpV15generic_structs13SingleDynamic([24 x i8]* %dest, %swift.opaque* %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
|
|
// 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* @_TwTkV15generic_structs13SingleDynamic([24 x i8]* %dest, %swift.opaque* %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
|
|
// 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* @_TwalV15generic_structs13SingleDynamic([24 x i8]* %buffer, %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 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* @_TwTKV15generic_structs13SingleDynamic([24 x i8]* %dest, [24 x i8]* %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 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: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
|
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
|
|
// 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<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:%.*]] = getelementptr inbounds i8*, i8** %T.ParentHasAssociatedType, i32 1
|
|
// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
|
|
// CHECK: [[T2:%.*]] = bitcast i8* [[T1]] to %swift.type* (%swift.type*, i8**)*
|
|
// CHECK: %T.Assoc = call %swift.type* [[T2]](%swift.type* %T, i8** %T.ParentHasAssociatedType)
|
|
// 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)
|