added some getters setters. changed a name. put them in _t.h
[libfirm] / ir / be / bearch.h
index 09397c8..a3b2a25 100644 (file)
@@ -1,9 +1,12 @@
-
 #ifndef _FIRM_BEARCH_H
 #define _FIRM_BEARCH_H
 
 #include "firm_config.h"
 
 #ifndef _FIRM_BEARCH_H
 #define _FIRM_BEARCH_H
 
 #include "firm_config.h"
 
+#ifdef WITH_LIBCORE
+#include <libcore/lc_opts.h>
+#endif
+
 #include "irnode.h"
 #include "irmode.h"
 
 #include "irnode.h"
 #include "irmode.h"
 
 #include "list.h"
 #include "ident.h"
 
 #include "list.h"
 #include "ident.h"
 
-typedef struct _arch_register_class_t   arch_register_class_t;
-typedef struct _arch_register_t         arch_register_t;
-typedef struct _arch_enum_t             arch_enum_t;
-typedef struct _arch_enum_member_t      arch_enum_member_t;
-typedef struct _arch_isa_if_t           arch_isa_if_t;
-typedef struct _arch_env_t              arch_env_t;
-typedef struct _arch_irn_ops_t          arch_irn_ops_t;
-typedef struct _arch_irn_handler_t      arch_irn_handler_t;
+#include "belistsched.h"
+
+typedef struct _arch_register_class_t     arch_register_class_t;
+typedef struct _arch_register_t           arch_register_t;
+typedef struct _arch_enum_t               arch_enum_t;
+typedef struct _arch_enum_member_t        arch_enum_member_t;
+typedef struct _arch_isa_if_t             arch_isa_if_t;
+typedef struct _arch_isa_t                arch_isa_t;
+typedef struct _arch_env_t                arch_env_t;
+typedef struct _arch_irn_ops_t            arch_irn_ops_t;
+typedef struct _arch_irn_handler_t        arch_irn_handler_t;
+typedef struct _arch_code_generator_t     arch_code_generator_t;
+typedef struct _arch_code_generator_if_t  arch_code_generator_if_t;
 
 struct _be_node_factory_t;
 
 typedef enum _arch_register_type_t {
 
 struct _be_node_factory_t;
 
 typedef enum _arch_register_type_t {
-       arch_register_type_none = 0,
+  arch_register_type_none = 0,
   arch_register_type_write_invariant,
   arch_register_type_write_invariant,
-       arch_register_type_caller_saved,    /**< The register must be saved by the caller
-                                        upon a function call. It thus can be overwritten
-                                                                                                                                                                                               in the called function. */
-       arch_register_type_callee_saved,    /**< The register must be saved by the called function,
-                                        it thus survives a function call. */
-       arch_register_type_ignore           /**< Do not consider this register when allocating. */
+  arch_register_type_caller_saved,    /**< The register must be saved by the caller
+                                           upon a function call. It thus can be overwritten
+                                           in the called function. */
+  arch_register_type_callee_saved,    /**< The register must be saved by the called function,
+                                           it thus survives a function call. */
+  arch_register_type_ignore           /**< Do not consider this register when allocating. */
 } arch_register_type_t;
 
 /**
 } arch_register_type_t;
 
 /**
@@ -41,9 +49,9 @@ typedef enum _arch_register_type_t {
  */
 struct _arch_register_t {
   const char *name;                         /**< The name of the register. */
  */
 struct _arch_register_t {
   const char *name;                         /**< The name of the register. */
-       const arch_register_class_t *reg_class;   /**< The class the register belongs to. */
-       int index;                                                                                                                              /**< The index of the register in the class. */
-       arch_register_type_t type;                /**< The type of the register. */
+  const arch_register_class_t *reg_class;   /**< The class the register belongs to. */
+  int index;                                /**< The index of the register in the class. */
+  arch_register_type_t type;                /**< The type of the register. */
   void *data;                               /**< Custom data. */
 };
 
   void *data;                               /**< Custom data. */
 };
 
@@ -67,9 +75,9 @@ static INLINE int _arch_register_get_index(const arch_register_t *reg)
  * Like general purpose or floating point.
  */
 struct _arch_register_class_t {
  * Like general purpose or floating point.
  */
 struct _arch_register_class_t {
-  const char *name;               /**< The name of the register. */
-       int n_regs;                                                                   /**< Number of registers in this class. */
-       const arch_register_t *regs;    /**< The array of registers. */
+  const char *name;               /**< The name of the register class. */
+  int n_regs;                     /**< Number of registers in this class. */
+  const arch_register_t *regs;    /**< The array of registers. */
 };
 
 #define arch_register_class_n_regs(cls) ((cls)->n_regs)
 };
 
 #define arch_register_class_n_regs(cls) ((cls)->n_regs)
@@ -85,8 +93,8 @@ extern int arch_register_class_put(const arch_register_class_t *cls, bitset_t *b
 static INLINE const arch_register_t *
 _arch_register_for_index(const arch_register_class_t *cls, int idx)
 {
 static INLINE const arch_register_t *
 _arch_register_for_index(const arch_register_class_t *cls, int idx)
 {
-       assert(0 <= idx && idx < cls->n_regs);
-       return &cls->regs[idx];
+  assert(0 <= idx && idx < cls->n_regs);
+  return &cls->regs[idx];
 }
 
 #define arch_register_for_index(cls, idx) \
 }
 
 #define arch_register_for_index(cls, idx) \
@@ -104,14 +112,14 @@ _arch_register_for_index(const arch_register_class_t *cls, int idx)
  */
 struct _arch_immediate_t {
   const char *name;         /**< The name of the immediate. */
  */
 struct _arch_immediate_t {
   const char *name;         /**< The name of the immediate. */
-       ir_mode *mode;                                          /**< The mode of the immediate. */
+  ir_mode *mode;            /**< The mode of the immediate. */
 };
 
 /**
  * The member of an enum.
  */
 struct _arch_enum_member_t {
 };
 
 /**
  * The member of an enum.
  */
 struct _arch_enum_member_t {
-       arch_enum_t *enm;                                       /**< The enum, this member belongs to. */
+  arch_enum_t *enm;         /**< The enum, this member belongs to. */
 };
 
 /**
 };
 
 /**
@@ -122,8 +130,8 @@ struct _arch_enum_member_t {
  * eq, ...) some other special attributes of an instruction.
  */
 struct _arch_enum_t {
  * eq, ...) some other special attributes of an instruction.
  */
 struct _arch_enum_t {
-       int n_members;                                                                          /**< The number of members in this enum. */
-       arch_enum_member_t *members[1];         /**< The array of members. */
+  int n_members;                    /**< The number of members in this enum. */
+  arch_enum_member_t *members[1];   /**< The array of members. */
 };
 
 typedef enum _arch_operand_type_t {
 };
 
 typedef enum _arch_operand_type_t {
@@ -132,29 +140,27 @@ typedef enum _arch_operand_type_t {
   arch_operand_type_register,
   arch_operand_type_immediate,
   arch_operand_type_symconst,
   arch_operand_type_register,
   arch_operand_type_immediate,
   arch_operand_type_symconst,
-       arch_operand_type_last
+  arch_operand_type_last
 } arch_operand_type_t;
 
 /**
  * Different types of register allocation requirements.
  */
 typedef enum _arch_register_req_type_t {
 } arch_operand_type_t;
 
 /**
  * Different types of register allocation requirements.
  */
 typedef enum _arch_register_req_type_t {
-  arch_register_req_type_none = 0,        /** No register requirement. */
+  arch_register_req_type_none = 0,        /**< No register requirement. */
 
 
-  arch_register_req_type_normal = 1,      /** All registers in the class
-                                            are allowed. */
+  arch_register_req_type_normal = 1,      /**< All registers in the class
+                                               are allowed. */
 
 
-  arch_register_req_type_limited = 2,     /** Only a real subset of
-                                            the class is allowed. */
+  arch_register_req_type_limited = 2,     /**< Only a real subset of
+                                               the class is allowed. */
 
 
-  arch_register_req_type_equal = 4,       /** The register must equal
-                                            another one at the node. */
+  arch_register_req_type_should_be_same = 4,       /**< The register should be equal
+                                                        another one at the node. */
 
 
-  arch_register_req_type_unequal = 8,     /** The register must be unequal
-                                            to some other at the node. */
+  arch_register_req_type_should_be_different = 8,  /**< The register must be unequal
+                                                        to some other at the node. */
 
 
-  arch_register_req_type_pair = 16        /** The register is part of a
-                                            register pair. */
 } arch_register_req_type_t;
 
 #define arch_register_req_is_constr(x) \
 } arch_register_req_type_t;
 
 #define arch_register_req_is_constr(x) \
@@ -164,19 +170,19 @@ typedef enum _arch_register_req_type_t {
  * Expresses requirements to register allocation for an operand.
  */
 typedef struct _arch_register_req_t {
  * Expresses requirements to register allocation for an operand.
  */
 typedef struct _arch_register_req_t {
-  arch_register_req_type_t type;          /** The type of the constraint. */
-  const arch_register_class_t *cls;       /** The register class this
-                                            constraint belongs to. */
+  arch_register_req_type_t type;          /**< The type of the constraint. */
+  const arch_register_class_t *cls;       /**< The register class this
+                                               constraint belongs to. */
   union {
     int (*limited)(const ir_node *irn, int pos, bitset_t *bs);
   union {
     int (*limited)(const ir_node *irn, int pos, bitset_t *bs);
-                                          /** In case of the 'limited'
+                                          /**< In case of the 'limited'
                                             constraint, this function
                                             must put all allowable
                                             registers in the bitset and
                                             return the number of registers
                                             in the bitset. */
 
                                             constraint, this function
                                             must put all allowable
                                             registers in the bitset and
                                             return the number of registers
                                             in the bitset. */
 
-    int pos;                             /** In case of the equal constraint,
+    int pos;                             /**< In case of the equal constraint,
                                             this gives the position of the
                                             operand to which the register of
                                             this should be equal to. Same for
                                             this gives the position of the
                                             operand to which the register of
                                             this should be equal to. Same for
@@ -196,60 +202,13 @@ typedef enum _arch_irn_class_t {
   arch_irn_class_branch
 } arch_irn_class_t;
 
   arch_irn_class_branch
 } arch_irn_class_t;
 
-/*
- * Some words about positions and indices:
- *
- * Firm has the policy "One node per value", that's why there are
- * Proj nodes. This view has its advantages, but in a backend
- * setting where we talk about instructions (which can also have
- * multiple results and not a single Tuple value) this is sometimes
- * hard.
- *
- * Each node representing an instruction must provide information
- * about the kind of its operands (where operands mean both input
- * and output operands). Such an operand is addressed with a position
- * which is infact a tuple {in, out} x N. The fact that a position
- * is an input/output operand is encoded in the sign, so input operands
- * go from 0..n-1 and output operands from -1..-m if the
- * instruction has n input and m output operands.
- */
-
-#define _BEARCH_TRANSFORM_INDEX(cmp, index) ((index) cmp 0 ? -((index) + 1) : (index))
-
 /**
 /**
- * Make an in position from an index.
- * @param index The index.
- * @return The position representing the index as an in operand.
+ * Some flags describing a node in more detail.
  */
  */
-#define arch_pos_make_in(index)   _BEARCH_TRANSFORM_INDEX(<, index)
-
-/**
- * Make an out position from an index.
- * @param index The index.
- * @return The position representing the index as an out operand.
- */
-#define arch_pos_make_out(index)  _BEARCH_TRANSFORM_INDEX(>=, index)
-
-/**
- * Check, if a position denotes an input operand.
- * @param pos The position.
- * @return 1, if the position denotes an input operand 0 if not.
- */
-#define arch_pos_is_in(pos)       ((pos) >= 0)
-
-/**
- * Check, if a position denotes an output operand.
- * @param pos The position.
- * @return 1, if the position denotes an output operand 0 if not.
- */
-#define arch_pos_is_out(pos)      (!arch_pos_is_in(pos))
-
-/**
- * Get the index of a position.
- * @param pos The position.
- * @return The index of the position.
- */
-#define arch_pos_get_index(pos)   _BEARCH_TRANSFORM_INDEX(<, pos)
+typedef enum _arch_irn_flags_t {
+  arch_irn_flags_spillable = 1,
+  arch_irn_flags_rematerializable = 2
+} arch_irn_flags_t;
 
 struct _arch_irn_ops_t {
 
 
 struct _arch_irn_ops_t {
 
@@ -257,45 +216,33 @@ struct _arch_irn_ops_t {
    * Get the register requirements for a given operand.
    * @param self The self pointer.
    * @param irn The node.
    * Get the register requirements for a given operand.
    * @param self The self pointer.
    * @param irn The node.
-   * @param pos The operand's position.
+   * @param pos The operand's position
+        *                                              (-1 for the result of the node, 0..n for the input
+        *                                              operands).
    * @return    The register requirements for the selected operand.
    *            The pointer returned is never NULL.
    */
   const arch_register_req_t *(*get_irn_reg_req)(const arch_irn_ops_t *self,
    * @return    The register requirements for the selected operand.
    *            The pointer returned is never NULL.
    */
   const arch_register_req_t *(*get_irn_reg_req)(const arch_irn_ops_t *self,
-      arch_register_req_t *req,
-      const ir_node *irn, int pos);
-
-  /**
-   * Get the number of operands of a node.
-   * @param irn     The node.
-   * @param in_out  Denotes wither input (a number >= 0) or
-   *                output (a number < 0).
-   * @return        The number of operands for either in, or output.
-   */
-  int (*get_n_operands)(const arch_irn_ops_t *self, const ir_node *irn, int in_out);
+      arch_register_req_t *req, const ir_node *irn, int pos);
 
   /**
    * Set the register for an output operand.
    * @param irn The node.
 
   /**
    * Set the register for an output operand.
    * @param irn The node.
-   * @param pos The position of the output operand.
    * @param reg The register allocated to that operand.
    * @note      If the operand is not a register operand,
    *            the call is ignored.
    */
    * @param reg The register allocated to that operand.
    * @note      If the operand is not a register operand,
    *            the call is ignored.
    */
-  void (*set_irn_reg)(const arch_irn_ops_t *self, ir_node *irn,
-      int idx, const arch_register_t *reg);
+  void (*set_irn_reg)(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg);
 
   /**
    * Get the register allocated for an output operand.
    * @param irn The node.
 
   /**
    * Get the register allocated for an output operand.
    * @param irn The node.
-   * @param pos The index of the output operand.
    * @return    The register allocated at that operand. NULL, if
    *            the operand was no register operand or
    *            @c arch_register_invalid, if no register has yet been
    *            allocated for this node.
    */
    * @return    The register allocated at that operand. NULL, if
    *            the operand was no register operand or
    *            @c arch_register_invalid, if no register has yet been
    *            allocated for this node.
    */
-  const arch_register_t *(*get_irn_reg)(const arch_irn_ops_t *self,
-      const ir_node *irn, int idx);
+  const arch_register_t *(*get_irn_reg)(const arch_irn_ops_t *self, const ir_node *irn);
 
   /**
    * Classify the node.
 
   /**
    * Classify the node.
@@ -304,6 +251,14 @@ struct _arch_irn_ops_t {
    */
   arch_irn_class_t (*classify)(const arch_irn_ops_t *self, const ir_node *irn);
 
    */
   arch_irn_class_t (*classify)(const arch_irn_ops_t *self, const ir_node *irn);
 
+  /**
+   * Get the flags of a node.
+   * @param self The irn ops themselves.
+   * @param irn The node.
+   * @return A set of flags.
+   */
+  arch_irn_flags_t (*get_flags)(const arch_irn_ops_t *self, const ir_node *irn);
+
 };
 
 /**
 };
 
 /**
@@ -372,13 +327,12 @@ arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos);
 
 /**
  * Get the register allocated at a certain output operand of a node.
 
 /**
  * Get the register allocated at a certain output operand of a node.
- * @param env The arch nvironment.
+ * @param env The arch environment.
  * @param irn The node.
  * @param irn The node.
- * @param idx The index of the output operand.
  * @return    The register allocated for this operand
  */
 extern const arch_register_t *
  * @return    The register allocated for this operand
  */
 extern const arch_register_t *
-arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx);
+arch_get_irn_register(const arch_env_t *env, const ir_node *irn);
 
 /**
  * Set the register for a certain output operand.
 
 /**
  * Set the register for a certain output operand.
@@ -387,8 +341,8 @@ arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx);
  * @param idx The index of the output operand.
  * @param reg The register.
  */
  * @param idx The index of the output operand.
  * @param reg The register.
  */
-extern void arch_set_irn_register(const arch_env_t *env,
-    ir_node *irn, int idx, const arch_register_t *reg);
+extern void arch_set_irn_register(const arch_env_t *env, ir_node *irn,
+               const arch_register_t *reg);
 
 /**
  * Classify a node.
 
 /**
  * Classify a node.
@@ -398,6 +352,14 @@ extern void arch_set_irn_register(const arch_env_t *env,
  */
 extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn);
 
  */
 extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn);
 
+/**
+ * Get the flags of a node.
+ * @param env The architecture environment.
+ * @param irn The node.
+ * @return The flags.
+ */
+extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn);
+
 #define arch_irn_has_reg_class(env, irn, pos, cls) \
   ((cls) == arch_get_irn_reg_class(env, irn, pos))
 
 #define arch_irn_has_reg_class(env, irn, pos, cls) \
   ((cls) == arch_get_irn_reg_class(env, irn, pos))
 
@@ -417,31 +379,129 @@ struct _arch_irn_handler_t {
 
 };
 
 
 };
 
+/**
+ * The code generator.
+ */
+struct _arch_code_generator_if_t {
+
+
+       /**
+        * Initialize the code generator.
+        * @param file The file to dump to.
+        * @param irg  The function to generate code for.
+        * @param env  The architecture environment.
+        * @return     A newly created code generator.
+        */
+       void *(*init)(FILE *file, ir_graph *irg, const arch_env_t *env);
+
+       /**
+        * Called, when the graph is being normalized.
+        */
+       void (*prepare_graph)(void *self);
+
+       /**
+        * Called before scheduling.
+        */
+       void (*before_sched)(void *self);
+
+       /**
+        * Called before register allocation.
+        */
+       void (*before_ra)(void *self);
+
+       /**
+        * Called after everything happened.
+        * The code generator must also be de-allocated here.
+        */
+       void (*done)(void *self);
+
+};
+
+#define _arch_cg_call(cg, func) \
+do { \
+       if((cg)->impl->func) \
+               (cg)->impl->func(cg); \
+} while(0)
+
+#define arch_code_generator_prepare_graph(cg)   _arch_cg_call(cg, prepare_graph)
+#define arch_code_generator_before_sched(cg)    _arch_cg_call(cg, before_sched)
+#define arch_code_generator_before_ra(cg)       _arch_cg_call(cg, before_ra)
+#define arch_code_generator_done(cg)            _arch_cg_call(cg, done)
+
+/**
+ * Code generator base class.
+ */
+struct _arch_code_generator_t {
+       const arch_code_generator_if_t *impl;
+};
+
+/**
+ * ISA base class.
+ */
+struct _arch_isa_t {
+       const arch_isa_if_t *impl;
+};
+
 /**
  * Architecture interface.
  */
 struct _arch_isa_if_t {
 
 /**
  * Architecture interface.
  */
 struct _arch_isa_if_t {
 
+#ifdef WITH_LIBCORE
+  void (*register_options)(lc_opt_entry_t *grp);
+#endif
+
   /**
    * Initialize the isa interface.
    */
   /**
    * Initialize the isa interface.
    */
-  void (*init)(void);
+  void *(*init)(void);
+
+  /**
+   * Free the isa instance.
+   */
+  void (*done)(void *self);
 
   /**
    * Get the the number of register classes in the isa.
    * @return The number of register classes.
    */
 
   /**
    * Get the the number of register classes in the isa.
    * @return The number of register classes.
    */
-  int (*get_n_reg_class)(void);
+  int (*get_n_reg_class)(const void *self);
 
   /**
    * Get the i-th register class.
    * @param i The number of the register class.
    * @return The register class.
    */
 
   /**
    * Get the i-th register class.
    * @param i The number of the register class.
    * @return The register class.
    */
-  const arch_register_class_t *(*get_reg_class)(int i);
+  const arch_register_class_t *(*get_reg_class)(const void *self, int i);
 
 
+  /**
+   * The irn handler for this architecture.
+   * The irn handler is registered by the Firm back end
+   * when the architecture is initialized.
+   * (May be NULL).
+   */
+  const arch_irn_handler_t *(*get_irn_handler)(const void *self);
+
+  /**
+   * Get the code generator interface.
+   * @param self The this pointer.
+   * @return     Some code generator interface.
+   */
+  const arch_code_generator_if_t *(*get_code_generator)(void *self);
+
+  /**
+   * Get the list scheduler to use.
+   * @param self  The isa object.
+   * @return      The list scheduler selector.
+   */
+  const list_sched_selector_t *(*get_list_sched_selector)(const void *self);
 };
 
 };
 
+#define arch_isa_get_n_reg_class(isa)           ((isa)->impl->get_n_reg_class(isa))
+#define arch_isa_get_reg_class(isa,i)           ((isa)->impl->get_reg_class(isa, i))
+#define arch_isa_get_irn_handler(isa)           ((isa)->impl->get_irn_handler(isa))
+#define arch_isa_make_code_generator(isa,irg)   ((isa)->impl->make_code_generator(isa, irg))
+
 #define ARCH_MAX_HANDLERS         8
 
 /**
 #define ARCH_MAX_HANDLERS         8
 
 /**
@@ -450,7 +510,7 @@ struct _arch_isa_if_t {
  */
 struct _arch_env_t {
   const struct _be_node_factory_t *node_factory;  /**< The node factory for be nodes. */
  */
 struct _arch_env_t {
   const struct _be_node_factory_t *node_factory;  /**< The node factory for be nodes. */
-  const arch_isa_if_t *isa;               /**< The isa about which everything is. */
+  arch_isa_t *isa;                                /**< The isa about which everything is. */
 
   arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /**< The handlers are organized as
                                                            a stack. */
 
   arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /**< The handlers are organized as
                                                            a stack. */