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 *
#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"
{ "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]))
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)
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;
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)
{
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
+};