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 * 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 *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 gcc_jit_type *char_type =
72 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
73 gcc_jit_type *aligned_char_type =
74 gcc_jit_type_get_aligned (char_type, alignment);
75 gcc_jit_field *x =
76 gcc_jit_context_new_field (ctxt,
77 NULL,
78 aligned_char_type,
79 "x");
80 gcc_jit_field *y =
81 gcc_jit_context_new_field (ctxt,
82 NULL,
83 aligned_char_type,
84 "y");
85 gcc_jit_field *fields[] = {x, y};
86 gcc_jit_type *struct_type =
87 gcc_jit_struct_as_type (
88 gcc_jit_context_new_struct_type (ctxt, NULL, struct_name, 2, fields));
89 gcc_jit_type *const_struct_type = gcc_jit_type_get_const (struct_type);
90 gcc_jit_type *const_ptr_type = gcc_jit_type_get_pointer (const_struct_type);
91
92 /* Build the reader fn. */
93 gcc_jit_param *param_f =
94 gcc_jit_context_new_param (ctxt, NULL, const_ptr_type, "f");
95 gcc_jit_function *fn_test_reading =
96 gcc_jit_context_new_function (ctxt, NULL,
97 GCC_JIT_FUNCTION_EXPORTED,
98 char_type,
99 reader_fn_name,
100 1, ¶m_f,
101 0);
102
103 /* return f->x * f->y; */
104 gcc_jit_block *reading_block = gcc_jit_function_new_block (fn_test_reading, NULL);
105 gcc_jit_block_end_with_return (
106 reading_block,
107 NULL,
108 gcc_jit_context_new_binary_op (
109 ctxt, NULL,
110 GCC_JIT_BINARY_OP_MULT,
111 char_type,
112 gcc_jit_lvalue_as_rvalue (
113 gcc_jit_rvalue_dereference_field (
114 gcc_jit_param_as_rvalue (param_f),
115 NULL,
116 x)),
117 gcc_jit_lvalue_as_rvalue (
118 gcc_jit_rvalue_dereference_field (
119 gcc_jit_param_as_rvalue (param_f),
120 NULL,
121 y))));
122
123 /* Build the writer fn. */
124 gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (struct_type);
125 gcc_jit_param *param_g =
126 gcc_jit_context_new_param (ctxt, NULL, ptr_type, "g");
127 gcc_jit_function *fn_test_writing =
128 gcc_jit_context_new_function (ctxt, NULL,
129 GCC_JIT_FUNCTION_EXPORTED,
130 char_type,
131 writer_fn_name,
132 1, ¶m_g,
133 0);
134
135 /* g->x = 5; */
136 gcc_jit_block *writing_block = gcc_jit_function_new_block (fn_test_writing, NULL);
137 gcc_jit_block_add_assignment (
138 writing_block, NULL,
139 gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_g),
140 NULL, x),
141 gcc_jit_context_new_rvalue_from_int (ctxt, char_type, 5));
142
143 /* g->y = 7; */
144 gcc_jit_block_add_assignment (
145 writing_block, NULL,
146 gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_g),
147 NULL, y),
148 gcc_jit_context_new_rvalue_from_int (ctxt, char_type, 7));
149
150 /* return READER_FN_NAME (g); */
151 gcc_jit_rvalue *arg = gcc_jit_param_as_rvalue (param_g);
152 gcc_jit_block_end_with_return (
153 writing_block,
154 NULL,
155 gcc_jit_context_new_call (
156 ctxt, NULL,
157 fn_test_reading,
158 1, &arg));
159 }
160
161 /* Implement a verifier function for a given struct. */
162
163 #define IMPL_VERIFY_ALIGNED_CODE(TYPENAME) \
164 static void \
165 verify_aligned_code_ ##TYPENAME (gcc_jit_context *ctxt, \
166 gcc_jit_result *result, \
167 const char *writer_fn_name) \
168 { \
169 typedef char (*fn_type) (struct TYPENAME *); \
170 CHECK_NON_NULL (result); \
171 \
172 struct TYPENAME tmp; \
173 memset (&tmp, 0xac, sizeof (tmp)); \
174 \
175 fn_type test_writing = \
176 (fn_type)gcc_jit_result_get_code (result, writer_fn_name); \
177 CHECK_NON_NULL (test_writing); \
178 \
179 /* Verify that the code correctly returns the product of the fields. */ \
180 CHECK_VALUE (test_writing (&tmp), 35); \
181 \
182 /* Verify the we can read the values of the fields, and thus that the \
183 struct layout agrees with that of the C frontend. */ \
184 CHECK_VALUE (tmp.x, 5); \
185 CHECK_VALUE (tmp.y, 7); \
186 }
187
188 void
create_code(gcc_jit_context * ctxt,void * user_data)189 create_code (gcc_jit_context *ctxt, void *user_data)
190 {
191 create_aligned_code (ctxt, "s2", 2, "test_aligned_reading_s2",
192 "test_aligned_writing_s2");
193 create_aligned_code (ctxt, "s4", 4, "test_aligned_reading_s4",
194 "test_aligned_writing_s4");
195 create_aligned_code (ctxt, "s8", 8, "test_aligned_reading_s8",
196 "test_aligned_writing_s8");
197 create_aligned_code (ctxt, "s16", 16, "test_aligned_reading_s16",
198 "test_aligned_writing_s16");
199 create_aligned_code (ctxt, "s32", 32, "test_aligned_reading_s32",
200 "test_aligned_writing_s32");
201 create_aligned_code (ctxt, "s64", 64, "test_aligned_reading_s64",
202 "test_aligned_writing_s64");
203 create_aligned_code (ctxt, "s128", 128, "test_aligned_reading_s128",
204 "test_aligned_writing_s128");
205 }
206
207 IMPL_VERIFY_ALIGNED_CODE(s2)
IMPL_VERIFY_ALIGNED_CODE(s4)208 IMPL_VERIFY_ALIGNED_CODE(s4)
209 IMPL_VERIFY_ALIGNED_CODE(s8)
210 IMPL_VERIFY_ALIGNED_CODE(s16)
211 IMPL_VERIFY_ALIGNED_CODE(s32)
212 IMPL_VERIFY_ALIGNED_CODE(s64)
213 IMPL_VERIFY_ALIGNED_CODE(s128)
214
215 void
216 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
217 {
218 verify_aligned_code_s2 (ctxt, result,
219 "test_aligned_writing_s2");
220 verify_aligned_code_s4 (ctxt, result,
221 "test_aligned_writing_s4");
222 verify_aligned_code_s8 (ctxt, result,
223 "test_aligned_writing_s8");
224 verify_aligned_code_s16 (ctxt, result,
225 "test_aligned_writing_s16");
226 verify_aligned_code_s32 (ctxt, result,
227 "test_aligned_writing_s32");
228 verify_aligned_code_s64 (ctxt, result,
229 "test_aligned_writing_s64");
230 verify_aligned_code_s128 (ctxt, result,
231 "test_aligned_writing_s128");
232 }
233