Clang Project

clang_source_code/test/CodeGen/pass-object-size.c
1// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
2
3typedef unsigned long size_t;
4
5struct Foo {
6  int t[10];
7};
8
9#define PS(N) __attribute__((pass_object_size(N)))
10#define PDS(N) __attribute__((pass_dynamic_object_size(N)))
11
12int gi = 0;
13
14// CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64)
15int ObjectSize0(void *const p PS(0)) {
16  // CHECK-NOT: @llvm.objectsize
17  return __builtin_object_size(p, 0);
18}
19
20// CHECK-LABEL: define i32 @DynamicObjectSize0(i8* %{{.*}}, i64)
21int DynamicObjectSize0(void *const p PDS(0)) {
22  // CHECK-NOT: @llvm.objectsize
23  return __builtin_dynamic_object_size(p, 0);
24}
25
26// CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64)
27int ObjectSize1(void *const p PS(1)) {
28  // CHECK-NOT: @llvm.objectsize
29  return __builtin_object_size(p, 1);
30}
31
32// CHECK-LABEL: define i32 @DynamicObjectSize1(i8* %{{.*}}, i64)
33int DynamicObjectSize1(void *const p PDS(1)) {
34  // CHECK-NOT: @llvm.objectsize
35  return __builtin_dynamic_object_size(p, 1);
36}
37
38// CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64)
39int ObjectSize2(void *const p PS(2)) {
40  // CHECK-NOT: @llvm.objectsize
41  return __builtin_object_size(p, 2);
42}
43
44// CHECK-LABEL: define i32 @DynamicObjectSize2(i8* %{{.*}}, i64)
45int DynamicObjectSize2(void *const p PDS(2)) {
46  // CHECK-NOT: @llvm.objectsize
47  return __builtin_object_size(p, 2);
48}
49
50// CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64)
51int ObjectSize3(void *const p PS(3)) {
52  // CHECK-NOT: @llvm.objectsize
53  return __builtin_object_size(p, 3);
54}
55
56// CHECK-LABEL: define i32 @DynamicObjectSize3(i8* %{{.*}}, i64)
57int DynamicObjectSize3(void *const p PDS(3)) {
58  // CHECK-NOT: @llvm.objectsize
59  return __builtin_object_size(p, 3);
60}
61
62void *malloc(unsigned long) __attribute__((alloc_size(1)));
63
64// CHECK-LABEL: define void @test1
65void test1(unsigned long sz) {
66  struct Foo t[10];
67
68  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
69  gi = ObjectSize0(&t[1]);
70  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
71  gi = ObjectSize1(&t[1]);
72  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
73  gi = ObjectSize2(&t[1]);
74  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
75  gi = ObjectSize3(&t[1]);
76
77  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
78  gi = ObjectSize0(&t[1].t[1]);
79  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
80  gi = ObjectSize1(&t[1].t[1]);
81  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
82  gi = ObjectSize2(&t[1].t[1]);
83  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
84  gi = ObjectSize3(&t[1].t[1]);
85
86  char *ptr = (char *)malloc(sz);
87
88  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8({{.*}}, i1 false, i1 true, i1 true)
89  // CHECK: call i32 @DynamicObjectSize0(i8* %{{.*}}, i64 [[REG]])
90  gi = DynamicObjectSize0(ptr);
91
92  // CHECK: [[WITH_OFFSET:%.*]] = getelementptr
93  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[WITH_OFFSET]], i1 false, i1 true, i1 true)
94  // CHECK: call i32 @DynamicObjectSize0(i8* {{.*}}, i64 [[REG]])
95  gi = DynamicObjectSize0(ptr+10);
96
97  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8({{.*}}, i1 true, i1 true, i1 true)
98  // CHECK: call i32 @DynamicObjectSize2(i8* {{.*}}, i64 [[REG]])
99  gi = DynamicObjectSize2(ptr);
100}
101
102// CHECK-LABEL: define void @test2
103void test2(struct Foo *t) {
104  // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
105  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]])
106  gi = ObjectSize1(&t->t[1]);
107  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
108  gi = ObjectSize3(&t->t[1]);
109}
110
111// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
112int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
113  // CHECK: @llvm.objectsize
114  return __builtin_object_size(p, 0);
115}
116
117// CHECK-LABEL: define i32 @_Z34NoViableOverloadDynamicObjectSize0Pv
118int NoViableOverloadDynamicObjectSize0(void *const p)
119  __attribute__((overloadable)) {
120  // CHECK: @llvm.objectsize
121  return __builtin_object_size(p, 0);
122}
123
124// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv
125int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
126  // CHECK: @llvm.objectsize
127  return __builtin_object_size(p, 1);
128}
129
130// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv
131int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
132  // CHECK: @llvm.objectsize
133  return __builtin_object_size(p, 2);
134}
135
136// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv
137int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
138  // CHECK-NOT: @llvm.objectsize
139  return __builtin_object_size(p, 3);
140}
141
142// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
143// CHECK-NOT: @llvm.objectsize
144int NoViableOverloadObjectSize0(void *const p PS(0))
145    __attribute__((overloadable)) {
146  return __builtin_object_size(p, 0);
147}
148
149int NoViableOverloadDynamicObjectSize0(void *const p PDS(0))
150  __attribute__((overloadable)) {
151  return __builtin_dynamic_object_size(p, 0);
152}
153
154int NoViableOverloadObjectSize1(void *const p PS(1))
155    __attribute__((overloadable)) {
156  return __builtin_object_size(p, 1);
157}
158
159int NoViableOverloadObjectSize2(void *const p PS(2))
160    __attribute__((overloadable)) {
161  return __builtin_object_size(p, 2);
162}
163
164int NoViableOverloadObjectSize3(void *const p PS(3))
165    __attribute__((overloadable)) {
166  return __builtin_object_size(p, 3);
167}
168
169const static int SHOULDNT_BE_CALLED = -100;
170int NoViableOverloadObjectSize0(void *const p PS(0))
171    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
172  return SHOULDNT_BE_CALLED;
173}
174
175int NoViableOverloadObjectSize1(void *const p PS(1))
176    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
177  return SHOULDNT_BE_CALLED;
178}
179
180int NoViableOverloadObjectSize2(void *const p PS(2))
181    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
182  return SHOULDNT_BE_CALLED;
183}
184
185int NoViableOverloadObjectSize3(void *const p PS(3))
186    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
187  return SHOULDNT_BE_CALLED;
188}
189
190// CHECK-LABEL: define void @test3
191void test3() {
192  struct Foo t[10];
193
194  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
195  gi = NoViableOverloadObjectSize0(&t[1]);
196  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
197  gi = NoViableOverloadObjectSize1(&t[1]);
198  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
199  gi = NoViableOverloadObjectSize2(&t[1]);
200  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
201  gi = NoViableOverloadObjectSize3(&t[1]);
202
203  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
204  gi = NoViableOverloadObjectSize0(&t[1].t[1]);
205  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
206  gi = NoViableOverloadObjectSize1(&t[1].t[1]);
207  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
208  gi = NoViableOverloadObjectSize2(&t[1].t[1]);
209  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
210  gi = NoViableOverloadObjectSize3(&t[1].t[1]);
211
212  // CHECK: call i32 @_Z34NoViableOverloadDynamicObjectSize0PvU25pass_dynamic_object_size0(i8* %{{.*}}, i64 360)
213  gi = NoViableOverloadDynamicObjectSize0(&t[1]);
214}
215
216// CHECK-LABEL: define void @test4
217void test4(struct Foo *t) {
218  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
219  gi = NoViableOverloadObjectSize0(&t[1]);
220  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
221  gi = NoViableOverloadObjectSize1(&t[1]);
222  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
223  gi = NoViableOverloadObjectSize2(&t[1]);
224  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
225  gi = NoViableOverloadObjectSize3(&t[1]);
226
227  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
228  gi = NoViableOverloadObjectSize0(&t[1].t[1]);
229  // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
230  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]])
231  gi = NoViableOverloadObjectSize1(&t[1].t[1]);
232  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
233  gi = NoViableOverloadObjectSize2(&t[1].t[1]);
234  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
235  gi = NoViableOverloadObjectSize3(&t[1].t[1]);
236}
237
238void test5() {
239  struct Foo t[10];
240
241  int (*f)(void *) = &NoViableOverloadObjectSize0;
242  gi = f(&t[1]);
243
244  int (*g)(void *) = &NoViableOverloadDynamicObjectSize0;
245  gi = g(&t[1]);
246}
247
248// CHECK-LABEL: define i32 @IndirectObjectSize0
249int IndirectObjectSize0(void *const p PS(0)) {
250  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
251  // CHECK-NOT: @llvm.objectsize
252  return ObjectSize0(p);
253}
254
255// CHECK-LABEL: define i32 @IndirectObjectSize1
256int IndirectObjectSize1(void *const p PS(1)) {
257  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
258  // CHECK-NOT: @llvm.objectsize
259  return ObjectSize1(p);
260}
261
262// CHECK-LABEL: define i32 @IndirectObjectSize2
263int IndirectObjectSize2(void *const p PS(2)) {
264  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
265  // CHECK-NOT: @llvm.objectsize
266  return ObjectSize2(p);
267}
268
269// CHECK-LABEL: define i32 @IndirectObjectSize3
270int IndirectObjectSize3(void *const p PS(3)) {
271  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
272  // CHECK-NOT: @llvm.objectsize
273  return ObjectSize3(p);
274}
275
276int IndirectDynamicObjectSize0(void *const p PDS(0)) {
277  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
278  // CHECK-NOT: @llvm.objectsize
279  return ObjectSize0(p);
280}
281
282int Overload0(void *, size_t, void *, size_t);
283int OverloadNoSize(void *, void *);
284
285int OverloadedObjectSize(void *const p PS(0),
286                         void *const c PS(0))
287    __attribute__((overloadable)) __asm__("Overload0");
288
289int OverloadedObjectSize(void *const p, void *const c)
290    __attribute__((overloadable)) __asm__("OverloadNoSize");
291
292// CHECK-LABEL: define void @test6
293void test6() {
294  int known[10], *opaque;
295
296  // CHECK: call i32 @"\01Overload0"
297  gi = OverloadedObjectSize(&known[0], &known[0]);
298
299  // CHECK: call i32 @"\01Overload0"
300  gi = OverloadedObjectSize(&known[0], opaque);
301
302  // CHECK: call i32 @"\01Overload0"
303  gi = OverloadedObjectSize(opaque, &known[0]);
304
305  // CHECK: call i32 @"\01Overload0"
306  gi = OverloadedObjectSize(opaque, opaque);
307}
308
309int Identity(void *p, size_t i) { return i; }
310
311// CHECK-NOT: define void @AsmObjectSize
312int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
313
314int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
315
316int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
317
318int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
319
320// CHECK-LABEL: define void @test7
321void test7() {
322  struct Foo t[10];
323
324  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
325  gi = AsmObjectSize0(&t[1]);
326  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
327  gi = AsmObjectSize1(&t[1]);
328  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
329  gi = AsmObjectSize2(&t[1]);
330  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
331  gi = AsmObjectSize3(&t[1]);
332
333  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
334  gi = AsmObjectSize0(&t[1].t[1]);
335  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
336  gi = AsmObjectSize1(&t[1].t[1]);
337  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
338  gi = AsmObjectSize2(&t[1].t[1]);
339  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
340  gi = AsmObjectSize3(&t[1].t[1]);
341}
342
343// CHECK-LABEL: define void @test8
344void test8(struct Foo *t) {
345  // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
346  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]])
347  gi = AsmObjectSize1(&t[1].t[1]);
348  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
349  gi = AsmObjectSize3(&t[1].t[1]);
350}
351
352void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
353void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
354void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
355void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
356
357// CHECK-LABEL: define void @test9
358void test9(void *const p __attribute__((pass_object_size(0)))) {
359  // CHECK: @llvm.objectsize
360  DifferingObjectSize2(p);
361
362  // CHECK-NOT: @llvm.objectsize
363  DifferingObjectSize0(p);
364  DifferingObjectSize1(p);
365
366  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
367  DifferingObjectSize3(p);
368}
369
370// CHECK-LABEL: define void @test10
371void test10(void *const p __attribute__((pass_object_size(1)))) {
372  // CHECK: @llvm.objectsize
373  DifferingObjectSize2(p);
374  // CHECK: @llvm.objectsize
375  DifferingObjectSize0(p);
376
377  // CHECK-NOT: @llvm.objectsize
378  DifferingObjectSize1(p);
379
380  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
381  DifferingObjectSize3(p);
382}
383
384// CHECK-LABEL: define void @test11
385void test11(void *const p __attribute__((pass_object_size(2)))) {
386  // CHECK: @llvm.objectsize
387  DifferingObjectSize0(p);
388  // CHECK: @llvm.objectsize
389  DifferingObjectSize1(p);
390
391  // CHECK-NOT: @llvm.objectsize
392  DifferingObjectSize2(p);
393
394  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
395  DifferingObjectSize3(p);
396}
397
398// CHECK-LABEL: define void @test12
399void test12(void *const p __attribute__((pass_object_size(3)))) {
400  // CHECK: @llvm.objectsize
401  DifferingObjectSize0(p);
402  // CHECK: @llvm.objectsize
403  DifferingObjectSize1(p);
404
405  // CHECK-NOT: @llvm.objectsize
406  DifferingObjectSize2(p);
407  DifferingObjectSize3(p);
408}
409
410// CHECK-LABEL: define void @test13
411void test13() {
412  char c[10];
413  unsigned i = 0;
414  char *p = c;
415
416  // CHECK: @llvm.objectsize
417  ObjectSize0(p);
418
419  // Allow side-effects, since they always need to happen anyway. Just make sure
420  // we don't perform them twice.
421  // CHECK: = add
422  // CHECK-NOT: = add
423  // CHECK: @llvm.objectsize
424  // CHECK: call i32 @ObjectSize0
425  ObjectSize0(p + ++i);
426
427  // CHECK: = add
428  // CHECK: @llvm.objectsize
429  // CHECK-NOT: = add
430  // CHECK: call i32 @ObjectSize0
431  ObjectSize0(p + i++);
432}
433
434// There was a bug where variadic functions with pass_object_size would cause
435// problems in the form of failed assertions.
436void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
437
438// CHECK-LABEL: define void @test14
439void test14(char *c) {
440  // CHECK: @llvm.objectsize
441  // CHECK: call void (i8*, i64, ...) @my_sprintf
442  my_sprintf(c);
443
444  // CHECK: @llvm.objectsize
445  // CHECK: call void (i8*, i64, ...) @my_sprintf
446  my_sprintf(c, 1, 2, 3);
447}
448
449void pass_size_unsigned(unsigned *const PS(0));
450
451// Bug: we weren't lowering to the proper @llvm.objectsize for pointers that
452// don't turn into i8*s, which caused crashes.
453// CHECK-LABEL: define void @test15
454void test15(unsigned *I) {
455  // CHECK: @llvm.objectsize.i64.p0i32
456  // CHECK: call void @pass_size_unsigned
457  pass_size_unsigned(I);
458}
459
460void pass_size_as1(__attribute__((address_space(1))) void *const PS(0));
461
462void pass_size_unsigned_as1(
463    __attribute__((address_space(1))) unsigned *const PS(0));
464
465// CHECK-LABEL: define void @test16
466void test16(__attribute__((address_space(1))) unsigned *I) {
467  // CHECK: call i64 @llvm.objectsize.i64.p1i8
468  // CHECK: call void @pass_size_as1
469  pass_size_as1(I);
470  // CHECK: call i64 @llvm.objectsize.i64.p1i32
471  // CHECK: call void @pass_size_unsigned_as1
472  pass_size_unsigned_as1(I);
473}
474
475// This used to cause assertion failures, since we'd try to emit the statement
476// expression (and definitions for `a`) twice.
477// CHECK-LABEL: define void @test17
478void test17(char *C) {
479  // Check for 65535 to see if we're emitting this pointer twice.
480  // CHECK: 65535
481  // CHECK-NOT: 65535
482  // CHECK: @llvm.objectsize.i64.p0i8(i8* [[PTR:%[^,]+]],
483  // CHECK-NOT: 65535
484  // CHECK: call i32 @ObjectSize0(i8* [[PTR]]
485  ObjectSize0(C + ({ int a = 65535; a; }));
486}
487
488// CHECK-LABEL: define void @test18
489void test18(char *const p PDS(0)) {
490  // CHECK-NOT: llvm.objectsize
491  gi = __builtin_dynamic_object_size(p, 0);
492  gi = __builtin_object_size(p, 0);
493}
494