1*67e74705SXin Li // RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li // This isn't really testing anything ARM-specific; it's just a convenient 4*67e74705SXin Li // 32-bit platform. 5*67e74705SXin Li 6*67e74705SXin Li #define SWIFTCALL __attribute__((swiftcall)) 7*67e74705SXin Li #define OUT __attribute__((swift_indirect_result)) 8*67e74705SXin Li #define ERROR __attribute__((swift_error_result)) 9*67e74705SXin Li #define CONTEXT __attribute__((swift_context)) 10*67e74705SXin Li 11*67e74705SXin Li /*****************************************************************************/ 12*67e74705SXin Li /********************************** LOWERING *********************************/ 13*67e74705SXin Li /*****************************************************************************/ 14*67e74705SXin Li 15*67e74705SXin Li #define TEST(TYPE) \ 16*67e74705SXin Li extern "C" SWIFTCALL TYPE return_##TYPE(void) { \ 17*67e74705SXin Li TYPE result = {}; \ 18*67e74705SXin Li return result; \ 19*67e74705SXin Li } \ 20*67e74705SXin Li extern "C" SWIFTCALL void take_##TYPE(TYPE v) { \ 21*67e74705SXin Li } \ 22*67e74705SXin Li extern "C" void test_##TYPE() { \ 23*67e74705SXin Li take_##TYPE(return_##TYPE()); \ 24*67e74705SXin Li } 25*67e74705SXin Li 26*67e74705SXin Li /*****************************************************************************/ 27*67e74705SXin Li /*********************************** STRUCTS *********************************/ 28*67e74705SXin Li /*****************************************************************************/ 29*67e74705SXin Li 30*67e74705SXin Li typedef struct { 31*67e74705SXin Li } struct_empty; 32*67e74705SXin Li TEST(struct_empty); 33*67e74705SXin Li // CHECK-LABEL: define {{.*}} @return_struct_empty() 34*67e74705SXin Li // CHECK: ret void 35*67e74705SXin Li // CHECK-LABEL: define {{.*}} @take_struct_empty() 36*67e74705SXin Li // CHECK: ret void 37*67e74705SXin Li 38*67e74705SXin Li // This is only properly testable in C++ because it relies on empty structs 39*67e74705SXin Li // actually taking up space in a structure without requiring any extra data 40*67e74705SXin Li // to be passed. 41*67e74705SXin Li typedef struct { 42*67e74705SXin Li int x; 43*67e74705SXin Li struct_empty padding[2]; 44*67e74705SXin Li char c1; 45*67e74705SXin Li float f0; 46*67e74705SXin Li float f1; 47*67e74705SXin Li } struct_1; 48*67e74705SXin Li TEST(struct_1); 49*67e74705SXin Li // CHECK-LABEL: define {{.*}} @return_struct_1() 50*67e74705SXin Li // CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4 51*67e74705SXin Li // CHECK: @llvm.memset 52*67e74705SXin Li // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, \[2 x i8\], i8, \[1 x i8\], float, float }]]* 53*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 54*67e74705SXin Li // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4 55*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 56*67e74705SXin Li // CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align 2 57*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 58*67e74705SXin Li // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4 59*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 60*67e74705SXin Li // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4 61*67e74705SXin Li // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8, float, float }]] undef, i32 [[FIRST]], 0 62*67e74705SXin Li // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i8 [[SECOND]], 1 63*67e74705SXin Li // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2 64*67e74705SXin Li // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3 65*67e74705SXin Li // CHECK: ret [[UAGG]] [[T3]] 66*67e74705SXin Li // CHECK-LABEL: define {{.*}} @take_struct_1(i32, i8, float, float) 67*67e74705SXin Li // CHECK: [[V:%.*]] = alloca [[REC]], align 4 68*67e74705SXin Li // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* 69*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 70*67e74705SXin Li // CHECK: store i32 %0, i32* [[T0]], align 4 71*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 72*67e74705SXin Li // CHECK: store i8 %1, i8* [[T0]], align 2 73*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 74*67e74705SXin Li // CHECK: store float %2, float* [[T0]], align 4 75*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 76*67e74705SXin Li // CHECK: store float %3, float* [[T0]], align 4 77*67e74705SXin Li // CHECK: ret void 78*67e74705SXin Li // CHECK-LABEL: define void @test_struct_1() 79*67e74705SXin Li // CHECK: [[TMP:%.*]] = alloca [[REC]], align 4 80*67e74705SXin Li // CHECK: [[CALL:%.*]] = call [[SWIFTCC:swiftcc]] [[UAGG]] @return_struct_1() 81*67e74705SXin Li // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* 82*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 83*67e74705SXin Li // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 84*67e74705SXin Li // CHECK: store i32 [[T1]], i32* [[T0]], align 4 85*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 86*67e74705SXin Li // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 87*67e74705SXin Li // CHECK: store i8 [[T1]], i8* [[T0]], align 2 88*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 89*67e74705SXin Li // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2 90*67e74705SXin Li // CHECK: store float [[T1]], float* [[T0]], align 4 91*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 92*67e74705SXin Li // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3 93*67e74705SXin Li // CHECK: store float [[T1]], float* [[T0]], align 4 94*67e74705SXin Li // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* 95*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 96*67e74705SXin Li // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4 97*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 98*67e74705SXin Li // CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align 2 99*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 100*67e74705SXin Li // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4 101*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 102*67e74705SXin Li // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4 103*67e74705SXin Li // CHECK: call [[SWIFTCC]] void @take_struct_1(i32 [[FIRST]], i8 [[SECOND]], float [[THIRD]], float [[FOURTH]]) 104*67e74705SXin Li // CHECK: ret void 105*67e74705SXin Li 106*67e74705SXin Li struct struct_indirect_1 { 107*67e74705SXin Li int x; 108*67e74705SXin Li ~struct_indirect_1(); 109*67e74705SXin Li }; 110*67e74705SXin Li TEST(struct_indirect_1) 111*67e74705SXin Li 112*67e74705SXin Li // CHECK-LABEL: define {{.*}} void @return_struct_indirect_1({{.*}} noalias sret 113*67e74705SXin Li 114*67e74705SXin Li // Should not be byval. 115*67e74705SXin Li // CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}}) 116