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, &param_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, &param_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