Added basic reflaction functionality for firm operators
[libfirm] / ir / ir / irreflect.c
1 /**
2  * @file irreflect.c
3  * @date 9.9.2004
4  * @author Sebastian Hack
5  * @brief Reflection for Firm operands.
6  *
7  * $Id$
8  */
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13
14 #define obstack_chunk_alloc malloc
15 #define obstack_chunk_free free
16 #include <obstack.h>
17
18 #include "irmode.h"
19 #include "irreflect.h"
20
21 #define obstack_grow_str(obst,s) obstack_grow((obst), (s), strlen((s)))
22 #define obstack_grow_str_const(obst,s) obstack_grow((obst), (s), sizeof((s)))
23
24 extern int obstack_printf(struct obstack *obst, const char *fmt, ...);
25
26 /**
27  * Get the number of bits set in a word.
28  */
29 static inline int pop(int i) {
30   unsigned x = (unsigned) i;
31   x = ((x >> 1) & 0x55555555);
32   x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
33   x = (x + (x >> 4)) & 0x0f0f0f0f;
34   x = x + (x >> 8);
35   x = x + (x >> 16);
36   return (int) (x & 0x3f);
37 }
38
39 /**
40  * Get the number of bits differing in two variables.
41  */
42 static inline int dist(int x, int y) {
43   return pop(x ^ y);
44 }
45
46
47 #define MAX_SIG_COUNT 8
48 #define MAX_ARG_COUNT 10
49
50 typedef struct {
51   int num;    /**< A sequential number (one opcode can have multiple signatures. */
52   rflct_arg_t args[]; /**< The signature. */
53 } rflct_args_t;
54
55 typedef struct {
56   opcode opc;
57   const char *name;
58   bool commutative;
59   int sig_count;
60   const rflct_arg_t *sigs[MAX_SIG_COUNT];
61 } rflct_opcode_t;
62
63 static struct obstack obst;
64
65 static const rflct_opcode_t *opcodes[iro_MaxOpcode];
66
67 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
68
69 // #define MODE_IS(mode,mask) (((mode) & (mask)) != 0)
70
71 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
72   mode_sort sort = get_mode_sort(mode);
73
74   switch(sort) {
75   case irms_auxiliary:
76   case irms_control_flow:
77     if(mode == mode_BB)
78       return RFLCT_MC(BB);
79     else if(mode == mode_X)
80       return RFLCT_MC(X);
81   case irms_memory:
82     return RFLCT_MC(Mem);
83   case irms_internal_boolean:
84     return RFLCT_MC(Bool);
85   case irms_int_number:
86     return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
87   case irms_float_number:
88     return RFLCT_MC(Float);
89   case irms_reference:
90     return RFLCT_MC(Ref);
91   case irms_character:
92     return RFLCT_MC(Char);
93   }
94
95   return RFLCT_MC(None);
96 }
97
98 static inline const rflct_opcode_t *get_opcode(opcode opc) {
99   assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
100   return opcodes[opc];
101 }
102
103 static inline const rflct_arg_t *get_args(opcode opc, int sig) {
104   const rflct_opcode_t *opcode = get_opcode(opc);
105   assert(sig >= 0 && sig < opcode->sig_count
106          && "Invalid signature");
107   return opcode->sigs[sig];
108 }
109
110 #define GET_OPCODE(opc) get_opcode(opc)
111 #define GET_ARGS(opc,args) get_args(opc, args)
112
113 int rflct_get_signature_count(opcode opc) {
114   const rflct_opcode_t *opcode = GET_OPCODE(opc);
115   return opcode->sig_count;
116 }
117
118 int rflct_get_in_args_count(opcode opc, int sig) {
119   const rflct_arg_t *args = GET_ARGS(opc, sig);
120   int res = 0, i = 0;
121
122   for(i = 0; args[i].name != NULL; i++);
123   for(res = 0, i += 1; args[i].name != NULL; res++, i++);
124   return res;
125 }
126
127 int rflct_get_out_args_count(opcode opc, int sig) {
128   const rflct_arg_t *args = GET_ARGS(opc, sig);
129   int i = 0;
130   for(i = 0; args[i].name != NULL; i++);
131   return i;
132 }
133
134
135 const rflct_arg_t *rflct_get_in_args(opcode opc, int sig) {
136   const rflct_arg_t *args = GET_ARGS(opc, sig);
137   int i;
138
139   for(i = 0; args[i].name != NULL; i++);
140   return &args[i + 1];
141 }
142
143 const rflct_arg_t *rflct_get_out_args(opcode opc, int sig) {
144   return GET_ARGS(opc, sig);
145 }
146
147 int rflct_signature_match(ir_node *irn, int sig) {
148   opcode op = get_irn_opcode(irn);
149   const rflct_arg_t *args = rflct_get_in_args(op, sig);
150   int dst = 0;
151   int i, j;
152
153   for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
154         && j < get_irn_arity(irn); j++) {
155
156     ir_node *child = get_irn_n(irn, j);
157     const rflct_arg_t *arg = &args[i];
158     rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
159
160     if(arg->accepted_modes & mc)
161       dst += dist(arg->accepted_modes, mc);
162     else
163       return INT_MAX;
164
165     if(!arg->is_variadic)
166       i++;
167   }
168
169   return dst;
170 }
171
172 int rflct_get_signature(ir_node *irn) {
173   const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
174   int min_dist = INT_MAX;
175   int min_sig = INT_MAX;
176   int i;
177
178   for(i = 0; i < opc->sig_count; i++) {
179     int dist = rflct_signature_match(irn, i);
180     if(dist < min_dist) {
181       min_dist = dist;
182       min_sig = i;
183     }
184   }
185
186   return min_sig;
187 }
188
189 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
190 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
191   switch(mc) {
192     XXX(None);
193     XXX(Mem);
194     XXX(Bool);
195     XXX(IntS);
196     XXX(IntU);
197     XXX(Float);
198     XXX(Ref);
199     XXX(Char);
200     XXX(X);
201     XXX(BB);
202     XXX(Int);
203     XXX(Intb);
204     XXX(Num);
205     XXX(NumP);
206     XXX(Data);
207     XXX(Datab);
208     XXX(DataM);
209     XXX(DataMX);
210     XXX(Lh);
211   default:
212     return "";
213   }
214 #undef XXX
215 }
216
217 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
218                                             rflct_mode_class_t mc) {
219   const char *res = rflct_mode_class_atomic_name(mc);
220
221   if(strlen(res) == 0) {
222     const char *prefix = "";
223     int mask;
224
225     obstack_1grow(obst, '{');
226     for(mask = 1; mask != 0; mask <<= 1) {
227       if(mask & mc) {
228         const char *s = rflct_mode_class_atomic_name(mask);
229         obstack_grow_str(obst, s);
230         obstack_grow_str(obst, prefix);
231         prefix = "|";
232       }
233     }
234     obstack_1grow(obst, '}');
235
236   } else
237     obstack_grow(obst, res, strlen(res));
238 }
239
240 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
241   struct obstack obst;
242   const char *res;
243
244   obstack_init(&obst);
245
246   rflct_mode_class_comb_name_obst(&obst, mc);
247   obstack_1grow(&obst, 0);
248   res = obstack_finish(&obst);
249
250   strncpy(str, res, n);
251
252   obstack_free(&obst, NULL);
253
254   return str;
255 }
256
257 static void rflct_obstack_grow_args(struct obstack *obst,
258                                     const rflct_arg_t *args) {
259   const rflct_arg_t *arg;
260   const char *prefix = "";
261
262   for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
263     obstack_grow_str(obst, prefix);
264     obstack_grow_str(obst, arg->name);
265     if(arg->is_variadic)
266       obstack_1grow(obst, '*');
267     obstack_1grow(obst, ':');
268     rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
269     prefix = ", ";
270   }
271
272 }
273
274 char *rflct_to_string(char *buf, int n, opcode opc, int sig) {
275   struct obstack obst;
276   char *s;
277   const rflct_opcode_t *opcode = GET_OPCODE(opc);
278
279   obstack_init(&obst);
280
281   obstack_1grow(&obst, '(');
282   rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
283
284   obstack_grow_str(&obst, ") = ");
285   obstack_grow_str(&obst, opcode->name);
286   obstack_1grow(&obst, '(');
287
288   rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
289
290   obstack_1grow(&obst, ')');
291   obstack_1grow(&obst, 0);
292   s = obstack_finish(&obst);
293   strncpy(buf, s, n);
294   obstack_free(&obst, NULL);
295
296   return buf;
297 }
298
299 #define ARG(name,modes) \
300   _ARG(name, modes, false, -1)
301
302 #define ARG_SAME(name,modes,mode_same) \
303   _ARG(name, modes, false, mode_same)
304
305 #define VARG(name,modes) \
306   _ARG(name, modes, true, 0)
307
308 #define VARG_SAME(name,modes) \
309   _ARG(name, modes, true, 1)
310
311 #define MARK \
312   _ARG(NULL, None, false, -1)
313
314 #define BLOCK ARG("Block", BB)
315
316 static void init_ops(void) {
317
318   int curr_sig;
319   rflct_opcode_t *opcode;
320
321   obstack_init(&obst);
322
323
324 #define BEGIN_OP(op)  \
325     curr_sig = 0; \
326     opcode = obstack_alloc(&obst, sizeof(*opcode)); \
327     opcode->opc = iro_ ## op; \
328     opcode->name = #op; \
329     opcodes[opcode->opc] = opcode;
330
331
332 #define BEGIN_ARGS
333
334 #define _ARG(_name,_modes,_variadic,_mode_equals) \
335   { \
336     rflct_arg_t args; \
337     args.name = _name; \
338     args.accepted_modes = RFLCT_MC(_modes); \
339     args.is_variadic = _variadic; \
340     args.mode_equals = _mode_equals; \
341     obstack_grow(&obst, &args, sizeof(args)); \
342   }
343
344 #define END_ARGS \
345   { \
346     _ARG(NULL, None, false, 0) \
347     assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
348     opcode->sigs[curr_sig++] = obstack_finish(&obst); \
349     opcode->sig_count = curr_sig; \
350   }
351
352 #define END_OP
353
354 #include "irreflect.def"
355
356 #undef BEGIN_ARGS
357 #undef END_ARGS
358 #undef BEGIN_OP
359 #undef END_OP
360 }
361
362
363
364
365 void init_rflct(void) {
366   init_ops();
367 }