|
| 1 | +// RUN: %swift -triple x86_64-apple-darwin10 -emit-llvm %s | FileCheck %s |
| 2 | + |
| 3 | +// CHECK: [[OPAQUE:%swift.opaque]] = type opaque |
| 4 | +// CHECK: [[TYPE:%swift.type]] = type { |
| 5 | +// CHECK: [[TUPLE_TYPE:%swift.tuple_type]] = type { [[TYPE]], i64, i8*, [0 x %swift.tuple_element_type] } |
| 6 | +// CHECK: %swift.tuple_element_type = type { [[TYPE]]*, i64 } |
| 7 | + |
| 8 | +func dup<T>(x : T) -> (T, T) { return (x,x) } |
| 9 | +// CHECK: define void @_T14generic_tuples3dupU__FT1xQ__TQ_Q__({ [[OPAQUE]] }* noalias sret |
| 10 | +// CHECK: [[ELTS:%.*]] = alloca [2 x [[TYPE]]*], align 8 |
| 11 | +// Get value witnesses for T. |
| 12 | +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TYPE]]* %T to i8*** |
| 13 | +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8*** [[T0]], i64 -1 |
| 14 | +// CHECK-NEXT: %T.value = load i8*** [[T1]], align 8 |
| 15 | +// Project to first element of tuple. |
| 16 | +// CHECK-NEXT: [[FST:%.*]] = bitcast { [[OPAQUE]] }* [[RET:%.*]] to [[OPAQUE]]* |
| 17 | +// Get the tuple metadata. |
| 18 | +// FIXME: maybe this should get passed in? |
| 19 | +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [2 x [[TYPE]]*]* [[ELTS]], i32 0, i32 0 |
| 20 | +// CHECK-NEXT: store [[TYPE]]* %T, [[TYPE]]** [[T0]], align 8 |
| 21 | +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [2 x [[TYPE]]*]* [[ELTS]], i32 0, i32 1 |
| 22 | +// CHECK-NEXT: store [[TYPE]]* %T, [[TYPE]]** [[T1]], align 8 |
| 23 | +// CHECK-NEXT: [[TT_PAIR:%.*]] = call [[TYPE]]* @swift_getTupleTypeMetadata(i64 2, [[TYPE]]** [[T0]], i8* null, i8** null) |
| 24 | +// Pull out the offset of the second element and GEP to that. |
| 25 | +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TYPE]]* [[TT_PAIR]] to [[TUPLE_TYPE]]* |
| 26 | +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[TUPLE_TYPE]]* [[T0]], i64 0, i32 3, i64 1, i32 1 |
| 27 | +// CHECK-NEXT: [[T2:%.*]] = load i64* [[T1]], align 8 |
| 28 | +// CHECK-NEXT: [[T3:%.*]] = bitcast { [[OPAQUE]] }* [[RET]] to i8* |
| 29 | +// CHECK-NEXT: [[T4:%.*]] = getelementptr inbounds i8* [[T3]], i64 [[T2]] |
| 30 | +// CHECK-NEXT: [[SND:%.*]] = bitcast i8* [[T4]] to [[OPAQUE]]* |
| 31 | +// Copy 'x' into the first element. |
| 32 | +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8** %T.value, i32 6 |
| 33 | +// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]], align 8 |
| 34 | +// CHECK-NEXT: [[COPY_FN:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)* |
| 35 | +// CHECK-NEXT: call [[OPAQUE]]* [[COPY_FN]]([[OPAQUE]]* [[FST]], [[OPAQUE]]* [[X:%.*]], [[TYPE]]* %T) |
| 36 | +// Copy 'x' into the second element. |
| 37 | +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8** %T.value, i32 6 |
| 38 | +// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]], align 8 |
| 39 | +// CHECK-NEXT: [[COPY_FN:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)* |
| 40 | +// CHECK-NEXT: call [[OPAQUE]]* [[COPY_FN]]([[OPAQUE]]* [[SND]], [[OPAQUE]]* [[X]], [[TYPE]]* %T) |
| 41 | +// Destroy 'x'. |
| 42 | +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8** %T.value, i32 4 |
| 43 | +// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]], align 8 |
| 44 | +// CHECK-NEXT: [[DESTROY_FN:%.*]] = bitcast i8* [[T1]] to void ([[OPAQUE]]*, [[TYPE]]*)* |
| 45 | +// CHECK-NEXT: call void [[DESTROY_FN]]([[OPAQUE]]* [[X]], [[TYPE]]* %T) |
| 46 | +// CHECK-NEXT: ret void |
0 commit comments