*** empty log message ***
[libfirm] / ir / be / bearch.h
index 9c0e924..9c11bb2 100644 (file)
@@ -10,6 +10,8 @@
 #include <libcore/lc_opts.h>
 #endif
 
+#include "type.h"
+
 #include "irnode.h"
 #include "irmode.h"
 
@@ -21,6 +23,7 @@
 #include "ident.h"
 
 #include "belistsched.h"
+#include "beabi_t.h"
 
 typedef struct _arch_register_class_t     arch_register_class_t;
 typedef struct _arch_register_t           arch_register_t;
@@ -37,12 +40,15 @@ struct _be_node_factory_t;
 
 typedef enum _arch_register_type_t {
   arch_register_type_none = 0,
-  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_save  = 1, /**< 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_save  = 2, /**< The register must be saved by the caller
+                                            upon a function call. It thus can be overwritten
+                                            in the called function. */
+  arch_register_type_ignore = 4,       /**< Do not consider this register when allocating. */
+  arch_register_type_sp = 8,           /**< This register is the stack pointer of the architecture. */
+  arch_register_type_bp = 16,          /**< The register is the base pointer of the architecture. */
 } arch_register_type_t;
 
 /**
@@ -87,6 +93,7 @@ static INLINE int _arch_register_get_index(const arch_register_t *reg)
 struct _arch_register_class_t {
   const char *name;               /**< The name of the register class. */
   int n_regs;                     /**< Number of registers in this class. */
+  ir_mode *mode;                  /**< The mode of the register class. */
   const arch_register_t *regs;    /**< The array of registers. */
 };
 
@@ -155,7 +162,7 @@ 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. */
 
-       void (*limited)(const ir_node *irn, int pos, bitset_t *bs);
+       void (*limited)(void *limited_env, bitset_t *bs);
                                           /**< In case of the 'limited'
                                             constraint, this function
                                             must put all allowable
@@ -163,10 +170,13 @@ typedef struct _arch_register_req_t {
                                             return the number of registers
                                             in the bitset. */
 
-       ir_node *other;                                           /**< In case of "should be equal"
-                                                                                   or should be different, this gives
-                                                                                       the node to whose register this
-                                                                                       one's should be the same/different. */
+       void *limited_env;                    /**< This must passed to limited. */
+
+       ir_node *other_same;                      /**< The other which shall have the same reg
+                                                                                   as this one. (for case should_be_same). */
+
+       ir_node *other_different;             /**< The other node from which this one's register
+                                                                                   must be different (case must_be_different). */
 } arch_register_req_t;
 
 /**
@@ -186,9 +196,10 @@ typedef enum _arch_irn_class_t {
  * Some flags describing a node in more detail.
  */
 typedef enum _arch_irn_flags_t {
-  arch_irn_flags_dont_spill       = 1, /**< This must not be spilled. */
-  arch_irn_flags_rematerializable = 2, /**< This should be replicated instead of spilled/reloaded. */
-  arch_irn_flags_ignore           = 4, /**< Do not consider the node during register allocation. */
+       arch_irn_flags_none             = 0, /**< Node flags. */
+       arch_irn_flags_dont_spill       = 1, /**< This must not be spilled. */
+       arch_irn_flags_rematerializable = 2, /**< This should be replicated instead of spilled/reloaded. */
+       arch_irn_flags_ignore           = 4, /**< Do not consider the node during register allocation. */
 } arch_irn_flags_t;
 
 struct _arch_irn_ops_if_t {
@@ -240,6 +251,27 @@ struct _arch_irn_ops_if_t {
    */
   arch_irn_flags_t (*get_flags)(const void *self, const ir_node *irn);
 
+  /**
+   * Check, if a node modifies the stack pointer by a constant.
+   * @param self The this pointer.
+   * @param irn  The node in question.
+   * @return     The (constant) amount by which the stack pointer is modifies
+   *             by this node. Return 0, if irn does not touch the stack pointer.
+   *             <tt>-n</tt> if the node modifies the sp by n against the stack's growing
+   *             direction and <tt>n</tt> if irn modifies the stack by n along the stack's
+   *             growing direction.
+   */
+  int (*modifies_sp)(const void *self, const ir_node *irn);
+
+  /**
+   * Set a bias for the stack pointer.
+   * If the node in question uses the stack pointer for indexing, it must
+   * consider the value of <code>bias</code> additionally.
+   * @param self The this pointer.
+   * @param irn  The node in question.
+   * @param bias The bias.
+   */
+  void (*set_stack_bias)(const void *self, ir_node *irn, int bias);
 };
 
 /**
@@ -281,15 +313,22 @@ extern int arch_is_register_operand(const arch_env_t *env,
  * @param env The environment.
  * @param irn The node.
  * @param pos The postition of the node's operand.
- * @param cls The register class.
  * @param bs  The bitset all allocatable registers shall be put into.
  *            Note, that you can also pass NULL here. If you don't,
  *            make sure, the bitset is as large as the register class
  *            has registers.
  * @return    The amount of registers allocatable for that operand.
  */
-extern int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
-    int pos, const arch_register_class_t *cls, bitset_t *bs);
+extern int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn, int pos, bitset_t *bs);
+
+/**
+ * Put all registers which shall not be ignored by the register
+ * allocator in a bit set.
+ * @param env The arch env.
+ * @param cls The register class to consider.
+ * @param bs  The bit set to put the registers to.
+ */
+extern void arch_put_non_ignore_regs(const arch_env_t *env, const arch_register_class_t *cls, bitset_t *bs);
 
 /**
  * Check, if a register is assignable to an operand of a node.
@@ -348,8 +387,7 @@ extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *
  */
 extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn);
 
-#define arch_irn_is_ignore(env, irn) \
-       (arch_irn_get_flags(env, irn) == arch_irn_flags_ignore)
+#define arch_irn_is_ignore(env, irn) ((arch_irn_get_flags(env, irn) & arch_irn_flags_ignore) != 0)
 
 #define arch_irn_has_reg_class(env, irn, pos, cls) \
   ((cls) == arch_get_irn_reg_class(env, irn, pos))
@@ -405,11 +443,17 @@ struct _arch_code_generator_if_t {
 
        /**
         * Called after register allocation to lower Spills to Stores
+        * @param self  The code generator
+        * @param spill The spill node to lower
+        * @return      The new backend node which substitutes the spill
         */
        ir_node *(*lower_spill)(void *self, ir_node *spill);
 
        /**
         * Called after register allocation to lower Reloads to Loads
+        * @param self   The code generator
+        * @param reload The reload node to lower
+        * @return       The new backend node which substitutes the reload
         */
        ir_node *(*lower_reload)(void *self, ir_node *reload);
 
@@ -444,8 +488,15 @@ struct _arch_code_generator_t {
  */
 struct _arch_isa_t {
        const arch_isa_if_t *impl;
+       const arch_register_t *sp;  /** The stack pointer register. */
+       const arch_register_t *bp;  /** The base pointer register. */
+       const int stack_dir;        /** -1 for decreasing, 1 for increasing. */
 };
 
+#define arch_isa_stack_dir(isa)  ((isa)->stack_dir)
+#define arch_isa_sp(isa)         ((isa)->sp)
+#define arch_isa_bp(isa)         ((isa)->bp)
+
 /**
  * Architecture interface.
  */
@@ -478,6 +529,22 @@ struct _arch_isa_if_t {
    */
   const arch_register_class_t *(*get_reg_class)(const void *self, int i);
 
+  /**
+   * Get the register class which shall be used to store a value of a given mode.
+   * @param self The this pointer.
+   * @param mode The mode in question.
+   * @return A register class which can hold values of the given mode.
+   */
+  const arch_register_class_t *(*get_reg_class_for_mode)(const void *self, const ir_mode *mode);
+
+  /**
+   * Get the ABI restrictions for procedure calls.
+   * @param self        The this pointer.
+   * @param method_type The type of the method (procedure) in question.
+   * @param p           The array of parameter locations to be filled.
+   */
+  void (*get_call_abi)(const void *self, ir_type *method_type, be_abi_call_t *abi);
+
   /**
    * The irn handler for this architecture.
    * The irn handler is registered by the Firm back end
@@ -501,18 +568,21 @@ struct _arch_isa_if_t {
   const list_sched_selector_t *(*get_list_sched_selector)(const void *self);
 
   /**
-   * Get the proj number assigned to the register.
-   * @param self  The isa object.
-   * @param reg   The register
-   * @return      The proj number assigned to this register
+   * Take a proj from a call, set the correct register and projnum for this proj
+   * @param self    The isa object.
+   * @param proj    The proj
+   * @param is_keep Non-zero if proj is a Keep argument
+   * @return        The backend proj number assigned to this proj
    */
-  long (*get_projnum_for_register)(const void *self, const arch_register_t *reg);
+  long (*handle_call_proj)(const void *self, ir_node *proj, int is_keep);
 };
 
-#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_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_get_call_abi(isa,tp,abi)                   ((isa)->impl->get_call_abi((isa), (tp), (abi)))
+#define arch_isa_get_reg_class_for_mode(isa,mode)           ((isa)->impl->get_reg_class_for_mode((isa), (mode)))
+#define arch_isa_make_code_generator(isa,irg)               ((isa)->impl->make_code_generator(isa, irg))
 
 #define ARCH_MAX_HANDLERS         8
 
@@ -551,7 +621,6 @@ extern arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa);
  * @param handler A node handler.
  * @return The environment itself.
  */
-extern arch_env_t *arch_env_add_irn_handler(arch_env_t *env,
-    const arch_irn_handler_t *handler);
+extern arch_env_t *arch_env_add_irn_handler(arch_env_t *env, const arch_irn_handler_t *handler);
 
 #endif /* _FIRM_BEARCH_H */