1 | // RUN: %clang_cc1 -triple x86_64-linux-android -emit-llvm -O -o - %s \ |
2 | // RUN: | FileCheck %s --check-prefix=ANDROID --check-prefix=CHECK |
3 | // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -O -o - %s \ |
4 | // RUN: | FileCheck %s --check-prefix=GNU --check-prefix=CHECK |
5 | // RUN: %clang_cc1 -triple x86_64 -emit-llvm -O -o - %s \ |
6 | // RUN: | FileCheck %s --check-prefix=GNU --check-prefix=CHECK |
7 | // NaCl is an example of a target for which long double is the same as double. |
8 | // RUN: %clang_cc1 -triple x86_64-nacl -emit-llvm -O -o - %s \ |
9 | // RUN: | FileCheck %s --check-prefix=NACL --check-prefix=CHECK |
10 | |
11 | // Android uses fp128 for long double but other x86_64 targets use x86_fp80. |
12 | |
13 | long double dataLD = 1.0L; |
14 | // ANDROID: @dataLD = local_unnamed_addr global fp128 0xL00000000000000003FFF000000000000, align 16 |
15 | // GNU: @dataLD = local_unnamed_addr global x86_fp80 0xK3FFF8000000000000000, align 16 |
16 | |
17 | long double _Complex dataLDC = {1.0L, 1.0L}; |
18 | // ANDROID: @dataLDC = local_unnamed_addr global { fp128, fp128 } { fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000003FFF000000000000 }, align 16 |
19 | // GNU: @dataLDC = local_unnamed_addr global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16 |
20 | |
21 | long double TestLD(long double x) { |
22 | return x * x; |
23 | // ANDROID: define fp128 @TestLD(fp128 %x) |
24 | // GNU: define x86_fp80 @TestLD(x86_fp80 %x) |
25 | // NACL: define double @TestLD(double %x) |
26 | } |
27 | |
28 | long double _Complex TestLDC(long double _Complex x) { |
29 | return x * x; |
30 | // ANDROID: define void @TestLDC({ fp128, fp128 }* {{.*}}, { fp128, fp128 }* {{.*}} %x) |
31 | // GNU: define { x86_fp80, x86_fp80 } @TestLDC({ x86_fp80, x86_fp80 }* {{.*}} %x) |
32 | // NACL: define { double, double } @TestLDC(double %x{{.*}}, double %x{{.*}}) |
33 | } |
34 | |
35 | typedef __builtin_va_list va_list; |
36 | |
37 | int TestGetVarInt(va_list ap) { |
38 | return __builtin_va_arg(ap, int); |
39 | // Since int can be passed in memory or register there are two branches. |
40 | // CHECK: define i32 @TestGetVarInt( |
41 | // CHECK: br label |
42 | // CHECK: br label |
43 | // CHECK: = phi |
44 | // CHECK: ret i32 |
45 | } |
46 | |
47 | double TestGetVarDouble(va_list ap) { |
48 | return __builtin_va_arg(ap, double); |
49 | // Since double can be passed in memory or register there are two branches. |
50 | // CHECK: define double @TestGetVarDouble( |
51 | // CHECK: br label |
52 | // CHECK: br label |
53 | // CHECK: = phi |
54 | // CHECK: ret double |
55 | } |
56 | |
57 | long double TestGetVarLD(va_list ap) { |
58 | return __builtin_va_arg(ap, long double); |
59 | // fp128 and double can be passed in memory or in register, but x86_fp80 is in |
60 | // memory. |
61 | // ANDROID: define fp128 @TestGetVarLD( |
62 | // GNU: define x86_fp80 @TestGetVarLD( |
63 | // NACL: define double @TestGetVarLD( |
64 | // ANDROID: br label |
65 | // ANDROID: br label |
66 | // NACL: br |
67 | // ANDROID: = phi |
68 | // GNU-NOT: br |
69 | // GNU-NOT: = phi |
70 | // NACL: = phi |
71 | // ANDROID: ret fp128 |
72 | // GNU: ret x86_fp80 |
73 | } |
74 | |
75 | long double _Complex TestGetVarLDC(va_list ap) { |
76 | return __builtin_va_arg(ap, long double _Complex); |
77 | // Pair of fp128 or x86_fp80 are passed as struct in memory. |
78 | // ANDROID: define void @TestGetVarLDC({ fp128, fp128 }* {{.*}}, %struct.__va_list_tag* |
79 | // GNU: define { x86_fp80, x86_fp80 } @TestGetVarLDC( |
80 | // Pair of double can go in SSE registers or memory |
81 | // NACL: define { double, double } @TestGetVarLDC( |
82 | // ANDROID-NOT: br |
83 | // GNU-NOT: br |
84 | // NACL: br |
85 | // ANDROID-NOT: phi |
86 | // GNU-NOT: phi |
87 | // NACL: phi |
88 | // ANDROID: ret void |
89 | // GNU: ret { x86_fp80, x86_fp80 } |
90 | // NACL: ret { double, double } |
91 | } |
92 | |
93 | void TestVarArg(const char *s, ...); |
94 | |
95 | void TestPassVarInt(int x) { |
96 | TestVarArg("A", x); |
97 | // CHECK: define void @TestPassVarInt(i32 %x) |
98 | // CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, i32 %x) |
99 | } |
100 | |
101 | void TestPassVarFloat(float x) { |
102 | TestVarArg("A", x); |
103 | // CHECK: define void @TestPassVarFloat(float %x) |
104 | // CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double % |
105 | } |
106 | |
107 | void TestPassVarDouble(double x) { |
108 | TestVarArg("A", x); |
109 | // CHECK: define void @TestPassVarDouble(double %x) |
110 | // CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double %x |
111 | } |
112 | |
113 | void TestPassVarLD(long double x) { |
114 | TestVarArg("A", x); |
115 | // ANDROID: define void @TestPassVarLD(fp128 %x) |
116 | // ANDROID: call {{.*}} @TestVarArg(i8* {{.*}}, fp128 %x |
117 | // GNU: define void @TestPassVarLD(x86_fp80 %x) |
118 | // GNU: call {{.*}} @TestVarArg(i8* {{.*}}, x86_fp80 %x |
119 | // NACL: define void @TestPassVarLD(double %x) |
120 | // NACL: call {{.*}} @TestVarArg(i8* {{.*}}, double %x |
121 | } |
122 | |
123 | void TestPassVarLDC(long double _Complex x) { |
124 | TestVarArg("A", x); |
125 | // ANDROID: define void @TestPassVarLDC({ fp128, fp128 }* {{.*}} %x) |
126 | // ANDROID: store fp128 %{{.*}}, fp128* % |
127 | // ANDROID-NEXT: store fp128 %{{.*}}, fp128* % |
128 | // ANDROID-NEXT: call {{.*}} @TestVarArg(i8* {{.*}}, { fp128, fp128 }* {{.*}} % |
129 | // GNU: define void @TestPassVarLDC({ x86_fp80, x86_fp80 }* {{.*}} %x) |
130 | // GNU: store x86_fp80 %{{.*}}, x86_fp80* % |
131 | // GNU-NEXT: store x86_fp80 %{{.*}}, x86_fp80* % |
132 | // GNU-NEXT: call {{.*}} @TestVarArg(i8* {{.*}}, { x86_fp80, x86_fp80 }* {{.*}} % |
133 | // NACL: define void @TestPassVarLDC(double %x{{.*}}, double %x{{.*}}) |
134 | // NACL: call {{.*}} @TestVarArg(i8* {{.*}}, double %x{{.*}}, double %x{{.*}}) |
135 | } |
136 | |