Added call serialization for firm arch
authorSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Wed, 10 Aug 2005 11:08:23 +0000 (11:08 +0000)
committerSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Wed, 10 Aug 2005 11:08:23 +0000 (11:08 +0000)
ir/be/bearch.c
ir/be/bearch.h
ir/be/bearch_firm.c

index bd53bd8..26adb97 100644 (file)
@@ -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 *
index 09397c8..122ce48 100644 (file)
@@ -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
index 5ddab05..7ee7165 100644 (file)
@@ -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
+};