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