1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "libgccjit++.h"
5
6 #include "harness.h"
7
8 struct s2
9 {
10 char x __attribute__ ((aligned (2)));
11 char y __attribute__ ((aligned (2)));
12 };
13
14 struct s4
15 {
16 char x __attribute__ ((aligned (4)));
17 char y __attribute__ ((aligned (4)));
18 };
19
20 struct s8
21 {
22 char x __attribute__ ((aligned (8)));
23 char y __attribute__ ((aligned (8)));
24 };
25
26 struct s16
27 {
28 char x __attribute__ ((aligned (16)));
29 char y __attribute__ ((aligned (16)));
30 };
31
32 struct s32
33 {
34 char x __attribute__ ((aligned (32)));
35 char y __attribute__ ((aligned (32)));
36 };
37
38 struct s64
39 {
40 char x __attribute__ ((aligned (64)));
41 char y __attribute__ ((aligned (64)));
42 };
43
44 struct s128
45 {
46 char x __attribute__ ((aligned (128)));
47 char y __attribute__ ((aligned (128)));
48 };
49
50 static void
create_aligned_code(gcc_jit_context * c_ctxt,const char * struct_name,unsigned int alignment,const char * reader_fn_name,const char * writer_fn_name)51 create_aligned_code (gcc_jit_context *c_ctxt, const char *struct_name,
52 unsigned int alignment, const char *reader_fn_name,
53 const char *writer_fn_name)
54 {
55 /* Let's try to inject the equivalent of:
56
57 char
58 READER_FN_NAME (const struct STRUCT_NAME *f)
59 {
60 return f->x * f->y;
61 }
62
63 char
64 WRITER_FN_NAME (struct STRUCT_NAME *g)
65 {
66 g->x = 5;
67 g->y = 7;
68 return READER_FN_NAME (g);
69 }
70 */
71 gccjit::context ctxt (c_ctxt);
72 gccjit::type char_type = ctxt.get_type (GCC_JIT_TYPE_CHAR);
73 gccjit::type aligned_char_type = char_type.get_aligned (alignment);
74 gccjit::field x = ctxt.new_field (aligned_char_type, "x");
75 gccjit::field y = ctxt.new_field (aligned_char_type, "y");
76 std::vector<gccjit::field> fields = {x, y};
77 gccjit::type struct_type = ctxt.new_struct_type (struct_name, fields);
78 gccjit::type const_struct_type = struct_type.get_const ();
79 gccjit::type const_ptr_type = const_struct_type.get_pointer ();
80
81 /* Build the reader fn. */
82 gccjit::param param_f = ctxt.new_param (const_ptr_type, "f");
83 std::vector<gccjit::param> params = {param_f};
84 gccjit::function fn_test_reading
85 = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
86 char_type,
87 reader_fn_name,
88 params,
89 0);
90
91 /* return f->x * f->y; */
92 gccjit::block reading_block = fn_test_reading.new_block ();
93 reading_block.end_with_return (param_f.dereference_field (x)
94 * param_f.dereference_field (y));
95
96 /* Build the writer fn. */
97 gccjit::type ptr_type = struct_type.get_pointer ();
98 gccjit::param param_g = ctxt.new_param (ptr_type, "g");
99 params = {param_g};
100 gccjit::function fn_test_writing
101 = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
102 char_type,
103 writer_fn_name,
104 params,
105 0);
106
107 /* g->x = 5; */
108 gccjit::block writing_block = fn_test_writing.new_block ();
109 writing_block.add_assignment (param_g.dereference_field (x),
110 ctxt.new_rvalue (char_type, 5));
111
112 /* g->y = 7; */
113 writing_block.add_assignment (param_g.dereference_field (y),
114 ctxt.new_rvalue (char_type, 7));
115
116 /* return READER_FN_NAME (g); */
117 writing_block.end_with_return (ctxt.new_call (fn_test_reading,
118 param_g));
119 }
120
121 /* Implement a verifier function for a given struct. */
122
123 template <typename T>
124 static void
verify_aligned_code(gcc_jit_context * ctxt,gcc_jit_result * result,const char * writer_fn_name)125 verify_aligned_code (gcc_jit_context *ctxt,
126 gcc_jit_result *result,
127 const char *writer_fn_name)
128 {
129 typedef char (*fn_type) (T *);
130 CHECK_NON_NULL (result);
131
132 T tmp;
133 memset (&tmp, 0xac, sizeof (tmp));
134 fn_type test_writing =
135 (fn_type)gcc_jit_result_get_code (result, writer_fn_name);
136 CHECK_NON_NULL (test_writing);
137
138 /* Verify that the code correctly returns the product of the fields. */
139 CHECK_VALUE (test_writing (&tmp), 35);
140
141 /* Verify the we can read the values of the fields, and thus that the
142 struct layout agrees with that of the C++ frontend. */
143 CHECK_VALUE (tmp.x, 5);
144 CHECK_VALUE (tmp.y, 7);
145 }
146
147 void
create_code(gcc_jit_context * ctxt,void * user_data)148 create_code (gcc_jit_context *ctxt, void *user_data)
149 {
150 create_aligned_code (ctxt, "s2", 2, "test_aligned_reading_s2",
151 "test_aligned_writing_s2");
152 create_aligned_code (ctxt, "s4", 4, "test_aligned_reading_s4",
153 "test_aligned_writing_s4");
154 create_aligned_code (ctxt, "s8", 8, "test_aligned_reading_s8",
155 "test_aligned_writing_s8");
156 create_aligned_code (ctxt, "s16", 16, "test_aligned_reading_s16",
157 "test_aligned_writing_s16");
158 create_aligned_code (ctxt, "s32", 32, "test_aligned_reading_s32",
159 "test_aligned_writing_s32");
160 create_aligned_code (ctxt, "s64", 64, "test_aligned_reading_s64",
161 "test_aligned_writing_s64");
162 create_aligned_code (ctxt, "s128", 128, "test_aligned_reading_s128",
163 "test_aligned_writing_s128");
164 }
165
166 void
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)167 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
168 {
169 verify_aligned_code<s2> (ctxt, result, "test_aligned_writing_s2");
170 verify_aligned_code<s4> (ctxt, result, "test_aligned_writing_s4");
171 verify_aligned_code<s8> (ctxt, result, "test_aligned_writing_s8");
172 verify_aligned_code<s16> (ctxt, result, "test_aligned_writing_s16");
173 verify_aligned_code<s32> (ctxt, result, "test_aligned_writing_s32");
174 verify_aligned_code<s64> (ctxt, result, "test_aligned_writing_s64");
175 verify_aligned_code<s128> (ctxt, result, "test_aligned_writing_s128");
176 }
177