2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Reflection for Firm operands.
23 * @author Sebastian Hack
47 #include "irreflect.h"
49 #define obstack_grow_str(obst,s) obstack_grow((obst), (s), strlen((s)))
50 #define obstack_grow_str_const(obst,s) obstack_grow((obst), (s), sizeof((s)))
53 * Get the number of bits set in a word.
55 static INLINE int pop(int i) {
56 unsigned x = (unsigned) i;
57 x = ((x >> 1) & 0x55555555);
58 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
59 x = (x + (x >> 4)) & 0x0f0f0f0f;
62 return (int) (x & 0x3f);
66 * Get the number of bits differing in two variables.
68 static INLINE int dist(int x, int y) {
73 #define MAX_SIG_COUNT 8
74 #define MAX_ARG_COUNT 10
77 int num; /**< A sequential number (one opcode can have multiple signatures. */
78 rflct_arg_t args[]; /**< The signature. */
86 rflct_arg_t *sigs[MAX_SIG_COUNT];
89 static struct obstack obst;
91 static rflct_opcode_t **opcodes = NULL;
93 static int opcodes_size = 0;
95 static INLINE void assure_opcode_capacity(int opcode)
97 if(opcode >= opcodes_size) {
98 int new_size = 2 * opcode;
99 rflct_opcode_t **new_opcodes = xcalloc(new_size, sizeof(new_opcodes[0]));
101 if(opcodes != NULL) {
102 memcpy(new_opcodes, opcodes, sizeof(*opcodes) * opcodes_size);
106 opcodes = new_opcodes;
107 opcodes_size = new_size;
113 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
115 #define OPCODES_COUNT opcodes_size
118 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
119 mode_sort sort = get_mode_sort(mode);
123 case irms_control_flow:
126 else if(mode == mode_X)
129 return RFLCT_MC(Mem);
130 case irms_internal_boolean:
131 return RFLCT_MC(Bool);
132 case irms_int_number:
133 return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
134 case irms_float_number:
135 return RFLCT_MC(Float);
137 return RFLCT_MC(Ref);
139 return RFLCT_MC(Char);
142 return RFLCT_MC(None);
145 static INLINE const rflct_opcode_t *get_opcode(ir_opcode opc) {
146 assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
150 static INLINE const rflct_arg_t *get_args(ir_opcode opc, int sig) {
151 const rflct_opcode_t *opcode = get_opcode(opc);
152 assert(sig >= 0 && sig < opcode->sig_count
153 && "Invalid signature");
154 return opcode->sigs[sig];
157 #define GET_OPCODE(opc) get_opcode(opc)
158 #define GET_ARGS(opc,args) get_args(opc, args)
160 int rflct_get_signature_count(ir_opcode opc) {
161 const rflct_opcode_t *opcode = GET_OPCODE(opc);
162 return opcode->sig_count;
165 int rflct_get_in_args_count(ir_opcode opc, int sig) {
166 const rflct_arg_t *args = GET_ARGS(opc, sig);
169 for(i = 0; args[i].name != NULL; i++);
170 for(res = 0, i += 1; args[i].name != NULL; res++, i++);
174 int rflct_get_out_args_count(ir_opcode opc, int sig) {
175 const rflct_arg_t *args = GET_ARGS(opc, sig);
177 for(i = 0; args[i].name != NULL; i++);
182 const rflct_arg_t *rflct_get_in_args(ir_opcode opc, int sig) {
183 const rflct_arg_t *args = GET_ARGS(opc, sig);
186 for(i = 0; args[i].name != NULL; i++);
190 const rflct_arg_t *rflct_get_out_args(ir_opcode opc, int sig) {
191 return GET_ARGS(opc, sig);
194 int rflct_signature_match(const ir_node *irn, int sig) {
195 ir_opcode op = get_irn_opcode(irn);
196 const rflct_arg_t *args = rflct_get_in_args(op, sig);
200 for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
201 && j < get_irn_arity(irn); j++) {
203 ir_node *child = get_irn_n(irn, j);
204 const rflct_arg_t *arg = &args[i];
205 rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
207 if(arg->accepted_modes & mc)
208 dst += dist(arg->accepted_modes, mc);
212 if(!arg->is_variadic)
219 int rflct_get_signature(const ir_node *irn) {
220 const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
221 int min_dist = INT_MAX;
222 int min_sig = INT_MAX;
225 for(i = 0; i < opc->sig_count; i++) {
226 int dist = rflct_signature_match(irn, i);
227 if(dist < min_dist) {
236 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
237 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
264 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
265 rflct_mode_class_t mc) {
266 const char *res = rflct_mode_class_atomic_name(mc);
268 if(strlen(res) == 0) {
269 const char *prefix = "";
272 obstack_1grow(obst, '{');
273 for(mask = 1; mask != 0; mask <<= 1) {
275 const char *s = rflct_mode_class_atomic_name(mask);
276 obstack_grow_str(obst, s);
277 obstack_grow_str(obst, prefix);
281 obstack_1grow(obst, '}');
284 obstack_grow(obst, res, strlen(res));
287 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
293 rflct_mode_class_comb_name_obst(&obst, mc);
294 obstack_1grow(&obst, 0);
295 res = obstack_finish(&obst);
297 strncpy(str, res, n);
299 obstack_free(&obst, NULL);
304 static void rflct_obstack_grow_args(struct obstack *obst,
305 const rflct_arg_t *args) {
306 const rflct_arg_t *arg;
307 const char *prefix = "";
309 for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
310 obstack_grow_str(obst, prefix);
311 obstack_grow_str(obst, arg->name);
313 obstack_1grow(obst, '*');
314 obstack_1grow(obst, ':');
315 rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
321 char *rflct_to_string(char *buf, int n, ir_opcode opc, int sig) {
324 const rflct_opcode_t *opcode = GET_OPCODE(opc);
328 obstack_1grow(&obst, '(');
329 rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
331 obstack_grow_str(&obst, ") = ");
332 obstack_grow_str(&obst, opcode->name);
333 obstack_1grow(&obst, '(');
335 rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
337 obstack_1grow(&obst, ')');
338 obstack_1grow(&obst, 0);
339 s = obstack_finish(&obst);
341 obstack_free(&obst, NULL);
346 #define NON_VARIADIC 0
349 #define ARG(name,modes) \
350 _ARG(name, modes, NON_VARIADIC, -1)
352 #define ARG_SAME(name,modes,mode_same) \
353 _ARG(name, modes, NON_VARIADIC, mode_same)
355 #define VARG(name,modes) \
356 _ARG(name, modes, VARIADIC, 0)
358 #define VARG_SAME(name,modes) \
359 _ARG(name, modes, VARIADIC, 1)
362 _ARG(NULL, None, NON_VARIADIC, -1)
365 _ARG(NULL, None, NON_VARIADIC, 0)
367 #define BLOCK ARG("Block", BB)
369 static void init_ops(void) {
372 rflct_opcode_t *opcode;
376 assure_opcode_capacity(iro_MaxOpcode);
379 #define BEGIN_OP(op) \
381 opcode = obstack_alloc(&obst, sizeof(*opcode)); \
382 opcode->opc = iro_ ## op; \
383 opcode->name = #op; \
384 opcodes[opcode->opc] = opcode;
389 #define _ARG(_name,_modes,_variadic,_mode_equals) \
393 args.accepted_modes = RFLCT_MC(_modes); \
394 args.is_variadic = _variadic; \
395 args.mode_equals = _mode_equals; \
396 obstack_grow(&obst, &args, sizeof(args)); \
402 assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
403 opcode->sigs[curr_sig++] = obstack_finish(&obst); \
404 opcode->sig_count = curr_sig; \
409 #include "irreflect.def"
418 #define _ARG(_name,_modes,_var,_me) \
420 arg->accepted_modes = RFLCT_MC(_modes); \
421 arg->is_variadic = _var; \
422 arg->mode_equals = _me;
424 void rflct_new_opcode(ir_opcode opc, const char *name, int commutative)
426 rflct_opcode_t *ropc = obstack_alloc(&obst, sizeof(*ropc));
431 memset(ropc->sigs, 0, sizeof(ropc->sigs));
433 assure_opcode_capacity(opc);
437 int rflct_opcode_add_signature(ir_opcode opc, rflct_sig_t *sig)
439 rflct_arg_t *args = sig->args;
440 rflct_opcode_t *op = opcodes[opc];
443 assert(op && "Illegal opcode");
445 for(i = 0; i < MAX_SIG_COUNT && op->sigs[i] != NULL; i++);
447 if(i >= MAX_SIG_COUNT)
450 op->sigs[op->sig_count++] = args;
457 rflct_sig_t *rflct_signature_allocate(int defs, int uses)
459 rflct_sig_t *sig = xmalloc(sizeof(*sig));
462 obstack_alloc(&obst, sizeof(*args) * (defs + uses + 2));
464 rflct_arg_t *arg = args + defs;
467 arg = args + defs + uses + 1;
477 int rflct_signature_get_index(const rflct_sig_t *sig, int is_use, int num)
479 return is_use ? num + sig->defs + 1 : num;
483 #define _ARG(_name,_modes,_var,_me) \
485 arg->accepted_modes = _modes; \
486 arg->is_variadic = _var; \
487 arg->mode_equals = _me;
489 int rflct_signature_set_arg(rflct_sig_t *sig, int is_use, int num,
490 const char *name, rflct_mode_class_t mc, int is_variadic, int mode_equals)
492 int index = rflct_signature_get_index(sig, is_use, num);
493 rflct_arg_t *arg = sig->args + index;
494 _ARG(name, mc, is_variadic, mode_equals);
499 void firm_init_rflct(void) {