#include <stdbool.h>
#include "firm_types.h"
-#include "bitset.h"
-#include "obst.h"
#include "raw_bitset.h"
-#include "irop_t.h"
#include "be_types.h"
#include "beinfo.h"
#include "be.h"
-#include "beirg.h"
-#include "error.h"
/**
* this constant is returned by the get_sp_bias functions if the stack
arch_register_type_none = 0,
/** Do not consider this register when allocating. */
arch_register_type_ignore = 1U << 0,
- /** The emitter can choose an arbitrary register. The register fulfills any
- * register constraints as long as the register class matches */
- arch_register_type_joker = 1U << 1,
/** This is just a virtual register. Virtual registers fulfill any register
* constraints as long as the register class matches. It is a allowed to
* have multiple definitions for the same virtual register at a point */
- arch_register_type_virtual = 1U << 2,
+ arch_register_type_virtual = 1U << 1,
/** The register represents a state that should be handled by bestate
* code */
- arch_register_type_state = 1U << 3,
+ arch_register_type_state = 1U << 2,
} arch_register_type_t;
ENUM_BITSET(arch_register_type_t)
} arch_register_req_type_t;
ENUM_BITSET(arch_register_req_type_t)
-extern const arch_register_req_t *arch_no_register_req;
-
-/**
- * Print information about a register requirement in human readable form
- * @param F output stream/file
- * @param req The requirements structure to format.
- */
-void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
- const ir_node *node);
+extern arch_register_req_t const arch_no_requirement;
+#define arch_no_register_req (&arch_no_requirement)
void arch_dump_register_reqs(FILE *F, const ir_node *node);
void arch_dump_reqs_and_registers(FILE *F, const ir_node *node);
int arch_get_sp_bias(ir_node *irn);
int arch_get_op_estimated_cost(const ir_node *irn);
-arch_inverse_t *arch_get_inverse(const ir_node *irn, int i,
- arch_inverse_t *inverse,
- struct obstack *obstack);
int arch_possible_memory_operand(const ir_node *irn,
unsigned int i);
void arch_perform_memory_operand(ir_node *irn, ir_node *spill,
/**
* Set the register for a certain output operand.
*/
-void arch_set_irn_register_out(ir_node *irn, int pos, const arch_register_t *r);
+void arch_set_irn_register_out(ir_node *irn, unsigned pos, const arch_register_t *r);
-const arch_register_t *arch_get_irn_register_out(const ir_node *irn, int pos);
+const arch_register_t *arch_get_irn_register_out(const ir_node *irn, unsigned pos);
const arch_register_t *arch_get_irn_register_in(const ir_node *irn, int pos);
/**
const ir_node *node, int pos)
{
const backend_info_t *info = be_get_info(node);
- if (info->in_reqs == NULL)
- return arch_no_register_req;
return info->in_reqs[pos];
}
* Get register constraint for a produced result (the @p pos result)
*/
static inline const arch_register_req_t *arch_get_irn_register_req_out(
- const ir_node *node, int pos)
+ const ir_node *node, unsigned pos)
{
const backend_info_t *info = be_get_info(node);
- if (info->out_infos == NULL)
- return arch_no_register_req;
return info->out_infos[pos].req;
}
-static inline void arch_set_irn_register_req_out(ir_node *node, int pos,
+static inline void arch_set_irn_register_req_out(ir_node *node, unsigned pos,
const arch_register_req_t *req)
{
backend_info_t *info = be_get_info(node);
- assert(pos < (int)ARR_LEN(info->out_infos));
+ assert(pos < (unsigned)ARR_LEN(info->out_infos));
info->out_infos[pos].req = req;
}
return info->in_reqs;
}
-const arch_register_req_t *arch_get_irn_register_req(const ir_node *node);
+static inline reg_out_info_t *get_out_info(const ir_node *node)
+{
+ size_t pos = 0;
+ const backend_info_t *info;
+ assert(get_irn_mode(node) != mode_T);
+ if (is_Proj(node)) {
+ pos = get_Proj_proj(node);
+ node = get_Proj_pred(node);
+ }
+
+ info = be_get_info(node);
+ assert(pos < ARR_LEN(info->out_infos));
+ return &info->out_infos[pos];
+}
+
+static inline const arch_register_req_t *arch_get_irn_register_req(const ir_node *node)
+{
+ reg_out_info_t *out = get_out_info(node);
+ return out->req;
+}
/**
* Get the flags of a node.
* @param irn The node.
* @return The flags.
*/
-arch_irn_flags_t arch_get_irn_flags(const ir_node *irn);
+static inline arch_irn_flags_t arch_get_irn_flags(const ir_node *node)
+{
+ backend_info_t const *const info = be_get_info(node);
+ return info->flags;
+}
void arch_set_irn_flags(ir_node *node, arch_irn_flags_t flags);
void arch_add_irn_flags(ir_node *node, arch_irn_flags_t flags);
static inline unsigned arch_get_irn_n_outs(const ir_node *node)
{
- backend_info_t *info = be_get_info(node);
- if (info->out_infos == NULL)
- return 0;
-
+ backend_info_t *const info = be_get_info(node);
return (unsigned)ARR_LEN(info->out_infos);
}
-/**
- * Start codegeneration
- */
-arch_env_t *arch_env_begin_codegeneration(const arch_isa_if_t *isa,
- be_main_env_t *main_env);
+#define be_foreach_out(node, i) \
+ for (unsigned i = 0, i##__n = arch_get_irn_n_outs(node); i != i##__n; ++i)
/**
* Register an instruction set architecture
const arch_register_class_t *reg_class; /**< The class of the register */
unsigned short index; /**< The index of the register in
the class. */
- unsigned short global_index; /** The global index this register
- in the architecture. */
+ unsigned short global_index; /**< The global index this
+ register in the architecture. */
arch_register_type_t type; /**< The type of the register. */
/** register constraint allowing just this register */
const arch_register_req_t *single_req;
+ /** register number in dwarf debugging format */
+ unsigned short dwarf_number;
};
-static inline const arch_register_class_t *arch_register_get_class(
- const arch_register_t *reg)
-{
- return reg->reg_class;
-}
-
-static inline unsigned arch_register_get_index(const arch_register_t *reg)
-{
- return reg->index;
-}
-
-static inline const char *arch_register_get_name(const arch_register_t *reg)
-{
- return reg->name;
-}
-
/**
* A class of registers.
* Like general purpose or floating point.
arch_register_req_type_t type; /**< The type of the constraint. */
const arch_register_class_t *cls; /**< The register class this constraint
belongs to. */
- const unsigned *limited; /**< allowed register bitset */
- unsigned other_same; /**< Bitmask of ins which should use the
- same register (should_be_same). */
- 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 */
+ const unsigned *limited; /**< allowed register bitset
+ (in case of wide-values this is
+ only about the first register) */
+ unsigned other_same; /**< Bitmask of ins which should use the
+ same register (should_be_same). */
+ 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 bool reg_reqs_equal(const arch_register_req_t *req1,
return true;
}
-/**
- * An inverse operation returned by the backend
- */
-struct arch_inverse_t {
- int n; /**< count of nodes returned in nodes array */
- int costs; /**< costs of this remat */
-
- /** nodes for this inverse operation. shall be in schedule order.
- * last element is the target value */
- ir_node **nodes;
-};
-
struct arch_irn_ops_t {
/**
*/
int (*get_sp_bias)(const ir_node *irn);
- /**
- * Returns an inverse operation which yields the i-th argument
- * of the given node as result.
- *
- * @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 ir_node *irn, int i,
- arch_inverse_t *inverse,
- struct obstack *obstack);
-
/**
* Get the estimated cycle count for @p irn.
*
* Start codegeneration
* @return a new isa instance
*/
- arch_env_t *(*begin_codegeneration)(const be_main_env_t *env);
+ arch_env_t *(*begin_codegeneration)(void);
/**
* Free the isa instance.
#define arch_env_handle_intrinsics(env) \
do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0)
#define arch_env_get_call_abi(env,tp,abi) ((env)->impl->get_call_abi((tp), (abi)))
-#define arch_env_get_params(env) ((env)->impl->get_params())
-#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((c))
-#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((clobber))
#define arch_env_mark_remat(env,node) \
do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((node)); } while(0)
const arch_register_class_t *register_classes; /**< register classes */
const arch_register_t *sp; /**< The stack pointer register. */
const arch_register_t *bp; /**< The base pointer register. */
- const arch_register_class_t *link_class; /**< The static link pointer
- register class. */
int stack_alignment; /**< power of 2 stack alignment */
- const be_main_env_t *main_env; /**< the be main environment */
int spill_cost; /**< cost for a be_Spill node */
int reload_cost; /**< cost for a be_Reload node */
bool custom_abi : 1; /**< backend does all abi handling
static inline bool arch_irn_is_ignore(const ir_node *irn)
{
const arch_register_req_t *req = arch_get_irn_register_req(irn);
- return req->type & arch_register_req_type_ignore;
+ return arch_register_req_is(req, ignore);
}
static inline bool arch_irn_consider_in_reg_alloc(
const arch_register_class_t *cls, const ir_node *node)
{
const arch_register_req_t *req = arch_get_irn_register_req(node);
- return
- req->cls == cls &&
- !(req->type & arch_register_req_type_ignore);
+ return req->cls == cls && !arch_register_req_is(req, ignore);
}
+#define be_foreach_value(node, value, code) \
+ do { \
+ if (get_irn_mode(node) == mode_T) { \
+ foreach_out_edge(node, node##__edge) { \
+ ir_node *const value = get_edge_src_irn(node##__edge); \
+ if (!is_Proj(value)) \
+ continue; \
+ code \
+ } \
+ } else { \
+ ir_node *const value = node; \
+ code \
+ } \
+ } while (0)
+
/**
* 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_irn_register_req(value); \
- if (req_->cls != cls) \
- continue; \
- code \
- } \
- } else { \
- const arch_register_req_t *req_ = arch_get_irn_register_req(node); \
- value = node; \
- if (req_->cls == cls) { \
- code \
- } \
- } \
- } while (0)
+#define be_foreach_definition_(node, ccls, value, req, code) \
+ be_foreach_value(node, value, \
+ arch_register_req_t const *const req = arch_get_irn_register_req(value); \
+ if (req->cls != ccls) \
+ continue; \
+ code \
+ )
-#define be_foreach_definition(node, cls, value, code) \
- be_foreach_definition_(node, cls, value, \
- if (req_->type & arch_register_req_type_ignore) \
- continue; \
- code \
+#define be_foreach_definition(node, ccls, value, req, code) \
+ be_foreach_definition_(node, ccls, value, req, \
+ if (arch_register_req_is(req, ignore)) \
+ continue; \
+ code \
)
+#define be_foreach_use(node, ccls, in_req, value, value_req, code) \
+ do { \
+ for (int i_ = 0, n_ = get_irn_arity(node); i_ < n_; ++i_) { \
+ const arch_register_req_t *in_req = arch_get_irn_register_req_in(node, i_); \
+ if (in_req->cls != ccls) \
+ continue; \
+ ir_node *value = get_irn_n(node, i_); \
+ const arch_register_req_t *value_req = arch_get_irn_register_req(value); \
+ if (value_req->type & arch_register_req_type_ignore) \
+ continue; \
+ code \
+ } \
+ } while (0)
+
static inline const arch_register_class_t *arch_get_irn_reg_class(
const ir_node *node)
{