removed INLINE definition
[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 #ifdef HAVE_CONFIG_H
10 # include "config.h"
11 #endif
12
13 #ifdef HAVE_STDLIB_H
14 # include <stdlib.h>
15 #endif
16 #ifdef HAVE_STRING_H
17 # include <string.h>
18 #endif
19 #ifdef HAVE_STRINGS_H
20 # include <strings.h>
21 #endif
22
23 #include "obst.h"
24
25 #include "irmode.h"
26 #include "irreflect.h"
27
28 #define obstack_grow_str(obst,s) obstack_grow((obst), (s), strlen((s)))
29 #define obstack_grow_str_const(obst,s) obstack_grow((obst), (s), sizeof((s)))
30
31 extern int obstack_printf(struct obstack *obst, const char *fmt, ...);
32
33 /**
34  * Get the number of bits set in a word.
35  */
36 static INLINE int pop(int i) {
37         unsigned x = (unsigned) i;
38         x = ((x >> 1) & 0x55555555);
39         x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
40         x = (x + (x >> 4)) & 0x0f0f0f0f;
41         x = x + (x >> 8);
42         x = x + (x >> 16);
43         return (int) (x & 0x3f);
44 }
45
46 /**
47  * Get the number of bits differing in two variables.
48  */
49 static INLINE int dist(int x, int y) {
50         return pop(x ^ y);
51 }
52
53
54 #define MAX_SIG_COUNT 8
55 #define MAX_ARG_COUNT 10
56
57 typedef struct {
58         int num;    /**< A sequential number (one opcode can have multiple signatures. */
59         rflct_arg_t args[]; /**< The signature. */
60 } rflct_args_t;
61
62 typedef struct {
63         opcode opc;
64         const char *name;
65         int commutative;
66         int sig_count;
67         rflct_arg_t *sigs[MAX_SIG_COUNT];
68 } rflct_opcode_t;
69
70 static struct obstack obst;
71
72 static rflct_opcode_t **opcodes = NULL;
73
74 static int opcodes_size = 0;
75
76 static INLINE void assure_opcode_capacity(int opcode)
77 {
78         if(opcode >= opcodes_size) {
79                 int new_size = 2 * opcode;
80                 rflct_opcode_t **new_opcodes = xcalloc(new_size, sizeof(new_opcodes[0]));
81
82                 if(opcodes != NULL) {
83                         memcpy(new_opcodes, opcodes, sizeof(*opcodes) * opcodes_size);
84                         free(opcodes);
85                 }
86
87                 opcodes = new_opcodes;
88                 opcodes_size = new_size;
89         }
90 }
91
92
93 #if 0
94 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
95 #endif
96 #define OPCODES_COUNT opcodes_size
97
98
99 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
100         mode_sort sort = get_mode_sort(mode);
101
102         switch(sort) {
103                 case irms_auxiliary:
104                 case irms_control_flow:
105                         if(mode == mode_BB)
106                                 return RFLCT_MC(BB);
107                         else if(mode == mode_X)
108                                 return RFLCT_MC(X);
109                 case irms_memory:
110                         return RFLCT_MC(Mem);
111                 case irms_internal_boolean:
112                         return RFLCT_MC(Bool);
113                 case irms_int_number:
114                         return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
115                 case irms_float_number:
116                         return RFLCT_MC(Float);
117                 case irms_reference:
118                         return RFLCT_MC(Ref);
119                 case irms_character:
120                         return RFLCT_MC(Char);
121         }
122
123         return RFLCT_MC(None);
124 }
125
126 static INLINE const rflct_opcode_t *get_opcode(opcode opc) {
127         assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
128         return opcodes[opc];
129 }
130
131 static INLINE const rflct_arg_t *get_args(opcode opc, int sig) {
132         const rflct_opcode_t *opcode = get_opcode(opc);
133         assert(sig >= 0 && sig < opcode->sig_count
134                         && "Invalid signature");
135         return opcode->sigs[sig];
136 }
137
138 #define GET_OPCODE(opc) get_opcode(opc)
139 #define GET_ARGS(opc,args) get_args(opc, args)
140
141 int rflct_get_signature_count(opcode opc) {
142         const rflct_opcode_t *opcode = GET_OPCODE(opc);
143         return opcode->sig_count;
144 }
145
146 int rflct_get_in_args_count(opcode opc, int sig) {
147         const rflct_arg_t *args = GET_ARGS(opc, sig);
148         int res = 0, i = 0;
149
150         for(i = 0; args[i].name != NULL; i++);
151         for(res = 0, i += 1; args[i].name != NULL; res++, i++);
152         return res;
153 }
154
155 int rflct_get_out_args_count(opcode opc, int sig) {
156         const rflct_arg_t *args = GET_ARGS(opc, sig);
157         int i = 0;
158         for(i = 0; args[i].name != NULL; i++);
159         return i;
160 }
161
162
163 const rflct_arg_t *rflct_get_in_args(opcode opc, int sig) {
164         const rflct_arg_t *args = GET_ARGS(opc, sig);
165         int i;
166
167         for(i = 0; args[i].name != NULL; i++);
168         return &args[i + 1];
169 }
170
171 const rflct_arg_t *rflct_get_out_args(opcode opc, int sig) {
172         return GET_ARGS(opc, sig);
173 }
174
175 int rflct_signature_match(const ir_node *irn, int sig) {
176         opcode op = get_irn_opcode(irn);
177         const rflct_arg_t *args = rflct_get_in_args(op, sig);
178         int dst = 0;
179         int i, j;
180
181         for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
182                         && j < get_irn_arity(irn); j++) {
183
184                 ir_node *child = get_irn_n(irn, j);
185                 const rflct_arg_t *arg = &args[i];
186                 rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
187
188                 if(arg->accepted_modes & mc)
189                         dst += dist(arg->accepted_modes, mc);
190                 else
191                         return INT_MAX;
192
193                 if(!arg->is_variadic)
194                         i++;
195         }
196
197         return dst;
198 }
199
200 int rflct_get_signature(const ir_node *irn) {
201         const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
202         int min_dist = INT_MAX;
203         int min_sig = INT_MAX;
204         int i;
205
206         for(i = 0; i < opc->sig_count; i++) {
207                 int dist = rflct_signature_match(irn, i);
208                 if(dist < min_dist) {
209                         min_dist = dist;
210                         min_sig = i;
211                 }
212         }
213
214         return min_sig;
215 }
216
217 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
218 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
219         switch(mc) {
220                 XXX(None);
221                 XXX(Mem);
222                 XXX(Bool);
223                 XXX(IntS);
224                 XXX(IntU);
225                 XXX(Float);
226                 XXX(Ref);
227                 XXX(Char);
228                 XXX(X);
229                 XXX(BB);
230                 XXX(Int);
231                 XXX(Intb);
232                 XXX(Num);
233                 XXX(NumP);
234                 XXX(Data);
235                 XXX(Datab);
236                 XXX(DataM);
237                 XXX(DataMX);
238                 XXX(Lh);
239                 default:
240                 return "";
241         }
242 #undef XXX
243 }
244
245 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
246                 rflct_mode_class_t mc) {
247         const char *res = rflct_mode_class_atomic_name(mc);
248
249         if(strlen(res) == 0) {
250                 const char *prefix = "";
251                 int mask;
252
253                 obstack_1grow(obst, '{');
254                 for(mask = 1; mask != 0; mask <<= 1) {
255                         if(mask & mc) {
256                                 const char *s = rflct_mode_class_atomic_name(mask);
257                                 obstack_grow_str(obst, s);
258                                 obstack_grow_str(obst, prefix);
259                                 prefix = "|";
260                         }
261                 }
262                 obstack_1grow(obst, '}');
263
264         } else
265                 obstack_grow(obst, res, strlen(res));
266 }
267
268 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
269         struct obstack obst;
270         const char *res;
271
272         obstack_init(&obst);
273
274         rflct_mode_class_comb_name_obst(&obst, mc);
275         obstack_1grow(&obst, 0);
276         res = obstack_finish(&obst);
277
278         strncpy(str, res, n);
279
280         obstack_free(&obst, NULL);
281
282         return str;
283 }
284
285 static void rflct_obstack_grow_args(struct obstack *obst,
286                 const rflct_arg_t *args) {
287         const rflct_arg_t *arg;
288         const char *prefix = "";
289
290         for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
291                 obstack_grow_str(obst, prefix);
292                 obstack_grow_str(obst, arg->name);
293                 if(arg->is_variadic)
294                         obstack_1grow(obst, '*');
295                 obstack_1grow(obst, ':');
296                 rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
297                 prefix = ", ";
298         }
299
300 }
301
302 char *rflct_to_string(char *buf, int n, opcode opc, int sig) {
303         struct obstack obst;
304         char *s;
305         const rflct_opcode_t *opcode = GET_OPCODE(opc);
306
307         obstack_init(&obst);
308
309         obstack_1grow(&obst, '(');
310         rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
311
312         obstack_grow_str(&obst, ") = ");
313         obstack_grow_str(&obst, opcode->name);
314         obstack_1grow(&obst, '(');
315
316         rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
317
318         obstack_1grow(&obst, ')');
319         obstack_1grow(&obst, 0);
320         s = obstack_finish(&obst);
321         strncpy(buf, s, n);
322         obstack_free(&obst, NULL);
323
324         return buf;
325 }
326
327 #define NON_VARIADIC 0
328 #define VARIADIC     1
329
330 #define ARG(name,modes) \
331 _ARG(name, modes, NON_VARIADIC, -1)
332
333 #define ARG_SAME(name,modes,mode_same) \
334 _ARG(name, modes, NON_VARIADIC, mode_same)
335
336 #define VARG(name,modes) \
337 _ARG(name, modes, VARIADIC, 0)
338
339 #define VARG_SAME(name,modes) \
340 _ARG(name, modes, VARIADIC, 1)
341
342 #define MARK \
343 _ARG(NULL, None, NON_VARIADIC, -1)
344
345 #define FINISH \
346 _ARG(NULL, None, NON_VARIADIC, 0)
347
348 #define BLOCK ARG("Block", BB)
349
350         static void init_ops(void) {
351
352                 int curr_sig;
353                 rflct_opcode_t *opcode;
354
355                 obstack_init(&obst);
356
357                 assure_opcode_capacity(iro_MaxOpcode);
358
359
360 #define BEGIN_OP(op)  \
361                 curr_sig = 0; \
362                         opcode = obstack_alloc(&obst, sizeof(*opcode)); \
363                         opcode->opc = iro_ ## op; \
364                         opcode->name = #op; \
365                         opcodes[opcode->opc] = opcode;
366
367
368 #define BEGIN_ARGS
369
370 #define _ARG(_name,_modes,_variadic,_mode_equals) \
371                 { \
372                         rflct_arg_t args; \
373                                 args.name = _name; \
374                                 args.accepted_modes = RFLCT_MC(_modes); \
375                                 args.is_variadic = _variadic; \
376                                 args.mode_equals = _mode_equals; \
377                                 obstack_grow(&obst, &args, sizeof(args)); \
378                 }
379
380 #define END_ARGS \
381                 { \
382                         FINISH; \
383                         assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
384                         opcode->sigs[curr_sig++] = obstack_finish(&obst); \
385                         opcode->sig_count = curr_sig; \
386                 }
387
388 #define END_OP
389
390 #include "irreflect.def"
391
392 #undef BEGIN_ARGS
393 #undef END_ARGS
394 #undef BEGIN_OP
395 #undef END_OP
396         }
397
398 #undef _ARG
399 #define _ARG(_name,_modes,_var,_me) \
400 arg->name = _name; \
401         arg->accepted_modes = RFLCT_MC(_modes); \
402         arg->is_variadic = _var; \
403         arg->mode_equals = _me;
404
405 void rflct_new_opcode(opcode opc, const char *name, int commutative)
406 {
407         rflct_opcode_t *ropc = obstack_alloc(&obst, sizeof(*ropc));
408
409         ropc->opc = opc;
410         ropc->name = name;
411         ropc->sig_count = 0;
412         memset(ropc->sigs, 0, sizeof(ropc->sigs));
413
414         assure_opcode_capacity(opc);
415         opcodes[opc] = ropc;
416 }
417
418 int rflct_opcode_add_signature(opcode opc, rflct_sig_t *sig)
419 {
420         rflct_arg_t *args = sig->args;
421         rflct_opcode_t *op = opcodes[opc];
422         int i;
423
424         assert(op && "Illegal opcode");
425
426         for(i = 0; i < MAX_SIG_COUNT && op->sigs[i] != NULL; i++);
427
428         if(i >= MAX_SIG_COUNT)
429                 return 0;
430
431         op->sigs[op->sig_count++] = args;
432
433         free(sig);
434         return 1;
435 }
436
437
438 rflct_sig_t *rflct_signature_allocate(int defs, int uses)
439 {
440         rflct_sig_t *sig = xmalloc(sizeof(*sig));
441
442         rflct_arg_t *args =
443                 obstack_alloc(&obst, sizeof(*args) * (defs + uses + 2));
444
445         rflct_arg_t *arg = args + defs;
446         MARK;
447
448         arg = args + defs + uses + 1;
449         FINISH;
450
451         sig->defs = defs;
452         sig->uses = uses;
453         sig->args = args;
454
455         return sig;
456 }
457
458 int rflct_signature_get_index(const rflct_sig_t *sig, int is_use, int num)
459 {
460         return is_use ? num + sig->defs + 1 : num;
461 }
462
463 #undef _ARG
464 #define _ARG(_name,_modes,_var,_me) \
465 arg->name = _name; \
466         arg->accepted_modes = _modes; \
467         arg->is_variadic = _var; \
468         arg->mode_equals = _me;
469
470 int rflct_signature_set_arg(rflct_sig_t *sig, int is_use, int num,
471                 const char *name, rflct_mode_class_t mc, int is_variadic, int mode_equals)
472 {
473         int index = rflct_signature_get_index(sig, is_use, num);
474         rflct_arg_t *arg = sig->args + index;
475         _ARG(name, mc, is_variadic, mode_equals);
476         return index;
477 }
478
479
480 void firm_init_rflct(void) {
481         init_ops();
482 }
483
484 #undef VARIADIC
485 #undef NON_VARIADIC