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
23 * @author Sebastian Hack
24 * @brief Reflection for Firm operands.
48 #include "irreflect.h"
50 #define obstack_grow_str(obst,s) obstack_grow((obst), (s), strlen((s)))
51 #define obstack_grow_str_const(obst,s) obstack_grow((obst), (s), sizeof((s)))
54 * Get the number of bits set in a word.
56 static INLINE int pop(int i) {
57 unsigned x = (unsigned) i;
58 x = ((x >> 1) & 0x55555555);
59 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
60 x = (x + (x >> 4)) & 0x0f0f0f0f;
63 return (int) (x & 0x3f);
67 * Get the number of bits differing in two variables.
69 static INLINE int dist(int x, int y) {
74 #define MAX_SIG_COUNT 8
75 #define MAX_ARG_COUNT 10
78 int num; /**< A sequential number (one opcode can have multiple signatures. */
79 rflct_arg_t args[]; /**< The signature. */
87 rflct_arg_t *sigs[MAX_SIG_COUNT];
90 static struct obstack obst;
92 static rflct_opcode_t **opcodes = NULL;
94 static int opcodes_size = 0;
96 static INLINE void assure_opcode_capacity(int opcode)
98 if(opcode >= opcodes_size) {
99 int new_size = 2 * opcode;
100 rflct_opcode_t **new_opcodes = xcalloc(new_size, sizeof(new_opcodes[0]));
102 if(opcodes != NULL) {
103 memcpy(new_opcodes, opcodes, sizeof(*opcodes) * opcodes_size);
107 opcodes = new_opcodes;
108 opcodes_size = new_size;
114 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
116 #define OPCODES_COUNT opcodes_size
119 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
120 mode_sort sort = get_mode_sort(mode);
124 case irms_control_flow:
127 else if(mode == mode_X)
130 return RFLCT_MC(Mem);
131 case irms_internal_boolean:
132 return RFLCT_MC(Bool);
133 case irms_int_number:
134 return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
135 case irms_float_number:
136 return RFLCT_MC(Float);
138 return RFLCT_MC(Ref);
140 return RFLCT_MC(Char);
143 return RFLCT_MC(None);
146 static INLINE const rflct_opcode_t *get_opcode(ir_opcode opc) {
147 assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
151 static INLINE const rflct_arg_t *get_args(ir_opcode opc, int sig) {
152 const rflct_opcode_t *opcode = get_opcode(opc);
153 assert(sig >= 0 && sig < opcode->sig_count
154 && "Invalid signature");
155 return opcode->sigs[sig];
158 #define GET_OPCODE(opc) get_opcode(opc)
159 #define GET_ARGS(opc,args) get_args(opc, args)
161 int rflct_get_signature_count(ir_opcode opc) {
162 const rflct_opcode_t *opcode = GET_OPCODE(opc);
163 return opcode->sig_count;
166 int rflct_get_in_args_count(ir_opcode opc, int sig) {
167 const rflct_arg_t *args = GET_ARGS(opc, sig);
170 for(i = 0; args[i].name != NULL; i++);
171 for(res = 0, i += 1; args[i].name != NULL; res++, i++);
175 int rflct_get_out_args_count(ir_opcode opc, int sig) {
176 const rflct_arg_t *args = GET_ARGS(opc, sig);
178 for(i = 0; args[i].name != NULL; i++);
183 const rflct_arg_t *rflct_get_in_args(ir_opcode opc, int sig) {
184 const rflct_arg_t *args = GET_ARGS(opc, sig);
187 for(i = 0; args[i].name != NULL; i++);
191 const rflct_arg_t *rflct_get_out_args(ir_opcode opc, int sig) {
192 return GET_ARGS(opc, sig);
195 int rflct_signature_match(const ir_node *irn, int sig) {
196 ir_opcode op = get_irn_opcode(irn);
197 const rflct_arg_t *args = rflct_get_in_args(op, sig);
201 for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
202 && j < get_irn_arity(irn); j++) {
204 ir_node *child = get_irn_n(irn, j);
205 const rflct_arg_t *arg = &args[i];
206 rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
208 if(arg->accepted_modes & mc)
209 dst += dist(arg->accepted_modes, mc);
213 if(!arg->is_variadic)
220 int rflct_get_signature(const ir_node *irn) {
221 const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
222 int min_dist = INT_MAX;
223 int min_sig = INT_MAX;
226 for(i = 0; i < opc->sig_count; i++) {
227 int dist = rflct_signature_match(irn, i);
228 if(dist < min_dist) {
237 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
238 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
265 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
266 rflct_mode_class_t mc) {
267 const char *res = rflct_mode_class_atomic_name(mc);
269 if(strlen(res) == 0) {
270 const char *prefix = "";
273 obstack_1grow(obst, '{');
274 for(mask = 1; mask != 0; mask <<= 1) {
276 const char *s = rflct_mode_class_atomic_name(mask);
277 obstack_grow_str(obst, s);
278 obstack_grow_str(obst, prefix);
282 obstack_1grow(obst, '}');
285 obstack_grow(obst, res, strlen(res));
288 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
294 rflct_mode_class_comb_name_obst(&obst, mc);
295 obstack_1grow(&obst, 0);
296 res = obstack_finish(&obst);
298 strncpy(str, res, n);
300 obstack_free(&obst, NULL);
305 static void rflct_obstack_grow_args(struct obstack *obst,
306 const rflct_arg_t *args) {
307 const rflct_arg_t *arg;
308 const char *prefix = "";
310 for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
311 obstack_grow_str(obst, prefix);
312 obstack_grow_str(obst, arg->name);
314 obstack_1grow(obst, '*');
315 obstack_1grow(obst, ':');
316 rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
322 char *rflct_to_string(char *buf, int n, ir_opcode opc, int sig) {
325 const rflct_opcode_t *opcode = GET_OPCODE(opc);
329 obstack_1grow(&obst, '(');
330 rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
332 obstack_grow_str(&obst, ") = ");
333 obstack_grow_str(&obst, opcode->name);
334 obstack_1grow(&obst, '(');
336 rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
338 obstack_1grow(&obst, ')');
339 obstack_1grow(&obst, 0);
340 s = obstack_finish(&obst);
342 obstack_free(&obst, NULL);
347 #define NON_VARIADIC 0
350 #define ARG(name,modes) \
351 _ARG(name, modes, NON_VARIADIC, -1)
353 #define ARG_SAME(name,modes,mode_same) \
354 _ARG(name, modes, NON_VARIADIC, mode_same)
356 #define VARG(name,modes) \
357 _ARG(name, modes, VARIADIC, 0)
359 #define VARG_SAME(name,modes) \
360 _ARG(name, modes, VARIADIC, 1)
363 _ARG(NULL, None, NON_VARIADIC, -1)
366 _ARG(NULL, None, NON_VARIADIC, 0)
368 #define BLOCK ARG("Block", BB)
370 static void init_ops(void) {
373 rflct_opcode_t *opcode;
377 assure_opcode_capacity(iro_MaxOpcode);
380 #define BEGIN_OP(op) \
382 opcode = obstack_alloc(&obst, sizeof(*opcode)); \
383 opcode->opc = iro_ ## op; \
384 opcode->name = #op; \
385 opcodes[opcode->opc] = opcode;
390 #define _ARG(_name,_modes,_variadic,_mode_equals) \
394 args.accepted_modes = RFLCT_MC(_modes); \
395 args.is_variadic = _variadic; \
396 args.mode_equals = _mode_equals; \
397 obstack_grow(&obst, &args, sizeof(args)); \
403 assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
404 opcode->sigs[curr_sig++] = obstack_finish(&obst); \
405 opcode->sig_count = curr_sig; \
410 #include "irreflect.def"
419 #define _ARG(_name,_modes,_var,_me) \
421 arg->accepted_modes = RFLCT_MC(_modes); \
422 arg->is_variadic = _var; \
423 arg->mode_equals = _me;
425 void rflct_new_opcode(ir_opcode opc, const char *name, int commutative)
427 rflct_opcode_t *ropc = obstack_alloc(&obst, sizeof(*ropc));
432 memset(ropc->sigs, 0, sizeof(ropc->sigs));
434 assure_opcode_capacity(opc);
438 int rflct_opcode_add_signature(ir_opcode opc, rflct_sig_t *sig)
440 rflct_arg_t *args = sig->args;
441 rflct_opcode_t *op = opcodes[opc];
444 assert(op && "Illegal opcode");
446 for(i = 0; i < MAX_SIG_COUNT && op->sigs[i] != NULL; i++);
448 if(i >= MAX_SIG_COUNT)
451 op->sigs[op->sig_count++] = args;
458 rflct_sig_t *rflct_signature_allocate(int defs, int uses)
460 rflct_sig_t *sig = xmalloc(sizeof(*sig));
463 obstack_alloc(&obst, sizeof(*args) * (defs + uses + 2));
465 rflct_arg_t *arg = args + defs;
468 arg = args + defs + uses + 1;
478 int rflct_signature_get_index(const rflct_sig_t *sig, int is_use, int num)
480 return is_use ? num + sig->defs + 1 : num;
484 #define _ARG(_name,_modes,_var,_me) \
486 arg->accepted_modes = _modes; \
487 arg->is_variadic = _var; \
488 arg->mode_equals = _me;
490 int rflct_signature_set_arg(rflct_sig_t *sig, int is_use, int num,
491 const char *name, rflct_mode_class_t mc, int is_variadic, int mode_equals)
493 int index = rflct_signature_get_index(sig, is_use, num);
494 rflct_arg_t *arg = sig->args + index;
495 _ARG(name, mc, is_variadic, mode_equals);
500 void firm_init_rflct(void) {