From eda212f88988120cf090de003feaaf4898200008 Mon Sep 17 00:00:00 2001 From: Sebastian Hack Date: Tue, 12 Oct 2004 09:57:29 +0000 Subject: [PATCH] Added dynamic extension of reflection. [r4107] --- ir/ir/irreflect.c | 522 ++++++++++++++++++++++++++++------------------ ir/ir/irreflect.h | 67 +++++- 2 files changed, 380 insertions(+), 209 deletions(-) diff --git a/ir/ir/irreflect.c b/ir/ir/irreflect.c index 0b1ce6621..ad211f6a3 100644 --- a/ir/ir/irreflect.c +++ b/ir/ir/irreflect.c @@ -23,24 +23,26 @@ extern int obstack_printf(struct obstack *obst, const char *fmt, ...); +#define INLINE inline + /** * Get the number of bits set in a word. */ -static inline int pop(int i) { - unsigned x = (unsigned) i; - x = ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0f0f0f0f; - x = x + (x >> 8); - x = x + (x >> 16); - return (int) (x & 0x3f); +static INLINE int pop(int i) { + unsigned x = (unsigned) i; + x = ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x = x + (x >> 8); + x = x + (x >> 16); + return (int) (x & 0x3f); } /** * Get the number of bits differing in two variables. */ -static inline int dist(int x, int y) { - return pop(x ^ y); +static INLINE int dist(int x, int y) { + return pop(x ^ y); } @@ -48,306 +50,331 @@ static inline int dist(int x, int y) { #define MAX_ARG_COUNT 10 typedef struct { - int num; /**< A sequential number (one opcode can have multiple signatures. */ - rflct_arg_t args[]; /**< The signature. */ + int num; /**< A sequential number (one opcode can have multiple signatures. */ + rflct_arg_t args[]; /**< The signature. */ } rflct_args_t; typedef struct { - opcode opc; - const char *name; - bool commutative; - int sig_count; - const rflct_arg_t *sigs[MAX_SIG_COUNT]; + opcode opc; + const char *name; + bool commutative; + int sig_count; + const rflct_arg_t *sigs[MAX_SIG_COUNT]; } rflct_opcode_t; static struct obstack obst; -static const rflct_opcode_t *opcodes[iro_MaxOpcode]; +static rflct_opcode_t **opcodes = NULL; + +static int opcodes_size = 0; + +static INLINE void assure_opcode_capacity(int opcode) +{ + if(opcode >= opcodes_size) { + int new_size = 2 * opcode; + rflct_opcode_t **new_opcodes = malloc(sizeof(*new_opcodes) * new_size); + + memset(new_opcodes, 0, sizeof(*new_opcodes) * new_size); + + if(opcodes != NULL) { + memcpy(new_opcodes, opcodes, sizeof(*opcodes) * opcodes_size); + free(opcodes); + } + + opcodes = new_opcodes; + opcodes_size = new_size; + } +} + #define OPCODES_COUNT (sizeof(opcodes) / sizeof(opcodes[0])) -// #define MODE_IS(mode,mask) (((mode) & (mask)) != 0) rflct_mode_class_t rflct_get_mode_class(const ir_mode *mode) { - mode_sort sort = get_mode_sort(mode); - - switch(sort) { - case irms_auxiliary: - case irms_control_flow: - if(mode == mode_BB) - return RFLCT_MC(BB); - else if(mode == mode_X) - return RFLCT_MC(X); - case irms_memory: - return RFLCT_MC(Mem); - case irms_internal_boolean: - return RFLCT_MC(Bool); - case irms_int_number: - return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU); - case irms_float_number: - return RFLCT_MC(Float); - case irms_reference: - return RFLCT_MC(Ref); - case irms_character: - return RFLCT_MC(Char); - } - - return RFLCT_MC(None); + mode_sort sort = get_mode_sort(mode); + + switch(sort) { + case irms_auxiliary: + case irms_control_flow: + if(mode == mode_BB) + return RFLCT_MC(BB); + else if(mode == mode_X) + return RFLCT_MC(X); + case irms_memory: + return RFLCT_MC(Mem); + case irms_internal_boolean: + return RFLCT_MC(Bool); + case irms_int_number: + return mode_is_signed(mode) ? RFLCT_MC(IntS) : RFLCT_MC(IntU); + case irms_float_number: + return RFLCT_MC(Float); + case irms_reference: + return RFLCT_MC(Ref); + case irms_character: + return RFLCT_MC(Char); + } + + return RFLCT_MC(None); } -static inline const rflct_opcode_t *get_opcode(opcode opc) { - assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode"); - return opcodes[opc]; +static INLINE const rflct_opcode_t *get_opcode(opcode opc) { + assert(opc >= 0 && opc < OPCODES_COUNT && "Invalid opcode"); + return opcodes[opc]; } -static inline const rflct_arg_t *get_args(opcode opc, int sig) { - const rflct_opcode_t *opcode = get_opcode(opc); - assert(sig >= 0 && sig < opcode->sig_count - && "Invalid signature"); - return opcode->sigs[sig]; +static INLINE const rflct_arg_t *get_args(opcode opc, int sig) { + const rflct_opcode_t *opcode = get_opcode(opc); + assert(sig >= 0 && sig < opcode->sig_count + && "Invalid signature"); + return opcode->sigs[sig]; } #define GET_OPCODE(opc) get_opcode(opc) #define GET_ARGS(opc,args) get_args(opc, args) int rflct_get_signature_count(opcode opc) { - const rflct_opcode_t *opcode = GET_OPCODE(opc); - return opcode->sig_count; + const rflct_opcode_t *opcode = GET_OPCODE(opc); + return opcode->sig_count; } int rflct_get_in_args_count(opcode opc, int sig) { - const rflct_arg_t *args = GET_ARGS(opc, sig); - int res = 0, i = 0; + const rflct_arg_t *args = GET_ARGS(opc, sig); + int res = 0, i = 0; - for(i = 0; args[i].name != NULL; i++); - for(res = 0, i += 1; args[i].name != NULL; res++, i++); - return res; + for(i = 0; args[i].name != NULL; i++); + for(res = 0, i += 1; args[i].name != NULL; res++, i++); + return res; } int rflct_get_out_args_count(opcode opc, int sig) { - const rflct_arg_t *args = GET_ARGS(opc, sig); - int i = 0; - for(i = 0; args[i].name != NULL; i++); - return i; + const rflct_arg_t *args = GET_ARGS(opc, sig); + int i = 0; + for(i = 0; args[i].name != NULL; i++); + return i; } const rflct_arg_t *rflct_get_in_args(opcode opc, int sig) { - const rflct_arg_t *args = GET_ARGS(opc, sig); - int i; + const rflct_arg_t *args = GET_ARGS(opc, sig); + int i; - for(i = 0; args[i].name != NULL; i++); - return &args[i + 1]; + for(i = 0; args[i].name != NULL; i++); + return &args[i + 1]; } const rflct_arg_t *rflct_get_out_args(opcode opc, int sig) { - return GET_ARGS(opc, sig); + return GET_ARGS(opc, sig); } int rflct_signature_match(ir_node *irn, int sig) { - opcode op = get_irn_opcode(irn); - const rflct_arg_t *args = rflct_get_in_args(op, sig); - int dst = 0; - int i, j; + opcode op = get_irn_opcode(irn); + const rflct_arg_t *args = rflct_get_in_args(op, sig); + int dst = 0; + int i, j; - for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i]) - && j < get_irn_arity(irn); j++) { + for(i = 0, j = -1; RFLCT_ARG_VALID(&args[i]) + && j < get_irn_arity(irn); j++) { - ir_node *child = get_irn_n(irn, j); - const rflct_arg_t *arg = &args[i]; - rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child)); + ir_node *child = get_irn_n(irn, j); + const rflct_arg_t *arg = &args[i]; + rflct_mode_class_t mc = rflct_get_mode_class(get_irn_mode(child)); - if(arg->accepted_modes & mc) - dst += dist(arg->accepted_modes, mc); - else - return INT_MAX; + if(arg->accepted_modes & mc) + dst += dist(arg->accepted_modes, mc); + else + return INT_MAX; - if(!arg->is_variadic) - i++; - } + if(!arg->is_variadic) + i++; + } - return dst; + return dst; } int rflct_get_signature(ir_node *irn) { - const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn)); - int min_dist = INT_MAX; - int min_sig = INT_MAX; - int i; - - for(i = 0; i < opc->sig_count; i++) { - int dist = rflct_signature_match(irn, i); - if(dist < min_dist) { - min_dist = dist; - min_sig = i; - } - } - - return min_sig; + const rflct_opcode_t *opc = GET_OPCODE(get_irn_opcode(irn)); + int min_dist = INT_MAX; + int min_sig = INT_MAX; + int i; + + for(i = 0; i < opc->sig_count; i++) { + int dist = rflct_signature_match(irn, i); + if(dist < min_dist) { + min_dist = dist; + min_sig = i; + } + } + + return min_sig; } static const char *rflct_mode_class_atomic_name(rflct_mode_class_t mc) { #define XXX(_mc) case RFLCT_MC(_mc): return #_mc - switch(mc) { - XXX(None); - XXX(Mem); - XXX(Bool); - XXX(IntS); - XXX(IntU); - XXX(Float); - XXX(Ref); - XXX(Char); - XXX(X); - XXX(BB); - XXX(Int); - XXX(Intb); - XXX(Num); - XXX(NumP); - XXX(Data); - XXX(Datab); - XXX(DataM); - XXX(DataMX); - XXX(Lh); - default: - return ""; - } + switch(mc) { + XXX(None); + XXX(Mem); + XXX(Bool); + XXX(IntS); + XXX(IntU); + XXX(Float); + XXX(Ref); + XXX(Char); + XXX(X); + XXX(BB); + XXX(Int); + XXX(Intb); + XXX(Num); + XXX(NumP); + XXX(Data); + XXX(Datab); + XXX(DataM); + XXX(DataMX); + XXX(Lh); + default: + return ""; + } #undef XXX } static void rflct_mode_class_comb_name_obst(struct obstack *obst, - rflct_mode_class_t mc) { - const char *res = rflct_mode_class_atomic_name(mc); - - if(strlen(res) == 0) { - const char *prefix = ""; - int mask; - - obstack_1grow(obst, '{'); - for(mask = 1; mask != 0; mask <<= 1) { - if(mask & mc) { - const char *s = rflct_mode_class_atomic_name(mask); - obstack_grow_str(obst, s); - obstack_grow_str(obst, prefix); - prefix = "|"; - } - } - obstack_1grow(obst, '}'); - - } else - obstack_grow(obst, res, strlen(res)); + rflct_mode_class_t mc) { + const char *res = rflct_mode_class_atomic_name(mc); + + if(strlen(res) == 0) { + const char *prefix = ""; + int mask; + + obstack_1grow(obst, '{'); + for(mask = 1; mask != 0; mask <<= 1) { + if(mask & mc) { + const char *s = rflct_mode_class_atomic_name(mask); + obstack_grow_str(obst, s); + obstack_grow_str(obst, prefix); + prefix = "|"; + } + } + obstack_1grow(obst, '}'); + + } else + obstack_grow(obst, res, strlen(res)); } char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc) { - struct obstack obst; - const char *res; + struct obstack obst; + const char *res; - obstack_init(&obst); + obstack_init(&obst); - rflct_mode_class_comb_name_obst(&obst, mc); - obstack_1grow(&obst, 0); - res = obstack_finish(&obst); + rflct_mode_class_comb_name_obst(&obst, mc); + obstack_1grow(&obst, 0); + res = obstack_finish(&obst); - strncpy(str, res, n); + strncpy(str, res, n); - obstack_free(&obst, NULL); + obstack_free(&obst, NULL); - return str; + return str; } static void rflct_obstack_grow_args(struct obstack *obst, - const rflct_arg_t *args) { - const rflct_arg_t *arg; - const char *prefix = ""; - - for(arg = args; RFLCT_ARG_VALID(arg); arg++) { - obstack_grow_str(obst, prefix); - obstack_grow_str(obst, arg->name); - if(arg->is_variadic) - obstack_1grow(obst, '*'); - obstack_1grow(obst, ':'); - rflct_mode_class_comb_name_obst(obst, arg->accepted_modes); - prefix = ", "; - } + const rflct_arg_t *args) { + const rflct_arg_t *arg; + const char *prefix = ""; + + for(arg = args; RFLCT_ARG_VALID(arg); arg++) { + obstack_grow_str(obst, prefix); + obstack_grow_str(obst, arg->name); + if(arg->is_variadic) + obstack_1grow(obst, '*'); + obstack_1grow(obst, ':'); + rflct_mode_class_comb_name_obst(obst, arg->accepted_modes); + prefix = ", "; + } } char *rflct_to_string(char *buf, int n, opcode opc, int sig) { - struct obstack obst; - char *s; - const rflct_opcode_t *opcode = GET_OPCODE(opc); + struct obstack obst; + char *s; + const rflct_opcode_t *opcode = GET_OPCODE(opc); - obstack_init(&obst); + obstack_init(&obst); - obstack_1grow(&obst, '('); - rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig)); + obstack_1grow(&obst, '('); + rflct_obstack_grow_args(&obst, rflct_get_out_args(opc, sig)); - obstack_grow_str(&obst, ") = "); - obstack_grow_str(&obst, opcode->name); - obstack_1grow(&obst, '('); + obstack_grow_str(&obst, ") = "); + obstack_grow_str(&obst, opcode->name); + obstack_1grow(&obst, '('); - rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig)); + rflct_obstack_grow_args(&obst, rflct_get_in_args(opc, sig)); - obstack_1grow(&obst, ')'); - obstack_1grow(&obst, 0); - s = obstack_finish(&obst); - strncpy(buf, s, n); - obstack_free(&obst, NULL); + obstack_1grow(&obst, ')'); + obstack_1grow(&obst, 0); + s = obstack_finish(&obst); + strncpy(buf, s, n); + obstack_free(&obst, NULL); - return buf; + return buf; } #define ARG(name,modes) \ - _ARG(name, modes, false, -1) +_ARG(name, modes, false, -1) #define ARG_SAME(name,modes,mode_same) \ - _ARG(name, modes, false, mode_same) +_ARG(name, modes, false, mode_same) #define VARG(name,modes) \ - _ARG(name, modes, true, 0) +_ARG(name, modes, true, 0) #define VARG_SAME(name,modes) \ - _ARG(name, modes, true, 1) +_ARG(name, modes, true, 1) #define MARK \ - _ARG(NULL, None, false, -1) +_ARG(NULL, None, false, -1) + +#define FINISH \ +_ARG(NULL, None, false, 0) #define BLOCK ARG("Block", BB) -static void init_ops(void) { + static void init_ops(void) { - int curr_sig; - rflct_opcode_t *opcode; + int curr_sig; + rflct_opcode_t *opcode; - obstack_init(&obst); + obstack_init(&obst); + + assure_opcode_capacity(iro_MaxOpcode); #define BEGIN_OP(op) \ - curr_sig = 0; \ - opcode = obstack_alloc(&obst, sizeof(*opcode)); \ - opcode->opc = iro_ ## op; \ - opcode->name = #op; \ - opcodes[opcode->opc] = opcode; + curr_sig = 0; \ + opcode = obstack_alloc(&obst, sizeof(*opcode)); \ + opcode->opc = iro_ ## op; \ + opcode->name = #op; \ + opcodes[opcode->opc] = opcode; #define BEGIN_ARGS #define _ARG(_name,_modes,_variadic,_mode_equals) \ - { \ - rflct_arg_t args; \ - args.name = _name; \ - args.accepted_modes = RFLCT_MC(_modes); \ - args.is_variadic = _variadic; \ - args.mode_equals = _mode_equals; \ - obstack_grow(&obst, &args, sizeof(args)); \ - } + { \ + rflct_arg_t args; \ + args.name = _name; \ + args.accepted_modes = RFLCT_MC(_modes); \ + args.is_variadic = _variadic; \ + args.mode_equals = _mode_equals; \ + obstack_grow(&obst, &args, sizeof(args)); \ + } #define END_ARGS \ - { \ - _ARG(NULL, None, false, 0) \ - assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \ - opcode->sigs[curr_sig++] = obstack_finish(&obst); \ - opcode->sig_count = curr_sig; \ - } + { \ + FINISH; \ + assert(curr_sig < MAX_SIG_COUNT && "Mind the maximum number of signatures"); \ + opcode->sigs[curr_sig++] = obstack_finish(&obst); \ + opcode->sig_count = curr_sig; \ + } #define END_OP @@ -357,11 +384,90 @@ static void init_ops(void) { #undef END_ARGS #undef BEGIN_OP #undef END_OP + } + +#undef _ARG +#define _ARG(_name,_modes,_var,_me) \ +arg->name = _name; \ + arg->accepted_modes = RFLCT_MC(_modes); \ + arg->is_variadic = _var; \ + arg->mode_equals = _me; + +void rflct_new_opcode(opcode opc, const char *name, bool commutative) +{ + rflct_opcode_t *ropc = obstack_alloc(&obst, sizeof(*ropc)); + + ropc->opc = opc; + ropc->name = name; + ropc->sig_count = 0; + memset(ropc->sigs, 0, sizeof(ropc->sigs)); + + assure_opcode_capacity(opc); + opcodes[opc] = ropc; } +bool rflct_opcode_add_signature(opcode opc, rflct_sig_t *sig) +{ + const rflct_arg_t *args = sig->args; + rflct_opcode_t *op = opcodes[opc]; + int i; + + assert(op && "Illegal opcode"); + + for(i = 0; i < MAX_SIG_COUNT && op->sigs[i] != NULL; i++); + + if(i >= MAX_SIG_COUNT) + return false; + + op->sigs[op->sig_count++] = args; + free(sig); + return true; +} + + +rflct_sig_t *rflct_signature_allocate(int defs, int uses) +{ + rflct_sig_t *sig = malloc(sizeof(*sig)); + + rflct_arg_t *args = + obstack_alloc(&obst, sizeof(*args) * (defs + uses + 2)); + + rflct_arg_t *arg = args + defs; + MARK; + + arg = args + defs + uses + 1; + FINISH; + + sig->defs = defs; + sig->uses = uses; + sig->args = args; + + return sig; +} + +int rflct_signature_get_index(const rflct_sig_t *sig, bool is_use, int num) +{ + return is_use ? num + sig->defs + 1 : num; +} + +#undef _ARG +#define _ARG(_name,_modes,_var,_me) \ +arg->name = _name; \ + arg->accepted_modes = _modes; \ + arg->is_variadic = _var; \ + arg->mode_equals = _me; + +int rflct_signature_set_arg(rflct_sig_t *sig, bool is_use, int num, + const char *name, rflct_mode_class_t mc, bool is_variadic, int mode_equals) +{ + int index = rflct_signature_get_index(sig, is_use, num); + rflct_arg_t *arg = sig->args + index; + _ARG(name, mc, is_variadic, mode_equals); + return index; +} void init_rflct(void) { - init_ops(); + init_ops(); } diff --git a/ir/ir/irreflect.h b/ir/ir/irreflect.h index 14167712c..a7335f8e4 100644 --- a/ir/ir/irreflect.h +++ b/ir/ir/irreflect.h @@ -44,7 +44,7 @@ typedef enum { } rflct_mode_class_t; -typedef struct { +typedef struct _rflct_arg_t { const char *name; /**< The name of the argument (just a description). */ bool is_variadic; /**< True, if this argument can have multiple parameters. */ @@ -62,6 +62,13 @@ typedef struct { must be the same. If false, they can differ. */ } rflct_arg_t; +typedef struct _rflct_sig_t { + int defs; /**< The number of defined arguments in the signature. */ + int uses; /**< The number of used arguments in the signature. */ + + rflct_arg_t *args; /**< The arguments array. */ +} rflct_sig_t; + #define RFLCT_ARG_IS_A(arg,modes) (((arg)->accepted_modes & modes) != 0) #define RFLCT_ARG_VALID(arg) ((arg)->name != NULL) #define RFLCT_SIG_VALID(sig) ((sig) != INT_MAX) @@ -147,4 +154,62 @@ char *rflct_to_string(char *buf, int n, opcode opc, int sig); */ char *rflct_mode_class_name(char *str, int n, rflct_mode_class_t mc); +/** + * Create a new opcode. + * @param opc The Firm opcode. + * @param name A name. + * @param commutative True, if the opcode is commuatative. + */ +void rflct_new_opcode(opcode opc, const char *name, bool commutative); + +/** + * Add a signature to the opcode. + * @param opc The opcode. + * @param args The signature. + * @return true, if the signature was added sucessfully, false if no + * more signatures can be added to the opcode. + */ +bool rflct_opcode_add_signature(opcode opc, rflct_sig_t *sig); + +/** + * Allocate a new signature. + * @param defs Number of def arguments. + * @param uses Number of use arguments. + * @return An allocated signature. + */ +rflct_sig_t *rflct_signature_allocate(int defs, int uses); + +/** + * Set an argument in a signature. + * @param sig The signature. + * @param is_use true, if the argument is a use, else it is considered a + * def. + * @param num The index of the argument. + * @param name The name of the argument. + * @param mc The mode class of the argument. + * @param is_variadic true, if the argument is variadic. + * @param mode_equals This variable has following meaning. If the + * argument is variadic, a 1 indicates that all operands binding to this + * argument must have the same mode. A 0 indicates, that their mode must + * be of the specified mode class but can differ. If the argument is non + * variadic, a positive number indicates, that the mode of the operand + * binding to this argument must be the same as the one binding to + * argument indexed by mode_equals. If the mode should not be dependent + * to another mode, set -1 here. + * @return The index of the argument. Only use this index in mode_equals + * parameters of other arguments. + */ +int rflct_signature_set_arg(rflct_sig_t *sig, bool is_use, int num, + const char *name, rflct_mode_class_t mc, bool is_variadic, int mode_equals); + +/** + * Get the arguments array index for an argument. + * @param sig The signature. + * @param is_use True, if the argument indicates a use or def argument. + * @param num The number of the argument. + * @return The index into the arguments array. + */ +int rflct_signature_get_index(const rflct_sig_t *sig, bool is_use, int num); + + #endif -- 2.20.1