Clang Project

clang_source_code/test/CodeGenCXX/trivial_abi.cpp
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
9struct __attribute__((trivial_abi)) Small {
10  int *p;
11  Small();
12  ~Small();
13  Small(const Small &) noexcept;
14  Small &operator=(const Small &);
15};
16
17struct __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
26struct Trivial {
27  int a;
28};
29
30struct NonTrivial {
31  NonTrivial();
32  ~NonTrivial();
33  int a;
34};
35
36struct HasTrivial {
37  Small s;
38  Trivial m;
39};
40
41struct 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
55void 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
67Small 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
85void 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
103void 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
117void 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
126void 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
134Large 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
149void 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
161void 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
172void 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
184Trivial 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
194NonTrivial 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
214void calleeExceptionSmall(Small, Small);
215
216void 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
235void calleeExceptionLarge(Large, Large);
236
237void testExceptionLarge() {
238  calleeExceptionLarge(Large(), Large());
239}
240