4 * @author Sebastian Hack
5 * @brief Reflection for Firm operands.
14 #define obstack_chunk_alloc malloc
15 #define obstack_chunk_free free
19 #include "irreflect.h"
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)))
24 extern int obstack_printf(struct obstack *obst, const char *fmt, ...);
29 * Get the number of bits set in a word.
31 static INLINE int pop(int i) {
32 unsigned x = (unsigned) i;
33 x = ((x >> 1) & 0x55555555);
34 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
35 x = (x + (x >> 4)) & 0x0f0f0f0f;
38 return (int) (x & 0x3f);
42 * Get the number of bits differing in two variables.
44 static INLINE int dist(int x, int y) {
49 #define MAX_SIG_COUNT 8
50 #define MAX_ARG_COUNT 10
53 int num; /**< A sequential number (one opcode can have multiple signatures. */
54 rflct_arg_t args[]; /**< The signature. */
62 const rflct_arg_t *sigs[MAX_SIG_COUNT];
65 static struct obstack obst;
67 static rflct_opcode_t **opcodes = NULL;
69 static int opcodes_size = 0;
71 static INLINE void assure_opcode_capacity(int opcode)
73 if(opcode >= opcodes_size) {
74 int new_size = 2 * opcode;
75 rflct_opcode_t **new_opcodes = malloc(sizeof(*new_opcodes) * new_size);
77 memset(new_opcodes, 0, sizeof(*new_opcodes) * new_size);
80 memcpy(new_opcodes, opcodes, sizeof(*opcodes) * opcodes_size);
84 opcodes = new_opcodes;
85 opcodes_size = new_size;
90 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
93 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
94 mode_sort sort = get_mode_sort(mode);
98 case irms_control_flow:
101 else if(mode == mode_X)
104 return RFLCT_MC(Mem);
105 case irms_internal_boolean:
106 return RFLCT_MC(Bool);
107 case irms_int_number:
108 return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
109 case irms_float_number:
110 return RFLCT_MC(Float);
112 return RFLCT_MC(Ref);
114 return RFLCT_MC(Char);
117 return RFLCT_MC(None);
120 static INLINE const rflct_opcode_t *get_opcode(opcode opc) {
121 assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
125 static INLINE const rflct_arg_t *get_args(opcode opc, int sig) {
126 const rflct_opcode_t *opcode = get_opcode(opc);
127 assert(sig >= 0 && sig < opcode->sig_count
128 && "Invalid signature");
129 return opcode->sigs[sig];
132 #define GET_OPCODE(opc) get_opcode(opc)
133 #define GET_ARGS(opc,args) get_args(opc, args)
135 int rflct_get_signature_count(opcode opc) {
136 const rflct_opcode_t *opcode = GET_OPCODE(opc);
137 return opcode->sig_count;
140 int rflct_get_in_args_count(opcode opc, int sig) {
141 const rflct_arg_t *args = GET_ARGS(opc, sig);
144 for(i = 0; args[i].name != NULL; i++);
145 for(res = 0, i += 1; args[i].name != NULL; res++, i++);
149 int rflct_get_out_args_count(opcode opc, int sig) {
150 const rflct_arg_t *args = GET_ARGS(opc, sig);
152 for(i = 0; args[i].name != NULL; i++);
157 const rflct_arg_t *rflct_get_in_args(opcode opc, int sig) {
158 const rflct_arg_t *args = GET_ARGS(opc, sig);
161 for(i = 0; args[i].name != NULL; i++);
165 const rflct_arg_t *rflct_get_out_args(opcode opc, int sig) {
166 return GET_ARGS(opc, sig);
169 int rflct_signature_match(ir_node *irn, int sig) {
170 opcode op = get_irn_opcode(irn);
171 const rflct_arg_t *args = rflct_get_in_args(op, sig);
175 for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
176 && j < get_irn_arity(irn); j++) {
178 ir_node *child = get_irn_n(irn, j);
179 const rflct_arg_t *arg = &args[i];
180 rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
182 if(arg->accepted_modes & mc)
183 dst += dist(arg->accepted_modes, mc);
187 if(!arg->is_variadic)
194 int rflct_get_signature(ir_node *irn) {
195 const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
196 int min_dist = INT_MAX;
197 int min_sig = INT_MAX;
200 for(i = 0; i < opc->sig_count; i++) {
201 int dist = rflct_signature_match(irn, i);
202 if(dist < min_dist) {
211 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
212 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
239 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
240 rflct_mode_class_t mc) {
241 const char *res = rflct_mode_class_atomic_name(mc);
243 if(strlen(res) == 0) {
244 const char *prefix = "";
247 obstack_1grow(obst, '{');
248 for(mask = 1; mask != 0; mask <<= 1) {
250 const char *s = rflct_mode_class_atomic_name(mask);
251 obstack_grow_str(obst, s);
252 obstack_grow_str(obst, prefix);
256 obstack_1grow(obst, '}');
259 obstack_grow(obst, res, strlen(res));
262 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
268 rflct_mode_class_comb_name_obst(&obst, mc);
269 obstack_1grow(&obst, 0);
270 res = obstack_finish(&obst);
272 strncpy(str, res, n);
274 obstack_free(&obst, NULL);
279 static void rflct_obstack_grow_args(struct obstack *obst,
280 const rflct_arg_t *args) {
281 const rflct_arg_t *arg;
282 const char *prefix = "";
284 for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
285 obstack_grow_str(obst, prefix);
286 obstack_grow_str(obst, arg->name);
288 obstack_1grow(obst, '*');
289 obstack_1grow(obst, ':');
290 rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
296 char *rflct_to_string(char *buf, int n, opcode opc, int sig) {
299 const rflct_opcode_t *opcode = GET_OPCODE(opc);
303 obstack_1grow(&obst, '(');
304 rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
306 obstack_grow_str(&obst, ") = ");
307 obstack_grow_str(&obst, opcode->name);
308 obstack_1grow(&obst, '(');
310 rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
312 obstack_1grow(&obst, ')');
313 obstack_1grow(&obst, 0);
314 s = obstack_finish(&obst);
316 obstack_free(&obst, NULL);
321 #define ARG(name,modes) \
322 _ARG(name, modes, false, -1)
324 #define ARG_SAME(name,modes,mode_same) \
325 _ARG(name, modes, false, mode_same)
327 #define VARG(name,modes) \
328 _ARG(name, modes, true, 0)
330 #define VARG_SAME(name,modes) \
331 _ARG(name, modes, true, 1)
334 _ARG(NULL, None, false, -1)
337 _ARG(NULL, None, false, 0)
339 #define BLOCK ARG("Block", BB)
341 static void init_ops(void) {
344 rflct_opcode_t *opcode;
348 assure_opcode_capacity(iro_MaxOpcode);
351 #define BEGIN_OP(op) \
353 opcode = obstack_alloc(&obst, sizeof(*opcode)); \
354 opcode->opc = iro_ ## op; \
355 opcode->name = #op; \
356 opcodes[opcode->opc] = opcode;
361 #define _ARG(_name,_modes,_variadic,_mode_equals) \
365 args.accepted_modes = RFLCT_MC(_modes); \
366 args.is_variadic = _variadic; \
367 args.mode_equals = _mode_equals; \
368 obstack_grow(&obst, &args, sizeof(args)); \
374 assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
375 opcode->sigs[curr_sig++] = obstack_finish(&obst); \
376 opcode->sig_count = curr_sig; \
381 #include "irreflect.def"
390 #define _ARG(_name,_modes,_var,_me) \
392 arg->accepted_modes = RFLCT_MC(_modes); \
393 arg->is_variadic = _var; \
394 arg->mode_equals = _me;
396 void rflct_new_opcode(opcode opc, const char *name, bool commutative)
398 rflct_opcode_t *ropc = obstack_alloc(&obst, sizeof(*ropc));
403 memset(ropc->sigs, 0, sizeof(ropc->sigs));
405 assure_opcode_capacity(opc);
409 bool rflct_opcode_add_signature(opcode opc, rflct_sig_t *sig)
411 const rflct_arg_t *args = sig->args;
412 rflct_opcode_t *op = opcodes[opc];
415 assert(op && "Illegal opcode");
417 for(i = 0; i < MAX_SIG_COUNT && op->sigs[i] != NULL; i++);
419 if(i >= MAX_SIG_COUNT)
422 op->sigs[op->sig_count++] = args;
429 rflct_sig_t *rflct_signature_allocate(int defs, int uses)
431 rflct_sig_t *sig = malloc(sizeof(*sig));
434 obstack_alloc(&obst, sizeof(*args) * (defs + uses + 2));
436 rflct_arg_t *arg = args + defs;
439 arg = args + defs + uses + 1;
449 int rflct_signature_get_index(const rflct_sig_t *sig, bool is_use, int num)
451 return is_use ? num + sig->defs + 1 : num;
455 #define _ARG(_name,_modes,_var,_me) \
457 arg->accepted_modes = _modes; \
458 arg->is_variadic = _var; \
459 arg->mode_equals = _me;
461 int rflct_signature_set_arg(rflct_sig_t *sig, bool is_use, int num,
462 const char *name, rflct_mode_class_t mc, bool is_variadic, int mode_equals)
464 int index = rflct_signature_get_index(sig, is_use, num);
465 rflct_arg_t *arg = sig->args + index;
466 _ARG(name, mc, is_variadic, mode_equals);
471 void init_rflct(void) {