1 #include <stdio.h>
2 #include "libgccjit.h"
3 #include "harness.h"
4
5 /* This testcase checks that gcc_jit_context_new_constructor() works
6 with locals. Tests that constructors can be used as return
7 values or function call values. Test that constructors can have side
8 effects and be assigned to locals.
9 */
10
11 void
12 create_code (gcc_jit_context *ctxt, void *user_data)
13 {
14 gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
15 GCC_JIT_TYPE_INT);
16 gcc_jit_type *pint_type = gcc_jit_type_get_pointer (int_type);
17 gcc_jit_type *double_type = gcc_jit_context_get_type (ctxt,
18 GCC_JIT_TYPE_DOUBLE);
19 gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
20 GCC_JIT_TYPE_FLOAT);
21 gcc_jit_type *bool_type = gcc_jit_context_get_type (ctxt,
22 GCC_JIT_TYPE_BOOL);
23 gcc_jit_type *char_type = gcc_jit_context_get_type (ctxt,
24 GCC_JIT_TYPE_CHAR);
25 gcc_jit_type *size_type = gcc_jit_context_get_type (ctxt,
26 GCC_JIT_TYPE_SIZE_T);
27 gcc_jit_type *voidptr_type = gcc_jit_context_get_type (ctxt,
28 GCC_JIT_TYPE_VOID_PTR);
29 gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt,
30 GCC_JIT_TYPE_VOID);
31
32 /* Make a struct: struct fi { float f; int i;} */
33 gcc_jit_field *fi_f = gcc_jit_context_new_field (ctxt,
34 0,
35 float_type,
36 "f");
37 gcc_jit_field *fi_i = gcc_jit_context_new_field (ctxt,
38 0,
39 int_type,
40 "i");
41 gcc_jit_field *fields[] = {fi_f, fi_i};
42
43 gcc_jit_type *struct_fi_type =
44 gcc_jit_struct_as_type (
45 gcc_jit_context_new_struct_type (ctxt,
46 0,
47 "fi",
48 2,
49 fields));
50
51 /* Make a struct:
52
53 struct bar {
54 int ii;
55 int arr[50];
56 float ff;
57 char cc;
58 }
59 */
60 gcc_jit_field *bar_ff = gcc_jit_context_new_field (ctxt,
61 0,
62 float_type,
63 "ff");
64 gcc_jit_field *bar_ii = gcc_jit_context_new_field (ctxt,
65 0,
66 int_type,
67 "ii");
68 gcc_jit_field *bar_cc = gcc_jit_context_new_field (ctxt,
69 0,
70 char_type,
71 "cc");
72 gcc_jit_type *int50arr_type =
73 gcc_jit_context_new_array_type (ctxt,
74 0,
75 int_type,
76 50);
77 gcc_jit_field *bar_fi = gcc_jit_context_new_field (ctxt,
78 0,
79 int50arr_type,
80 "arr");
81 gcc_jit_field *fields2[] = {bar_ff, bar_fi, bar_ii, bar_cc};
82
83 gcc_jit_type *struct_bar_type =
84 gcc_jit_struct_as_type (
85 gcc_jit_context_new_struct_type (ctxt,
86 0,
87 "bar",
88 4,
89 fields2));
90
91 /* Make an union:
92
93 union ubar {
94 float ff;
95 int ii;
96 };
97 */
98 gcc_jit_field *ubar_ff = gcc_jit_context_new_field (ctxt,
99 0,
100 float_type,
101 "ff");
102 gcc_jit_field *ubar_ii = gcc_jit_context_new_field (ctxt,
103 0,
104 int_type,
105 "ii");
106 gcc_jit_field *fields3[] = {ubar_ff, ubar_ii};
107 gcc_jit_type *ubar = gcc_jit_context_new_union_type (ctxt,
108 0,
109 "ubar",
110 2,
111 fields3);
112
113 (void) ubar;
114 (void) struct_bar_type;
115 (void) struct_fi_type;
116 (void) bool_type;
117 (void) double_type;
118 (void) pint_type;
119 (void) voidptr_type;
120 (void) size_type;
121
122 gcc_jit_function *fn_int_3;
123 { /* int foo () { int local = 3; return local;} */
124 fn_int_3 =
125 gcc_jit_context_new_function (ctxt,
126 0,
127 GCC_JIT_FUNCTION_EXPORTED,
128 int_type,
129 "fn_int_3",
130 0,
131 0,
132 0);
133 gcc_jit_block *block = gcc_jit_function_new_block (fn_int_3, "start");
134 gcc_jit_lvalue *local = gcc_jit_function_new_local (fn_int_3,
135 0,
136 int_type,
137 "local");
138 gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
139 ctxt, int_type, 3);
140
141 gcc_jit_block_add_assignment (block, 0, local, rval);
142
143 gcc_jit_block_end_with_return (block,
144 0,
145 gcc_jit_lvalue_as_rvalue(local));
146 }
147 { /* struct fi foo() { return (struct fi){1,2};} */
148 gcc_jit_function *fn =
149 gcc_jit_context_new_function (ctxt,
150 0,
151 GCC_JIT_FUNCTION_EXPORTED,
152 struct_fi_type,
153 "fn_fi_1_2",
154 0,
155 0,
156 0);
157 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
158
159 gcc_jit_rvalue *rval_f1 = gcc_jit_context_new_rvalue_from_int (
160 ctxt, float_type, 1);
161 gcc_jit_rvalue *rval_i2 = gcc_jit_context_new_rvalue_from_int (
162 ctxt, int_type, 2);
163
164 gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
165 gcc_jit_field *fields[] = {fi_f, fi_i};
166
167 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
168 (ctxt, 0,
169 struct_fi_type,
170 2,
171 fields,
172 vals);
173
174 gcc_jit_block_end_with_return (block,
175 0,
176 ctor);
177 }
178 { /*
179 struct fi foo()
180 {
181 struct fi local = {1,2};
182 local = (struct fi){5,6};
183 return local;
184 }
185 */
186 gcc_jit_function *fn =
187 gcc_jit_context_new_function (ctxt,
188 0,
189 GCC_JIT_FUNCTION_EXPORTED,
190 struct_fi_type,
191 "fn_fi_5_6",
192 0,
193 0,
194 0);
195 gcc_jit_lvalue *local = gcc_jit_function_new_local (fn,
196 0,
197 struct_fi_type,
198 "local");
199 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
200
201 {
202 gcc_jit_rvalue *rval_f1 =
203 gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 1);
204 gcc_jit_rvalue *rval_i2 =
205 gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2);
206
207 gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
208 gcc_jit_field *fields[] = {fi_f, fi_i};
209
210 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
211 (ctxt, 0,
212 struct_fi_type,
213 2,
214 fields,
215 vals);
216 gcc_jit_block_add_assignment (block, 0, local, ctor);
217 }
218 {
219 gcc_jit_rvalue *rval_f1 =
220 gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 5);
221 gcc_jit_rvalue *rval_i2 =
222 gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 6);
223
224 gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
225 gcc_jit_field *fields[] = {fi_f, fi_i};
226
227 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
228 (ctxt, 0,
229 struct_fi_type,
230 2,
231 fields,
232 vals);
233 gcc_jit_block_add_assignment (block, 0, local, ctor);
234 }
235
236 gcc_jit_block_end_with_return (block,
237 0,
238 gcc_jit_lvalue_as_rvalue(local));
239 }
240 { /* struct fi foo() { struct fi local = {1, fn_int_3()};
241 return local;}
242
243 The ctor has a side effect (funccall) */
244 gcc_jit_function *fn =
245 gcc_jit_context_new_function (ctxt,
246 0,
247 GCC_JIT_FUNCTION_EXPORTED,
248 struct_fi_type,
249 "fn_fi_1_3",
250 0,
251 0,
252 0);
253 gcc_jit_lvalue *local = gcc_jit_function_new_local (fn,
254 0,
255 struct_fi_type,
256 "local");
257 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
258
259 {
260 gcc_jit_rvalue *rval_f1 =
261 gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 1);
262 gcc_jit_rvalue *rval_i2 =
263 gcc_jit_context_new_call (ctxt, 0, fn_int_3, 0, 0);
264
265 gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
266 gcc_jit_field *fields[] = {fi_f, fi_i};
267
268 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
269 (ctxt, 0,
270 struct_fi_type,
271 2,
272 fields,
273 vals);
274 gcc_jit_block_add_assignment (block, 0, local, ctor);
275 }
276
277 gcc_jit_block_end_with_return (block,
278 0,
279 gcc_jit_lvalue_as_rvalue(local));
280 }
281 { /* struct fi foo(fi) { return fi;}
282 struct fi bar() { return foo((struct fi){3, 4}); }
283 */
284
285 gcc_jit_param *fi_param =
286 gcc_jit_context_new_param (ctxt, 0, struct_fi_type, "fi");
287
288 gcc_jit_function *fn0 =
289 gcc_jit_context_new_function (ctxt,
290 0,
291 GCC_JIT_FUNCTION_EXPORTED,
292 struct_fi_type,
293 "fn_fi_x_x",
294 1,
295 &fi_param,
296 0);
297 gcc_jit_block *block0 = gcc_jit_function_new_block (fn0, "start");
298 gcc_jit_block_end_with_return (block0,
299 0,
300 gcc_jit_param_as_rvalue (
301 gcc_jit_function_get_param (fn0, 0)));
302
303 gcc_jit_function *fn =
304 gcc_jit_context_new_function (ctxt,
305 0,
306 GCC_JIT_FUNCTION_EXPORTED,
307 struct_fi_type,
308 "fn_fi_3_4",
309 0,
310 0,
311 0);
312 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
313
314 gcc_jit_rvalue *rval_f1 = gcc_jit_context_new_rvalue_from_int (
315 ctxt, float_type, 3);
316 gcc_jit_rvalue *rval_i2 = gcc_jit_context_new_rvalue_from_int (
317 ctxt, int_type, 4);
318
319 gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
320 gcc_jit_field *fields[] = {fi_f, fi_i};
321
322 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
323 (ctxt, 0,
324 struct_fi_type,
325 2,
326 fields,
327 vals);
328
329 gcc_jit_rvalue *call = gcc_jit_context_new_call (ctxt, 0, fn0, 1, &ctor);
330
331 gcc_jit_block_end_with_return (block,
332 0,
333 call);
334 }
335 { /*
336 void foo(struct bar *b) { *b = (struct bar) {.arr = {1,2}; }
337 */
338
339 gcc_jit_param *param =
340 gcc_jit_context_new_param (ctxt, 0,
341 gcc_jit_type_get_pointer (struct_bar_type),
342 "b");
343
344
345 gcc_jit_function *fn =
346 gcc_jit_context_new_function (ctxt,
347 0,
348 GCC_JIT_FUNCTION_EXPORTED,
349 void_type,
350 "fn_pbar_12",
351 1,
352 ¶m,
353 0);
354 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
355
356 gcc_jit_rvalue *rval_i1 = gcc_jit_context_new_rvalue_from_int (
357 ctxt, int_type, 1);
358 gcc_jit_rvalue *rval_i2 = gcc_jit_context_new_rvalue_from_int (
359 ctxt, int_type, 2);
360
361 gcc_jit_rvalue *arr_vals[] = { rval_i1, rval_i2};
362
363 gcc_jit_rvalue *arr_ctor = gcc_jit_context_new_array_constructor
364 (ctxt, 0,
365 int50arr_type,
366 2,
367 arr_vals);
368
369 gcc_jit_rvalue *str_ctor = gcc_jit_context_new_struct_constructor
370 (ctxt,
371 0,
372 struct_bar_type,
373 1,
374 &bar_fi,
375 &arr_ctor);
376
377 gcc_jit_param *p0 = gcc_jit_function_get_param (fn, 0);
378 gcc_jit_lvalue *lv0 = gcc_jit_param_as_lvalue (p0);
379 gcc_jit_lvalue *deref =
380 gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (lv0), 0);
381
382 gcc_jit_block_add_assignment (block, 0,
383 deref,
384 str_ctor);
385
386 gcc_jit_block_end_with_void_return (block, 0);
387 }
388 { /* struct bar foo() { struct bar local = {};
389 return local;}
390 */
391 gcc_jit_function *fn =
392 gcc_jit_context_new_function (ctxt,
393 0,
394 GCC_JIT_FUNCTION_EXPORTED,
395 struct_bar_type,
396 "fn_bar_0s",
397 0,
398 0,
399 0);
400 gcc_jit_lvalue *local =
401 gcc_jit_function_new_local (fn,
402 0,
403 struct_bar_type,
404 "local");
405 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
406
407 gcc_jit_rvalue *ctor = gcc_jit_context_new_struct_constructor
408 (ctxt, 0,
409 struct_bar_type,
410 0,
411 0,
412 0);
413 gcc_jit_block_add_assignment (block, 0, local, ctor);
414
415 gcc_jit_block_end_with_return (block,
416 0,
417 gcc_jit_lvalue_as_rvalue(local));
418 }
419 { /* struct bar foo() { struct bar local;
420 local.arr = (int [50]){1,2,3,4,5,6};
421 return local;}
422 */
423 gcc_jit_function *fn =
424 gcc_jit_context_new_function (ctxt,
425 0,
426 GCC_JIT_FUNCTION_EXPORTED,
427 struct_bar_type,
428 "fn_bar_123s",
429 0,
430 0,
431 0);
432 gcc_jit_lvalue *local =
433 gcc_jit_function_new_local (fn,
434 0,
435 struct_bar_type,
436 "local");
437 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
438
439 gcc_jit_rvalue *values[6];
440
441 for (int i = 0; i < 6; i++)
442 values[i] = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, i + 1);
443
444 gcc_jit_rvalue *ctor = gcc_jit_context_new_array_constructor
445 (ctxt, 0,
446 int50arr_type,
447 6,
448 values);
449
450 gcc_jit_lvalue *arr_lv = gcc_jit_lvalue_access_field (local,
451 0,
452 bar_fi);
453 gcc_jit_block_add_assignment (block, 0, arr_lv, ctor);
454
455 gcc_jit_block_end_with_return (block,
456 0,
457 gcc_jit_lvalue_as_rvalue(local));
458 }
459 { /* int[50] foo() { int arr[50];
460 arr = (int [50]){1,2,3,4,5,6};
461 return arr;}
462
463 N.B: Not a typo, returning an array.
464 */
465 gcc_jit_function *fn =
466 gcc_jit_context_new_function (ctxt,
467 0,
468 GCC_JIT_FUNCTION_EXPORTED,
469 int50arr_type,
470 "fn_int50arr_123s",
471 0,
472 0,
473 0);
474 gcc_jit_lvalue *local =
475 gcc_jit_function_new_local (fn,
476 0,
477 int50arr_type,
478 "local");
479 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
480
481 gcc_jit_rvalue *values[6];
482
483 for (int i = 0; i < 6; i++)
484 values[i] = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, i + 1);
485
486 gcc_jit_rvalue *ctor = gcc_jit_context_new_array_constructor (
487 ctxt,
488 0,
489 int50arr_type,
490 6,
491 values);
492
493 gcc_jit_block_add_assignment (block, 0, local, ctor);
494
495 gcc_jit_block_end_with_return (block,
496 0,
497 gcc_jit_lvalue_as_rvalue(local));
498 }
499 { /*
500 Verify that circular linked lists compiles, .e.g.
501 that visit_children does not run in circles or something.
502
503 struct llist { struct llist *next; };
504
505 bool foo (void)
506 {
507 volatile struct llist a;
508 volatile struct llist b;
509
510 a = (struct llist) {.next = &b};
511 b = (struct llist) {.next = &a};
512
513 return a.next == &b;
514 }
515 */
516 gcc_jit_struct *llist =
517 gcc_jit_context_new_opaque_struct(ctxt,
518 0, "llist_lcl");
519 gcc_jit_field *fields[] =
520 {
521 gcc_jit_context_new_field (ctxt, 0,
522 gcc_jit_type_get_pointer (
523 gcc_jit_struct_as_type (llist)),
524 "next")
525 };
526 gcc_jit_struct_set_fields (llist, 0, 1, fields);
527 gcc_jit_type *t_llist = gcc_jit_struct_as_type (llist);
528
529 gcc_jit_function *fn =
530 gcc_jit_context_new_function (ctxt,
531 0,
532 GCC_JIT_FUNCTION_EXPORTED,
533 bool_type,
534 "fn_llist",
535 0,
536 0,
537 0);
538 gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
539
540 gcc_jit_lvalue *a =
541 gcc_jit_function_new_local (fn,
542 0,
543 gcc_jit_type_get_volatile (t_llist),
544 "a");
545 gcc_jit_lvalue *b =
546 gcc_jit_function_new_local (fn,
547 0,
548 gcc_jit_type_get_volatile (t_llist),
549 "b");
550
551 gcc_jit_rvalue *a_addr = gcc_jit_lvalue_get_address( a, 0);
552 gcc_jit_rvalue *b_addr = gcc_jit_lvalue_get_address( b, 0);
553
554 gcc_jit_rvalue *a_ctor = gcc_jit_context_new_struct_constructor (
555 ctxt,
556 0,
557 t_llist,
558 1,
559 0,
560 &b_addr);
561
562 gcc_jit_rvalue *b_ctor = gcc_jit_context_new_struct_constructor (
563 ctxt,
564 0,
565 t_llist,
566 1,
567 0,
568 &a_addr);
569
570 gcc_jit_block_add_assignment (block, 0,
571 a, a_ctor);
572 gcc_jit_block_add_assignment (block, 0,
573 b, b_ctor);
574
575 gcc_jit_rvalue *cmp =
576 gcc_jit_context_new_comparison (
577 ctxt, 0,
578 GCC_JIT_COMPARISON_EQ,
579 gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (a),
580 0, fields[0]),
581 gcc_jit_context_new_cast (ctxt, 0,
582 gcc_jit_lvalue_get_address (b, 0),
583 gcc_jit_type_get_pointer (t_llist)));
584
585 gcc_jit_block_end_with_return (block,
586 0, cmp);
587 }
588 }
589
590 struct fi2 {
591 float f;
592 int i;
593 };
594
595 struct bar2 {
596 float ff;
597 int arr[50];
598 int ii;
599 char c;
600 };
601
602 union ubar2 {
603 float ff;
604 int ii;
605 };
606
607 struct int50arr {
608 int arr[50];
609 };
610
611 void __attribute__((optimize(0)))
612 scramble_stack(void)
613 {
614 char *p = alloca(100);
615 for (int i = 0; i < 100; i++)
616 *p++ = 0xF0;
617 asm(""); /* Mark for side-effect */
618 }
619
620 void __attribute__((optimize(0)))
621 scramble_arr (char *arr, int len)
622 {
623 for (int i = 0; i < len; i++)
624 *arr++ = i;
625 asm(""); /* Mark for side-effect */
626 }
627
628 void
629 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
630 {
631 CHECK_NON_NULL (result);
632
633 {
634 struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_1_2");
635 scramble_stack ();
636 struct fi2 fi = fn ();
637 CHECK_VALUE (fi.f, 1);
638 CHECK_VALUE (fi.i, 2);
639 }
640 {
641 struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_5_6");
642 struct fi2 fi = fn ();
643 CHECK_VALUE (fi.f, 5);
644 CHECK_VALUE (fi.i, 6);
645 }
646 {
647 struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_1_3");
648 struct fi2 fi = fn ();
649 CHECK_VALUE (fi.f, 1);
650 CHECK_VALUE (fi.i, 3);
651 }
652 {
653 struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_3_4");
654 struct fi2 fi = fn ();
655 CHECK_VALUE (fi.f, 3);
656 CHECK_VALUE (fi.i, 4);
657 }
658 {
659 scramble_stack();
660 struct bar2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_bar_0s");
661 struct bar2 bar = fn ();
662 struct bar2 key = {};
663
664 CHECK_VALUE (bar.ff, 0);
665 CHECK_VALUE (bar.ii, 0);
666 CHECK_VALUE (memcmp (&bar.arr, &key.arr, sizeof (key.arr)), 0);
667 }
668 {
669
670 void (*fn) (struct bar2 *) = gcc_jit_result_get_code (result, "fn_pbar_12");
671
672 struct bar2 bar = (struct bar2) {};
673
674 scramble_arr ((char*)&bar, sizeof bar);
675 scramble_stack();
676
677 fn (&bar);
678
679 struct bar2 key = {.arr = {1,2}};
680 __builtin_clear_padding (&key);
681
682 CHECK_VALUE (memcmp (&bar, &key, sizeof (key)), 0);
683 }
684 {
685 scramble_stack();
686 struct bar2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_bar_123s");
687 struct bar2 bar = fn ();
688 struct bar2 key = {.arr = {1,2,3,4,5,6} };
689
690 CHECK_VALUE (memcmp (&bar.arr, &key.arr, sizeof (key.arr)), 0);
691 }
692 {
693 scramble_stack ();
694 /* This is abit shady. Lets just pretend that array returns à la Fortran
695 is the same thing as returning a struct with an array in it in C. */
696 struct int50arr (*fn) (void) =
697 gcc_jit_result_get_code (result, "fn_int50arr_123s");
698 struct int50arr ans = fn ();
699 int key[50] = {1,2,3,4,5,6};
700
701 CHECK_VALUE (memcmp (ans.arr, key, sizeof (key)), 0);
702 }
703 {
704 _Bool (*fn) (void) = gcc_jit_result_get_code (result, "fn_llist");
705 CHECK_VALUE (fn (), 1);
706 }
707 }