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, ...);
27 * Get the number of bits set in a word.
29 static inline int pop(int i) {
30 unsigned x = (unsigned) i;
31 x = ((x >> 1) & 0x55555555);
32 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
33 x = (x + (x >> 4)) & 0x0f0f0f0f;
36 return (int) (x & 0x3f);
40 * Get the number of bits differing in two variables.
42 static inline int dist(int x, int y) {
47 #define MAX_SIG_COUNT 8
48 #define MAX_ARG_COUNT 10
51 int num; /**< A sequential number (one opcode can have multiple signatures. */
52 rflct_arg_t args[]; /**< The signature. */
60 const rflct_arg_t *sigs[MAX_SIG_COUNT];
63 static struct obstack obst;
65 static const rflct_opcode_t *opcodes[iro_MaxOpcode];
67 #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0]))
69 // #define MODE_IS(mode,mask) (((mode) & (mask)) != 0)
71 rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) {
72 mode_sort sort = get_mode_sort(mode);
76 case irms_control_flow:
79 else if(mode == mode_X)
83 case irms_internal_boolean:
84 return RFLCT_MC(Bool);
86 return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU);
87 case irms_float_number:
88 return RFLCT_MC(Float);
92 return RFLCT_MC(Char);
95 return RFLCT_MC(None);
98 static inline const rflct_opcode_t *get_opcode(opcode opc) {
99 assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode");
103 static inline const rflct_arg_t *get_args(opcode opc, int sig) {
104 const rflct_opcode_t *opcode = get_opcode(opc);
105 assert(sig >= 0 && sig < opcode->sig_count
106 && "Invalid signature");
107 return opcode->sigs[sig];
110 #define GET_OPCODE(opc) get_opcode(opc)
111 #define GET_ARGS(opc,args) get_args(opc, args)
113 int rflct_get_signature_count(opcode opc) {
114 const rflct_opcode_t *opcode = GET_OPCODE(opc);
115 return opcode->sig_count;
118 int rflct_get_in_args_count(opcode opc, int sig) {
119 const rflct_arg_t *args = GET_ARGS(opc, sig);
122 for(i = 0; args[i].name != NULL; i++);
123 for(res = 0, i += 1; args[i].name != NULL; res++, i++);
127 int rflct_get_out_args_count(opcode opc, int sig) {
128 const rflct_arg_t *args = GET_ARGS(opc, sig);
130 for(i = 0; args[i].name != NULL; i++);
135 const rflct_arg_t *rflct_get_in_args(opcode opc, int sig) {
136 const rflct_arg_t *args = GET_ARGS(opc, sig);
139 for(i = 0; args[i].name != NULL; i++);
143 const rflct_arg_t *rflct_get_out_args(opcode opc, int sig) {
144 return GET_ARGS(opc, sig);
147 int rflct_signature_match(ir_node *irn, int sig) {
148 opcode op = get_irn_opcode(irn);
149 const rflct_arg_t *args = rflct_get_in_args(op, sig);
153 for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i])
154 && j < get_irn_arity(irn); j++) {
156 ir_node *child = get_irn_n(irn, j);
157 const rflct_arg_t *arg = &args[i];
158 rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child));
160 if(arg->accepted_modes & mc)
161 dst += dist(arg->accepted_modes, mc);
165 if(!arg->is_variadic)
172 int rflct_get_signature(ir_node *irn) {
173 const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn));
174 int min_dist = INT_MAX;
175 int min_sig = INT_MAX;
178 for(i = 0; i < opc->sig_count; i++) {
179 int dist = rflct_signature_match(irn, i);
180 if(dist < min_dist) {
189 static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) {
190 #define XXX(_mc) case RFLCT_MC(_mc): return #_mc
217 static void rflct_mode_class_comb_name_obst(struct obstack *obst,
218 rflct_mode_class_t mc) {
219 const char *res = rflct_mode_class_atomic_name(mc);
221 if(strlen(res) == 0) {
222 const char *prefix = "";
225 obstack_1grow(obst, '{');
226 for(mask = 1; mask != 0; mask <<= 1) {
228 const char *s = rflct_mode_class_atomic_name(mask);
229 obstack_grow_str(obst, s);
230 obstack_grow_str(obst, prefix);
234 obstack_1grow(obst, '}');
237 obstack_grow(obst, res, strlen(res));
240 char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) {
246 rflct_mode_class_comb_name_obst(&obst, mc);
247 obstack_1grow(&obst, 0);
248 res = obstack_finish(&obst);
250 strncpy(str, res, n);
252 obstack_free(&obst, NULL);
257 static void rflct_obstack_grow_args(struct obstack *obst,
258 const rflct_arg_t *args) {
259 const rflct_arg_t *arg;
260 const char *prefix = "";
262 for(arg = args; RFLCT_ARG_VALID(arg); arg++) {
263 obstack_grow_str(obst, prefix);
264 obstack_grow_str(obst, arg->name);
266 obstack_1grow(obst, '*');
267 obstack_1grow(obst, ':');
268 rflct_mode_class_comb_name_obst(obst, arg->accepted_modes);
274 char *rflct_to_string(char *buf, int n, opcode opc, int sig) {
277 const rflct_opcode_t *opcode = GET_OPCODE(opc);
281 obstack_1grow(&obst, '(');
282 rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig));
284 obstack_grow_str(&obst, ") = ");
285 obstack_grow_str(&obst, opcode->name);
286 obstack_1grow(&obst, '(');
288 rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig));
290 obstack_1grow(&obst, ')');
291 obstack_1grow(&obst, 0);
292 s = obstack_finish(&obst);
294 obstack_free(&obst, NULL);
299 #define ARG(name,modes) \
300 _ARG(name, modes, false, -1)
302 #define ARG_SAME(name,modes,mode_same) \
303 _ARG(name, modes, false, mode_same)
305 #define VARG(name,modes) \
306 _ARG(name, modes, true, 0)
308 #define VARG_SAME(name,modes) \
309 _ARG(name, modes, true, 1)
312 _ARG(NULL, None, false, -1)
314 #define BLOCK ARG("Block", BB)
316 static void init_ops(void) {
319 rflct_opcode_t *opcode;
324 #define BEGIN_OP(op) \
326 opcode = obstack_alloc(&obst, sizeof(*opcode)); \
327 opcode->opc = iro_ ## op; \
328 opcode->name = #op; \
329 opcodes[opcode->opc] = opcode;
334 #define _ARG(_name,_modes,_variadic,_mode_equals) \
338 args.accepted_modes = RFLCT_MC(_modes); \
339 args.is_variadic = _variadic; \
340 args.mode_equals = _mode_equals; \
341 obstack_grow(&obst, &args, sizeof(args)); \
346 _ARG(NULL, None, false, 0) \
347 assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \
348 opcode->sigs[curr_sig++] = obstack_finish(&obst); \
349 opcode->sig_count = curr_sig; \
354 #include "irreflect.def"
365 void init_rflct(void) {