#include "firm_config.h"
-#ifdef WITH_LIBCORE
-#include <libcore/lc_opts.h>
-#endif
-
#include "firm_types.h"
#include "bitset.h"
#include "bearch_t.h"
#include "be_t.h"
#include "bemachine.h"
-
-struct _be_node_factory_t;
+#include "beirg.h"
typedef enum _arch_register_type_t {
- arch_register_type_none = 0,
- arch_register_type_caller_save = 1, /**< The register must be saved by the caller
+ arch_register_type_none = 0,
+ 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
+ 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_joker = 8, /**< The emitter can choose an arbitrary register */
- arch_register_type_virtual = 16, /**< This is just a virtual register */
+ arch_register_type_ignore = 4, /**< Do not consider this register when allocating. */
+ arch_register_type_joker = 8, /**< The emitter can choose an arbitrary register */
+ arch_register_type_virtual = 16, /**< This is just a virtual register */
+ arch_register_type_state = 32,
} arch_register_type_t;
/**
* A 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. */
- void *data; /**< Custom data. */
+ 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. */
+ void *data; /**< Custom data. */
};
static INLINE const arch_register_class_t *
_arch_register_get_class(const arch_register_t *reg)
{
- return reg->reg_class;
+ return reg->reg_class;
}
static INLINE int _arch_register_get_index(const arch_register_t *reg)
{
- return reg->index;
+ return reg->index;
}
static INLINE const char *_arch_register_get_name(const arch_register_t *reg)
* Like general purpose or floating point.
*/
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. */
+ 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. */
};
/** return the number of registers in this register class */
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) \
_arch_register_for_index(cls, idx)
typedef enum _arch_operand_type_t {
- arch_operand_type_invalid,
- arch_operand_type_memory,
- arch_operand_type_register,
- arch_operand_type_immediate,
- arch_operand_type_symconst,
- arch_operand_type_last
+ arch_operand_type_invalid,
+ arch_operand_type_memory,
+ arch_operand_type_register,
+ arch_operand_type_immediate,
+ arch_operand_type_symconst,
+ arch_operand_type_last
} 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_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_should_be_same = 4, /**< The register should be equal
- another one 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_should_be_different_from_all = 16, /**< The register must be different from
- all in's at the node */
+ 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_limited = 2, /**< Only a real subset of the class is allowed. */
+ arch_register_req_type_should_be_same = 4, /**< The register should be equal another one 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_should_be_different_from_all = 16, /**< The register must be different from all in's at the node */
} arch_register_req_type_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. */
-
- void (*limited)(void *limited_env, bitset_t *bs);
- /**< 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. */
-
- void *limited_env; /**< This must passed to limited. */
+ arch_register_req_type_t type; /**< The type of the constraint. */
+ const arch_register_class_t *cls; /**< The register class this constraint belongs to. */
- ir_node *other_same; /**< The other which shall have the same reg
- as this one. (for case should_be_same). */
+ const unsigned *limited; /**< allowed register bitset */
- ir_node *other_different; /**< The other node from which this one's register
- must be different (case must_be_different). */
+ int other_same; /**< The in number which shall have
+ the same res (should_be_same)*/
+ int other_different; /**< The other node from which this
+ one's register must be different
+ (case must_be_different). */
} arch_register_req_t;
+extern const arch_register_req_t *arch_no_register_req;
+
/**
* Format a register requirements information into a string.
* @param buf The string where to put it to.
* @param req The requirements structure to format.
* @return A pointer to buf.
*/
-extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req);
+extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req, const ir_node *node);
/**
* Certain node classes which are relevant for the register allocator.
*/
typedef enum _arch_irn_class_t {
- arch_irn_class_normal = 1 << 0,
- arch_irn_class_spill = 1 << 1,
- arch_irn_class_reload = 1 << 2,
- arch_irn_class_copy = 1 << 3,
- arch_irn_class_perm = 1 << 4,
- arch_irn_class_branch = 1 << 5,
- arch_irn_class_call = 1 << 6,
- arch_irn_class_const = 1 << 7,
- arch_irn_class_load = 1 << 8,
- arch_irn_class_store = 1 << 9,
- arch_irn_class_stackparam = 1 << 10,
+ arch_irn_class_normal = 1 << 0,
+ arch_irn_class_spill = 1 << 1,
+ arch_irn_class_reload = 1 << 2,
+ arch_irn_class_copy = 1 << 3,
+ arch_irn_class_perm = 1 << 4,
+ arch_irn_class_branch = 1 << 5,
+ arch_irn_class_call = 1 << 6,
+ arch_irn_class_const = 1 << 7,
+ arch_irn_class_load = 1 << 8,
+ arch_irn_class_store = 1 << 9,
+ arch_irn_class_stackparam = 1 << 10,
} arch_irn_class_t;
/**
struct _arch_irn_ops_if_t {
- /**
- * Get the register requirements for a given operand.
- * @param self The self pointer.
- * @param irn The node.
- * @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 void *self,
- arch_register_req_t *req, const ir_node *irn, int pos);
+ /**
+ * Get the register requirements for a given operand.
+ * @param self The self pointer.
+ * @param irn The node.
+ * @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 void *self,
+ const ir_node *irn, int pos);
- /**
- * Set the register for an output operand.
- * @param irn The node.
- * @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 void *self, ir_node *irn, const arch_register_t *reg);
+ /**
+ * Set the register for an output operand.
+ * @param irn The node.
+ * @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 void *self, ir_node *irn, const arch_register_t *reg);
- /**
- * Get the register allocated for an output operand.
- * @param irn The 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 void *self, const ir_node *irn);
+ /**
+ * Get the register allocated for an output operand.
+ * @param irn The 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 void *self, const ir_node *irn);
- /**
- * Classify the node.
- * @param irn The node.
- * @return A classification.
- */
- arch_irn_class_t (*classify)(const void *self, const ir_node *irn);
+ /**
+ * Classify the node.
+ * @param irn The node.
+ * @return A classification.
+ */
+ arch_irn_class_t (*classify)(const void *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 void *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 void *self, const ir_node *irn);
- /**
- * Get the entity on the stack frame this node depends on.
- * @param self The this pointer.
- * @param irn The node in question.
- * @return The entity on the stack frame or NULL, if the node does not have a
- * stack frame entity.
- */
- ir_entity *(*get_frame_entity)(const void *self, const ir_node *irn);
+ /**
+ * Get the entity on the stack frame this node depends on.
+ * @param self The this pointer.
+ * @param irn The node in question.
+ * @return The entity on the stack frame or NULL, if the node does not have a
+ * stack frame entity.
+ */
+ ir_entity *(*get_frame_entity)(const void *self, const ir_node *irn);
- /**
- * Set the entity on the stack frame this node depends on.
- * @param self The this pointer.
- * @param irn The node in question.
- * @param ent The entity to set
- */
- void (*set_frame_entity)(const void *self, ir_node *irn, ir_entity *ent);
+ /**
+ * Set the entity on the stack frame this node depends on.
+ * @param self The this pointer.
+ * @param irn The node in question.
+ * @param ent The entity to set
+ */
+ void (*set_frame_entity)(const void *self, ir_node *irn, ir_entity *ent);
- /**
- * Set the offset of a node carrying an entity on the stack frame.
- * @param self The this pointer.
- * @param irn The node.
- * @param offset The offset of the node's stack frame entity.
- */
- void (*set_frame_offset)(const void *self, ir_node *irn, int offset);
+ /**
+ * Set the offset of a node carrying an entity on the stack frame.
+ * @param self The this pointer.
+ * @param irn The node.
+ * @param offset The offset of the node's stack frame entity.
+ */
+ void (*set_frame_offset)(const void *self, ir_node *irn, int offset);
- /**
- * Returns the delta of the stackpointer for nodes that increment or
- * decrement the stackpointer with a constant value. (push, pop
- * nodes on most architectures).
- * A positive value stands for an expanding stack area, a negative value for
- * a shrinking one.
- *
- * @param self The this pointer
- * @param irn The node
- * @return 0 if the stackpointer is not modified with a constant
- * value, otherwise the increment/decrement value
- */
- int (*get_sp_bias)(const void *self, const ir_node *irn);
+ /**
+ * Returns the delta of the stackpointer for nodes that increment or
+ * decrement the stackpointer with a constant value. (push, pop
+ * nodes on most architectures).
+ * A positive value stands for an expanding stack area, a negative value for
+ * a shrinking one.
+ *
+ * @param self The this pointer
+ * @param irn The node
+ * @return 0 if the stackpointer is not modified with a constant
+ * value, otherwise the increment/decrement value
+ */
+ int (*get_sp_bias)(const void *self, const ir_node *irn);
- /**
- * Returns an inverse operation which yields the i-th argument
- * of the given node as result.
- *
- * @param self The this pointer.
- * @param irn The original operation
- * @param i Index of the argument we want the inverse operation to yield
- * @param inverse struct to be filled with the resulting inverse op
- * @param obstack The obstack to use for allocation of the returned nodes array
- * @return The inverse operation or NULL if operation invertible
- */
- arch_inverse_t *(*get_inverse)(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack);
+ /**
+ * Returns an inverse operation which yields the i-th argument
+ * of the given node as result.
+ *
+ * @param self The this pointer.
+ * @param irn The original operation
+ * @param i Index of the argument we want the inverse operation to yield
+ * @param inverse struct to be filled with the resulting inverse op
+ * @param obstack The obstack to use for allocation of the returned nodes array
+ * @return The inverse operation or NULL if operation invertible
+ */
+ arch_inverse_t *(*get_inverse)(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack);
- /**
- * Get the estimated cycle count for @p irn.
- *
- * @param self The this pointer.
- * @param irn The node.
- *
- * @return The estimated cycle count for this operation
- */
- int (*get_op_estimated_cost)(const void *self, const ir_node *irn);
+ /**
+ * Get the estimated cycle count for @p irn.
+ *
+ * @param self The this pointer.
+ * @param irn The node.
+ *
+ * @return The estimated cycle count for this operation
+ */
+ int (*get_op_estimated_cost)(const void *self, const ir_node *irn);
- /**
- * Asks the backend whether operand @p i of @p irn can be loaded form memory internally
- *
- * @param self The this pointer.
- * @param irn The node.
- * @param i Index of the argument we would like to know whether @p irn can load it form memory internally
- *
- * @return nonzero if argument can be loaded or zero otherwise
- */
- int (*possible_memory_operand)(const void *self, const ir_node *irn, unsigned int i);
+ /**
+ * Asks the backend whether operand @p i of @p irn can be loaded form memory internally
+ *
+ * @param self The this pointer.
+ * @param irn The node.
+ * @param i Index of the argument we would like to know whether @p irn can load it form memory internally
+ *
+ * @return nonzero if argument can be loaded or zero otherwise
+ */
+ int (*possible_memory_operand)(const void *self, const ir_node *irn, unsigned int i);
- /**
- * Ask the backend to assimilate @p reload of operand @p i into @p irn.
- *
- * @param self The this pointer.
- * @param irn The node.
- * @param spill The spill.
- * @param i The position of the reload.
- */
- void (*perform_memory_operand)(const void *self, ir_node *irn, ir_node *spill, unsigned int i);
+ /**
+ * Ask the backend to assimilate @p reload of operand @p i into @p irn.
+ *
+ * @param self The this pointer.
+ * @param irn The node.
+ * @param spill The spill.
+ * @param i The position of the reload.
+ */
+ void (*perform_memory_operand)(const void *self, ir_node *irn, ir_node *spill, unsigned int i);
};
/**
* operand was no register operand.
*/
extern const arch_register_req_t *
-arch_get_register_req(const arch_env_t *env, arch_register_req_t *req,
- const ir_node *irn, int pos);
+arch_get_register_req(const arch_env_t *env, const ir_node *irn, int pos);
/**
* Check if an operand is a register operand.
#define arch_irn_is(env, irn, flag) ((arch_irn_get_flags(env, irn) & arch_irn_flags_ ## flag) != 0)
#define arch_irn_has_reg_class(env, irn, pos, cls) \
- ((cls) == arch_get_irn_reg_class(env, irn, pos))
+ ((cls) == arch_get_irn_reg_class(env, irn, pos))
#define arch_irn_consider_in_reg_alloc(env, cls, irn) \
(arch_irn_has_reg_class(env, irn, -1, cls) && !arch_irn_is(env, irn, ignore))
* Backend may provide an own spiller.
* This spiller needs to spill all register classes.
*/
- void (*spill)(void *self, void *env);
+ void (*spill)(void *self, be_irg_t *birg);
/**
* Called before scheduling.
#define arch_code_generator_after_ra(cg) _arch_cg_call(cg, after_ra)
#define arch_code_generator_finish(cg) _arch_cg_call(cg, finish)
#define arch_code_generator_done(cg) _arch_cg_call(cg, done)
-#define arch_code_generator_spill(cg, env) _arch_cg_call_env(cg, env, spill)
+#define arch_code_generator_spill(cg, birg) _arch_cg_call_env(cg, birg, spill)
#define arch_code_generator_has_spiller(cg) ((cg)->impl->spill != NULL)
/**
* @param self The isa object.
*/
const be_machine_t *(*get_machine)(const void *self);
+
+ /**
+ * Return an ordered list of irgs where code should be generated for.
+ * If NULL is returned, all irg will be taken into account and they will be
+ * generated in an arbitrary order.
+ * @param self The isa object.
+ * @param irgs A flexible array ARR_F of length 0 where the backend cann append the desired irgs.
+ * @return A flexible array ARR_F containing all desired irgs in the desired order.
+ */
+ ir_graph **(*get_backend_irg_list)(const void *self, ir_graph ***irgs);
};
#define arch_isa_get_n_reg_class(isa) ((isa)->impl->get_n_reg_class(isa))
#define arch_isa_get_reg_class_alignment(isa, cls) ((isa)->impl->get_reg_class_alignment((isa), (cls)))
#define arch_isa_get_allowed_execution_units(isa, irn) ((isa)->impl->get_allowed_execution_units((isa), (irn)))
#define arch_isa_get_machine(isa) ((isa)->impl->get_machine((isa)))
+#define arch_isa_get_backend_irg_list(isa, irgs) ((isa)->impl->get_backend_irg_list((isa), (irgs)))
#define ARCH_MAX_HANDLERS 8
* Keep this everywhere you're going.
*/
struct _arch_env_t {
- const struct _be_node_factory_t *node_factory; /**< The node factory for be nodes. */
- arch_isa_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
+ arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /**< The handlers are organized as
a stack. */
- int handlers_tos; /**< The stack pointer of the handler
+ int handlers_tos; /**< The stack pointer of the handler
stack. */
};
*/
extern const arch_irn_handler_t *arch_env_pop_irn_handler(arch_env_t *env);
+/**
+ * Register an instruction set architecture
+ */
+void be_register_isa_if(const char *name, const arch_isa_if_t *isa);
+
#endif /* _FIRM_BEARCH_H */