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