From: Sebastian Hack Date: Wed, 10 Aug 2005 11:08:23 +0000 (+0000) Subject: Added call serialization for firm arch X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ad177bc3490f7f1da426d681aaeadc2f254b0acf;p=libfirm Added call serialization for firm arch --- diff --git a/ir/be/bearch.c b/ir/be/bearch.c index bd53bd8c9..26adb9716 100644 --- a/ir/be/bearch.c +++ b/ir/be/bearch.c @@ -117,12 +117,25 @@ int arch_is_register_operand(const arch_env_t *env, int arch_reg_is_allocatable(const arch_env_t *env, const ir_node *irn, int pos, const arch_register_t *reg) { - const arch_register_class_t *cls = arch_register_get_class(reg); - int n_regs = arch_register_class_n_regs(cls); - bitset_t *bs = bitset_alloca(n_regs); - - arch_get_allocatable_regs(env, irn, pos, cls, bs); - return bitset_is_set(bs, arch_register_get_index(reg)); + int res = 0; + arch_register_req_t req; + + arch_get_register_req(env, &req, irn, pos); + switch(req.type) { + case arch_register_req_type_normal: + res = req.cls == reg->reg_class; + break; + case arch_register_req_type_limited: + { + bitset_t *bs = bitset_alloca(req.cls->n_regs); + req.data.limited(irn, pos, bs); + res = bitset_is_set(bs, arch_register_get_index(reg)); + } + default: + res = 0; + } + + return res; } const arch_register_class_t * diff --git a/ir/be/bearch.h b/ir/be/bearch.h index 09397c8ce..122ce485f 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -196,6 +196,7 @@ typedef enum _arch_irn_class_t { arch_irn_class_branch } arch_irn_class_t; + /* * Some words about positions and indices: * @@ -304,6 +305,7 @@ struct _arch_irn_ops_t { */ arch_irn_class_t (*classify)(const arch_irn_ops_t *self, const ir_node *irn); + }; /** @@ -440,6 +442,13 @@ struct _arch_isa_if_t { */ const arch_register_class_t *(*get_reg_class)(int i); + /** + * Prepare a graph. + * This function is called each time, the backend starts running over + * a graph. + * @param irg The graph. + */ + void (*prepare_graph)(ir_graph *irg); }; #define ARCH_MAX_HANDLERS 8 diff --git a/ir/be/bearch_firm.c b/ir/be/bearch_firm.c index 5ddab0567..7ee7165b1 100644 --- a/ir/be/bearch_firm.c +++ b/ir/be/bearch_firm.c @@ -9,7 +9,15 @@ #include "bitset.h" #include "obst.h" +#include "irmode_t.h" +#include "irnode_t.h" +#include "irgmod.h" +#include "ircons_t.h" +#include "irgwalk.h" +#include "type.h" + #include "bearch.h" +#include "beutil.h" #include "irreflect.h" @@ -21,6 +29,19 @@ static arch_register_class_t reg_classes[] = { { "datab", N_REGS, datab_regs }, }; +static ir_op *op_push_end; +static ir_op *op_push; +static ir_op *op_imm; +static type *push_type; + +typedef struct { + enum { imm_Const, imm_SymConst } tp; + union { + tarval *tv; + entity *ent; + } data; +} imm_attr_t; + #define N_CLASSES \ (sizeof(reg_classes) / sizeof(reg_classes[0])) @@ -57,6 +78,29 @@ static void firm_init(void) reg->type = 0; } } + + /* + * Create some opcodes and types to let firm look a little + * bit more like real machines. + */ + if(!op_push_end) { + op_push_end = new_ir_op(get_next_ir_opcode(), "PushEnd", + op_pin_state_pinned, 0, oparity_unary, 0, 0); + } + + if(!op_push) { + op_push = new_ir_op(get_next_ir_opcode(), "Push", + op_pin_state_pinned, 0, oparity_binary, 0, 0); + } + + if(!op_imm) { + op_imm = new_ir_op(get_next_ir_opcode(), "Imm", + op_pin_state_pinned, 0, oparity_zero, 0, sizeof(imm_attr_t)); + } + + if(!push_type) + push_type = new_type_pointer(new_id_from_str("push_ptr"), get_glob_type()); + } static int firm_get_n_reg_class(void) @@ -88,7 +132,7 @@ static const arch_register_req_t * firm_get_irn_reg_req(const arch_irn_ops_t *self, arch_register_req_t *req, const ir_node *irn, int pos) { - if(mode_is_datab(get_irn_mode(irn))) + if(is_firm_be_mode(get_irn_mode(irn))) memcpy(req, &firm_std_reg_req, sizeof(*req)); else req = NULL; @@ -171,12 +215,6 @@ static const arch_irn_ops_t irn_ops = { firm_classify }; -const arch_isa_if_t firm_isa = { - firm_init, - firm_get_n_reg_class, - firm_get_reg_class -}; - static const arch_irn_ops_t *firm_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) { @@ -186,3 +224,118 @@ static const arch_irn_ops_t *firm_get_irn_ops(const arch_irn_handler_t *self, const arch_irn_handler_t firm_irn_handler = { firm_get_irn_ops, }; + +static ir_node *new_PushEnd(ir_graph *irg, ir_node *bl, ir_node *arg) +{ + ir_node *ins[1]; + ins[0] = arg; + return new_ir_node(NULL, irg, bl, op_push_end, mode_P, 1, ins); +} + +static ir_node *new_Push(ir_graph *irg, ir_node *bl, ir_node *push, ir_node *arg) +{ + ir_node *ins[2]; + ins[0] = push; + ins[1] = arg; + return new_ir_node(NULL, irg, bl, op_push, mode_P, 2, ins); +} + +static ir_node *new_Imm(ir_graph *irg, ir_node *bl, ir_node *cnst) +{ + ir_node *ins[1]; + ir_node *res; + imm_attr_t *attr; + + res = new_ir_node(NULL, irg, bl, op_imm, get_irn_mode(cnst), 0, ins); + attr = (imm_attr_t *) &res->attr; + + if(get_irn_opcode(cnst) == iro_SymConst) { + attr->tp = imm_SymConst; + attr->data.ent = get_SymConst_entity(cnst); + } + + else { + attr->tp = imm_Const; + attr->data.tv = get_Const_tarval(cnst); + } + + return res; +} + +static void prepare_walker(ir_node *irn, void *data) +{ + opcode opc = get_irn_opcode(irn); + + /* A replacement for this node has already been computed. */ + if(get_irn_link(irn)) + return; + + if(opc == iro_Call) { + ir_node *bl = get_nodes_block(irn); + ir_graph *irg = get_irn_irg(bl); + + ir_node *ins[1]; + ir_node *store = get_Call_mem(irn); + ir_node *ptr = get_Call_ptr(irn); + type *ct = get_Call_type(irn); + int np = get_Call_n_params(irn) > 0 ? 1 : 0; + + if(np > 0) { + char buf[128]; + ir_node *nc; + ir_node *push; + int i, n; + type *nt; + + push = new_PushEnd(irg, bl, get_Call_param(irn, 0)); + + for(i = 1, n = get_Call_n_params(irn); i < n; ++i) { + push = new_Push(irg, bl, push, get_Call_param(irn, i)); + } + + snprintf(buf, sizeof(buf), "push_%s", get_type_name(ct)); + + n = get_method_n_ress(ct); + nt = new_type_method(new_id_from_str(buf), 1, n); + for(i = 0; i < n; ++i) + set_method_res_type(nt, i, get_method_res_type(ct, i)); + + set_method_param_type(nt, 0, push_type); + + ins[0] = push; + nc = new_r_Call(irg, bl, store, ptr, 1, ins, nt); + exchange(irn, nc); + set_irn_link(nc, nc); + } + } + +#if 0 + else if(opc == iro_Const || opc == iro_SymConst) { + ir_node *bl = get_nodes_block(irn); + ir_graph *irg = get_irn_irg(bl); + + ir_node *imm = new_Imm(irg, bl, irn); + exchange(irn, imm); + set_irn_link(imm, imm); + } +#endif + +} + +static void clear_link(ir_node *irn, void *data) +{ + set_irn_link(irn, NULL); +} + +static void firm_prepare_graph(ir_graph *irg) +{ + irg_walk_graph(irg, clear_link, NULL, NULL); + irg_walk_graph(irg, NULL, prepare_walker, NULL); +} + +const arch_isa_if_t firm_isa = { + firm_init, + firm_get_n_reg_class, + firm_get_reg_class, + firm_prepare_graph +};