1 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
3 
4 // CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
5 // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
6 // CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
7 // CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 }
8 
9 struct __attribute__((trivial_abi)) Small {
10   int *p;
11   Small();
12   ~Small();
13   Small(const Small &) noexcept;
14   Small &operator=(const Small &);
15 };
16 
17 struct __attribute__((trivial_abi)) Large {
18   int *p;
19   int a[128];
20   Large();
21   ~Large();
22   Large(const Large &) noexcept;
23   Large &operator=(const Large &);
24 };
25 
26 struct Trivial {
27   int a;
28 };
29 
30 struct NonTrivial {
31   NonTrivial();
32   ~NonTrivial();
33   int a;
34 };
35 
36 struct HasTrivial {
37   Small s;
38   Trivial m;
39 };
40 
41 struct HasNonTrivial {
42   Small s;
43   NonTrivial m;
44 };
45 
46 // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
47 // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
48 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
49 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32*
50 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
51 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]])
52 // CHECK: ret void
53 // CHECK: }
54 
55 void testParamSmall(Small a) noexcept {
56 }
57 
58 // CHECK: define i64 @_Z15testReturnSmallv()
59 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
60 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]])
61 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
62 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
63 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
64 // CHECK: ret i64 %[[COERCE_VAL_PI]]
65 // CHECK: }
66 
67 Small testReturnSmall() {
68   Small t;
69   return t;
70 }
71 
72 // CHECK: define void @_Z14testCallSmall0v()
73 // CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
74 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
75 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]])
76 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]])
77 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
78 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
79 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
80 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
81 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]])
82 // CHECK: ret void
83 // CHECK: }
84 
85 void testCallSmall0() {
86   Small t;
87   testParamSmall(t);
88 }
89 
90 // CHECK: define void @_Z14testCallSmall1v()
91 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
92 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
93 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
94 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
95 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
96 // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
97 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8
98 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
99 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
100 // CHECK: ret void
101 // CHECK: }
102 
103 void testCallSmall1() {
104   testParamSmall(testReturnSmall());
105 }
106 
107 // CHECK: define void @_Z16testIgnoredSmallv()
108 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
109 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
110 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0
111 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
112 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
113 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]])
114 // CHECK: ret void
115 // CHECK: }
116 
117 void testIgnoredSmall() {
118   testReturnSmall();
119 }
120 
121 // CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]])
122 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]])
123 // CHECK: ret void
124 // CHECK: }
125 
126 void testParamLarge(Large a) noexcept {
127 }
128 
129 // CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]])
130 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]])
131 // CHECK: ret void
132 // CHECK: }
133 
134 Large testReturnLarge() {
135   Large t;
136   return t;
137 }
138 
139 // CHECK: define void @_Z14testCallLarge0v()
140 // CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
141 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
142 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]])
143 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]])
144 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
145 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]])
146 // CHECK: ret void
147 // CHECK: }
148 
149 void testCallLarge0() {
150   Large t;
151   testParamLarge(t);
152 }
153 
154 // CHECK: define void @_Z14testCallLarge1v()
155 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
156 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]])
157 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
158 // CHECK: ret void
159 // CHECK: }
160 
161 void testCallLarge1() {
162   testParamLarge(testReturnLarge());
163 }
164 
165 // CHECK: define void @_Z16testIgnoredLargev()
166 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
167 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]])
168 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]])
169 // CHECK: ret void
170 // CHECK: }
171 
172 void testIgnoredLarge() {
173   testReturnLarge();
174 }
175 
176 // CHECK: define i64 @_Z20testReturnHasTrivialv()
177 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4
178 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0
179 // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4
180 // CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64
181 // CHECK: ret i64 %[[COERCE_VAL_II]]
182 // CHECK: }
183 
184 Trivial testReturnHasTrivial() {
185   Trivial t;
186   return t;
187 }
188 
189 // CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]])
190 // CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]])
191 // CHECK: ret void
192 // CHECK: }
193 
194 NonTrivial testReturnHasNonTrivial() {
195   NonTrivial t;
196   return t;
197 }
198 
199 // CHECK: define void @_Z18testExceptionSmallv()
200 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
201 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8
202 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
203 // CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]])
204 
205 // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}})
206 // CHECK-NEXT: ret void
207 
208 // CHECK: landingpad { i8*, i32 }
209 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
210 // CHECK: br
211 
212 // CHECK: resume { i8*, i32 }
213 
214 void calleeExceptionSmall(Small, Small);
215 
216 void testExceptionSmall() {
217   calleeExceptionSmall(Small(), Small());
218 }
219 
220 // CHECK: define void @_Z18testExceptionLargev()
221 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
222 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8
223 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
224 // CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]])
225 
226 // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]])
227 // CHECK-NEXT: ret void
228 
229 // CHECK: landingpad { i8*, i32 }
230 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
231 // CHECK: br
232 
233 // CHECK: resume { i8*, i32 }
234 
235 void calleeExceptionLarge(Large, Large);
236 
237 void testExceptionLarge() {
238   calleeExceptionLarge(Large(), Large());
239 }
240