backend: created a (not so nice) macro to iterate over all values defined by an instr...
[libfirm] / ir / be / bearch.h
index b673fcc..5207c79 100644 (file)
@@ -43,7 +43,7 @@
 typedef enum arch_register_class_flags_t {
        arch_register_class_flag_none      = 0,
        /** don't do automatic register allocation for this class */
-       arch_register_class_flag_manual_ra = 1U << 0,
+       arch_register_class_flag_manual_ra = 1U << 0,
        /** the register models an abstract state (example: fpu rounding mode) */
        arch_register_class_flag_state     = 1U << 1
 } arch_register_class_flags_t;
@@ -75,7 +75,7 @@ typedef enum arch_register_type_t {
  */
 typedef enum arch_register_req_type_t {
        /** No register requirement. */
-       arch_register_req_type_none              = 0,
+       arch_register_req_type_none              = 0,
        /** All registers in the class are allowed. */
        arch_register_req_type_normal            = 1U << 0,
        /** Only a real subset of the class is allowed. */
@@ -84,12 +84,14 @@ typedef enum arch_register_req_type_t {
        arch_register_req_type_should_be_same    = 1U << 2,
        /** The register must be unequal from some other at the node. */
        arch_register_req_type_must_be_different = 1U << 3,
+       /** The registernumber should be aligned (in case of multiregister values)*/
+       arch_register_req_type_aligned           = 1U << 4,
        /** ignore while allocating registers */
-       arch_register_req_type_ignore            = 1U << 4,
+       arch_register_req_type_ignore            = 1U << 5,
        /** the output produces a new value for the stack pointer
         * (this is not really a constraint but a marker to guide the stackpointer
         * rewiring logic) */
-       arch_register_req_type_produces_sp       = 1U << 5,
+       arch_register_req_type_produces_sp       = 1U << 6,
 } arch_register_req_type_t;
 
 extern const arch_register_req_t *arch_no_register_req;
@@ -119,7 +121,6 @@ typedef enum arch_irn_class_t {
 void arch_set_frame_offset(ir_node *irn, int bias);
 
 ir_entity *arch_get_frame_entity(const ir_node *irn);
-void       arch_set_frame_entity(ir_node *irn, ir_entity *ent);
 int        arch_get_sp_bias(ir_node *irn);
 
 int             arch_get_op_estimated_cost(const ir_node *irn);
@@ -338,6 +339,8 @@ struct arch_register_req_t {
        unsigned other_different;           /**< Bitmask of ins which shall use a
                                                 different register
                                                 (must_be_different) */
+       unsigned char width;                /**< specifies how many sequential
+                                                registers are required */
 };
 
 static inline int reg_reqs_equal(const arch_register_req_t *req1,
@@ -381,7 +384,7 @@ struct arch_inverse_t {
 struct arch_irn_ops_t {
 
        /**
-        * Get the register requirements for a given operand.
+        * Get the register requirements for a given operand.
         * @param irn The node.
         * @param pos The operand's position
         * @return    The register requirements for the selected operand.
@@ -405,13 +408,6 @@ struct arch_irn_ops_t {
         */
        ir_entity *(*get_frame_entity)(const ir_node *irn);
 
-       /**
-        * Set the entity on the stack frame this node depends on.
-        * @param irn  The node in question.
-        * @param ent  The entity to set
-        */
-       void (*set_frame_entity)(ir_node *irn, ir_entity *ent);
-
        /**
         * Set the offset of a node carrying an entity on the stack frame.
         * @param irn  The node.
@@ -840,4 +836,34 @@ static inline void arch_set_out_register_req(ir_node *node, int pos,
        info->out_infos[pos].req = req;
 }
 
+/**
+ * Iterate over all values defined by an instruction.
+ * Only looks at values in a certain register class where the requirements
+ * are not marked as ignore.
+ * Executes @p code for each definition.
+ */
+#define be_foreach_definition(node, cls, value, code)                      \
+       do {                                                                   \
+       if (get_irn_mode(node) == mode_T) {                                    \
+               const ir_edge_t *edge_;                                            \
+               foreach_out_edge(node, edge_) {                                    \
+                       const arch_register_req_t *req_;                               \
+                       value = get_edge_src_irn(edge_);                               \
+                       req_  = arch_get_register_req_out(value);                      \
+                       if (req_->cls != cls)                                          \
+                               continue;                                                  \
+                       if (req_->type & arch_register_req_type_ignore)                \
+                               continue;                                                  \
+                       code                                                           \
+               }                                                                  \
+       } else {                                                               \
+               const arch_register_req_t *req_ = arch_get_register_req_out(node); \
+               value = node;                                                      \
+               if (req_->cls == cls                                               \
+                               && !(req_->type & arch_register_req_type_ignore)) {        \
+                       code                                                           \
+               }                                                                  \
+       }                                                                      \
+       } while (0)
+
 #endif