#define SNPRINTF_BUF_LEN 128
-static const arch_env_t *arch_env = NULL;
-
-
-/*************************************************************
- * _ _ __ _ _
- * (_) | | / _| | | | |
- * _ __ _ __ _ _ __ | |_| |_ | |__ ___| |_ __ ___ _ __
- * | '_ \| '__| | '_ \| __| _| | '_ \ / _ \ | '_ \ / _ \ '__|
- * | |_) | | | | | | | |_| | | | | | __/ | |_) | __/ |
- * | .__/|_| |_|_| |_|\__|_| |_| |_|\___|_| .__/ \___|_|
- * | | | |
- * |_| |_|
- *************************************************************/
-
-/**
- * Return a const or symconst as string.
- */
-static const char *node_const_to_str(ir_node *n) {
- /* TODO */
-}
-
-/**
- * Returns node's offset as string.
- */
-static char *node_offset_to_str(ir_node *n) {
- /* TODO */
-}
-
-/* We always pass the ir_node which is a pointer. */
-static int TEMPLATE_get_arg_type(const lc_arg_occ_t *occ) {
- return lc_arg_type_ptr;
-}
-
-
/**
* Returns the register at in position pos.
*/
-static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
+static const arch_register_t *get_in_reg(const arch_env_t *arch_env,
+ const ir_node *node, int pos)
+{
ir_node *op;
const arch_register_t *reg = NULL;
- assert(get_irn_arity(irn) > pos && "Invalid IN position");
+ assert(get_irn_arity(node) > pos && "Invalid IN position");
/* The out register of the operator at position pos is the
in register we need. */
- op = get_irn_n(irn, pos);
+ op = get_irn_n(node, pos);
reg = arch_get_irn_register(arch_env, op);
/**
* Returns the register at out position pos.
*/
-static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
+static const arch_register_t *get_out_reg(const arch_env_t *arch_env,
+ const ir_node *node, int pos)
+{
ir_node *proj;
const arch_register_t *reg = NULL;
/* 2nd case: irn is of mode_T -> collect all Projs and ask the */
/* Proj with the corresponding projnum for the register */
- if (get_irn_mode(irn) != mode_T) {
- reg = arch_get_irn_register(arch_env, irn);
- }
- else if (is_TEMPLATE_irn(irn)) {
- reg = get_TEMPLATE_out_reg(irn, pos);
- }
- else {
+ if (get_irn_mode(node) != mode_T) {
+ reg = arch_get_irn_register(arch_env, node);
+ } else if (is_TEMPLATE_irn(node)) {
+ reg = get_TEMPLATE_out_reg(node, pos);
+ } else {
const ir_edge_t *edge;
- foreach_out_edge(irn, edge) {
+ foreach_out_edge(node, edge) {
proj = get_edge_src_irn(edge);
assert(is_Proj(proj) && "non-Proj from mode_T node");
if (get_Proj_proj(proj) == pos) {
return reg;
}
-/**
- * Returns the number of the in register at position pos.
- */
-int get_TEMPLATE_reg_nr(ir_node *irn, int pos, int in_out) {
- const arch_register_t *reg;
-
- if (in_out == 1) {
- reg = get_in_reg(irn, pos);
- }
- else {
- reg = get_out_reg(irn, pos);
- }
-
- return arch_register_get_index(reg);
-}
-
-/**
- * Returns the name of the in register at position pos.
- */
-const char *get_TEMPLATE_reg_name(ir_node *irn, int pos, int in_out) {
- const arch_register_t *reg;
-
- if (in_out == 1) {
- reg = get_in_reg(irn, pos);
- }
- else {
- reg = get_out_reg(irn, pos);
- }
-
- return arch_register_get_name(reg);
-}
+/*************************************************************
+ * _ _ __ _ _
+ * (_) | | / _| | | | |
+ * _ __ _ __ _ _ __ | |_| |_ | |__ ___| |_ __ ___ _ __
+ * | '_ \| '__| | '_ \| __| _| | '_ \ / _ \ | '_ \ / _ \ '__|
+ * | |_) | | | | | | | |_| | | | | | __/ | |_) | __/ |
+ * | .__/|_| |_|_| |_|\__|_| |_| |_|\___|_| .__/ \___|_|
+ * | | | |
+ * |_| |_|
+ *************************************************************/
-/**
- * Get the register name for a node.
- */
-static int TEMPLATE_get_reg_name(lc_appendable_t *app,
- const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+void TEMPLATE_emit_immediate(TEMPLATE_emit_env_t *env, const ir_node *node)
{
- const char *buf;
- ir_node *X = arg->v_ptr;
- int nr = occ->width - 1;
-
- if (!X)
- return lc_arg_append(app, occ, "(null)", 6);
-
- if (occ->conversion == 'S') {
- buf = get_TEMPLATE_reg_name(X, nr, 1);
- }
- else { /* 'D' */
- buf = get_TEMPLATE_reg_name(X, nr, 0);
- }
-
- return buf ? lc_arg_append(app, occ, buf, strlen(buf)) : 0;
+ /* TODO */
}
-/**
- * Returns the tarval or offset of an TEMPLATE node as a string.
- */
-static int TEMPLATE_const_to_str(lc_appendable_t *app,
- const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+void TEMPLATE_emit_source_register(TEMPLATE_emit_env_t *env, const ir_node *node, int pos)
{
- const char *buf;
- ir_node *X = arg->v_ptr;
-
- if (!X)
- return lc_arg_append(app, occ, "(null)", 6);
-
- if (occ->conversion == 'C') {
- buf = node_const_to_str(X);
- }
- else { /* 'O' */
- buf = node_offset_to_str(X);
- }
-
- return lc_arg_append(app, occ, buf, strlen(buf));
+ const arch_register_t *reg = get_in_reg(env->arch_env, node, pos);
+ be_emit_string(env->emit, arch_register_get_name(reg));
}
-/**
- * Determines the SSE suffix depending on the mode.
- */
-static int TEMPLATE_get_mode_suffix(lc_appendable_t *app,
- const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+void TEMPLATE_emit_dest_register(TEMPLATE_emit_env_t *env, const ir_node *node, int pos)
{
- ir_node *X = arg->v_ptr;
-
- if (!X)
- return lc_arg_append(app, occ, "(null)", 6);
-
- if (get_mode_size_bits(get_irn_mode(X)) == 32)
- return lc_appendable_chadd(app, 's');
- else
- return lc_appendable_chadd(app, 'd');
-}
-
-/**
- * Return the TEMPLATE printf arg environment.
- * We use the firm environment with some additional handlers.
- */
-const lc_arg_env_t *TEMPLATE_get_arg_env(void) {
- static lc_arg_env_t *env = NULL;
-
- static const lc_arg_handler_t TEMPLATE_reg_handler = { TEMPLATE_get_arg_type, TEMPLATE_get_reg_name };
- static const lc_arg_handler_t TEMPLATE_const_handler = { TEMPLATE_get_arg_type, TEMPLATE_const_to_str };
- static const lc_arg_handler_t TEMPLATE_mode_handler = { TEMPLATE_get_arg_type, TEMPLATE_get_mode_suffix };
-
- if(env == NULL) {
- /* extend the firm printer */
- env = firm_get_arg_env();
- //lc_arg_new_env();
-
- lc_arg_register(env, "TEMPLATE:sreg", 'S', &TEMPLATE_reg_handler);
- lc_arg_register(env, "TEMPLATE:dreg", 'D', &TEMPLATE_reg_handler);
- lc_arg_register(env, "TEMPLATE:cnst", 'C', &TEMPLATE_const_handler);
- lc_arg_register(env, "TEMPLATE:offs", 'O', &TEMPLATE_const_handler);
- lc_arg_register(env, "TEMPLATE:mode", 'M', &TEMPLATE_mode_handler);
- }
-
- return env;
-}
-
-/*
- * Add a number to a prefix. This number will not be used a second time.
- */
-static char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
- static unsigned long id = 0;
- snprintf(buf, buflen, "%s%lu", prefix, ++id);
- return buf;
+ const arch_register_t *reg = get_out_reg(env->arch_env, node, pos);
+ be_emit_string(env->emit, arch_register_get_name(reg));
}
-
/**
* Returns the target label for a control flow node.
*/
-static char *get_cfop_target(const ir_node *irn, char *buf) {
- ir_node *bl = get_irn_link(irn);
+static void TEMPLATE_emit_cfop_target(TEMPLATE_emit_env_t *env, const ir_node *node) {
+ ir_node *block = get_irn_link(node);
- snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
- return buf;
+ be_emit_irprintf(env->emit, "BLOCK_%ld", get_irn_node_nr(block));
}
-
-
/***********************************************************************************
* _ __ _
* (_) / _| | |
*
***********************************************************************************/
+/**
+ * Emits code for a unconditional jump.
+ */
+static void emit_Jmp(TEMPLATE_emit_env_t *env, const ir_node *node) {
+ ir_node *block;
+
+ /* for now, the code works for scheduled and non-schedules blocks */
+ block = get_nodes_block(node);
+
+ be_emit_cstring(env->emit, "\tjmp ");
+ TEMPLATE_emit_cfop_target(env, node);
+ be_emit_finish_line_gas(env->emit, node);
+}
+
/**
* Enters the emitter functions for handled nodes into the generic
* pointer of an opcode.
TEMPLATE_register_spec_emitters();
/* register addtional emitter functions if needed */
+ EMIT(Jmp);
#undef TEMPLATE_EMIT
#undef BE_EMIT
#undef EMIT
}
+typedef void (*emit_func_ptr) (TEMPLATE_emit_env_t *, const ir_node *);
/**
* Emits code for a node.
*/
-void TEMPLATE_emit_node(ir_node *irn, void *env) {
- TEMPLATE_emit_env_t *emit_env = env;
- FILE *F = emit_env->out;
- ir_op *op = get_irn_op(irn);
- DEBUG_ONLY(firm_dbg_module_t *mod = emit_env->mod;)
+void TEMPLATE_emit_node(TEMPLATE_emit_env_t *env, const ir_node *node) {
+ ir_op *op = get_irn_op(node);
+ DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
- DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
+ DBG((mod, LEVEL_1, "emitting code for %+F\n", node));
if (op->ops.generic) {
- void (*emit)(const ir_node *, void *) = (void (*)(const ir_node *, void *))op->ops.generic;
- (*emit)(irn, env);
- }
- else {
- ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
+ emit_func_ptr func = (emit_func_ptr) op->ops.generic;
+ (*func) (env, node);
+ } else {
+ ir_fprintf(stderr, "No emitter for node %+F\n", node);
}
}
* Walks over the nodes in a block connected by scheduling edges
* and emits code for each node.
*/
-void TEMPLATE_gen_block(ir_node *block, void *env) {
- TEMPLATE_emit_env_t *emit_env = env;
- ir_node *irn;
+void TEMPLATE_gen_block(ir_node *block, void *data) {
+ TEMPLATE_emit_env_t *env = data;
+ ir_node *node;
if (! is_Block(block))
return;
- fprintf(emit_env->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
- sched_foreach(block, irn) {
- TEMPLATE_emit_node(irn, env);
+ be_emit_cstring(env->emit, "BLOCK_");
+ be_emit_irprintf(env->emit, "%ld:\n", get_irn_node_nr(block));
+ be_emit_write_line(env->emit);
+
+ sched_foreach(block, node) {
+ TEMPLATE_emit_node(env, node);
}
}
/**
* Emits code for function start.
*/
-void TEMPLATE_emit_func_prolog(FILE *F, ir_graph *irg) {
+void TEMPLATE_emit_func_prolog(TEMPLATE_emit_env_t *env, ir_graph *irg) {
const char *irg_name = get_entity_name(get_irg_entity(irg));
/* TODO: emit function header */
+ be_emit_cstring(env->emit, "/* start of ");
+ be_emit_string(env->emit, irg_name);
+ be_emit_cstring(env->emit, " */\n");
+ be_emit_write_line(env->emit);
}
/**
* Emits code for function end
*/
-void TEMPLATE_emit_func_epilog(FILE *F, ir_graph *irg) {
+void TEMPLATE_emit_func_epilog(TEMPLATE_emit_env_t *env, ir_graph *irg) {
const char *irg_name = get_entity_name(get_irg_entity(irg));
/* TODO: emit function end */
+ be_emit_cstring(env->emit, "/* end of ");
+ be_emit_string(env->emit, irg_name);
+ be_emit_cstring(env->emit, " */\n");
+ be_emit_write_line(env->emit);
}
/**
/**
* Main driver
*/
-void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const TEMPLATE_code_gen_t *cg) {
- TEMPLATE_emit_env_t emit_env;
-
- emit_env.out = F;
- emit_env.arch_env = cg->arch_env;
- emit_env.cg = cg;
- FIRM_DBG_REGISTER(emit_env.mod, "firm.be.TEMPLATE.emit");
+void TEMPLATE_gen_routine(const TEMPLATE_code_gen_t *cg, ir_graph *irg) {
+ TEMPLATE_emit_env_t env;
- /* set the global arch_env (needed by print hooks) */
- arch_env = cg->arch_env;
+ env.isa = (TEMPLATE_isa_t *) cg->arch_env->isa;
+ env.emit = &env.isa->emit;
+ env.arch_env = cg->arch_env;
+ env.cg = cg;
+ FIRM_DBG_REGISTER(env.mod, "firm.be.TEMPLATE.emit");
/* register all emitter functions */
TEMPLATE_register_emitters();
- TEMPLATE_emit_func_prolog(F, irg);
- irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, &emit_env);
- irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, &emit_env);
- TEMPLATE_emit_func_epilog(F, irg);
+ TEMPLATE_emit_func_prolog(&env, irg);
+ irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, &env);
+ irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, &env);
+ TEMPLATE_emit_func_epilog(&env, irg);
}
#include "debug.h"
#include "../bearch.h"
+#include "../beemitter.h"
#include "bearch_TEMPLATE_t.h"
typedef struct _TEMPLATE_emit_env_t {
- FILE *out;
+ be_emit_env_t *emit;
const arch_env_t *arch_env;
const TEMPLATE_code_gen_t *cg;
+ TEMPLATE_isa_t *isa;
DEBUG_ONLY(firm_dbg_module_t *mod;)
} TEMPLATE_emit_env_t;
-const lc_arg_env_t *TEMPLATE_get_arg_env(void);
-
-void equalize_dest_src(FILE *F, ir_node *n);
+void TEMPLATE_emit_source_register(TEMPLATE_emit_env_t *env, const ir_node *node, int pos);
+void TEMPLATE_emit_dest_register(TEMPLATE_emit_env_t *env, const ir_node *node, int pos);
+void TEMPLATE_emit_immediate(TEMPLATE_emit_env_t *env, const ir_node *node);
int get_TEMPLATE_reg_nr(ir_node *irn, int posi, int in_out);
const char *get_TEMPLATE_in_reg_name(ir_node *irn, int pos);
-void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const TEMPLATE_code_gen_t *cg);
+void TEMPLATE_gen_routine(const TEMPLATE_code_gen_t *cg, ir_graph *irg);
#endif /* _TEMPLATE_EMITTER_H_ */
+++ /dev/null
-/**
- * Dumps global variables and constants as TEMPLATE assembler.
- * @date 14.02.2006
- * @version $Id$
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "xmalloc.h"
-#include <obstack.h>
-
-#ifdef obstack_chunk_alloc
-# undef obstack_chunk_alloc
-# define obstack_chunk_alloc xmalloc
-#else
-# define obstack_chunk_alloc xmalloc
-# define obstack_chunk_free free
-#endif
-
-#include "tv.h"
-#include "irnode.h"
-#include "entity.h"
-#include "irprog.h"
-
-#include "TEMPLATE_gen_decls.h"
-
-/************************************************************************/
-
-/*
- * returns the highest bit value
- */
-static unsigned highest_bit(unsigned v)
-{
- int res = -1;
-
- if (v >= (1U << 16U)) {
- res += 16;
- v >>= 16;
- }
- if (v >= (1U << 8U)) {
- res += 8;
- v >>= 8;
- }
- if (v >= (1U << 4U)) {
- res += 4;
- v >>= 4;
- }
- if (v >= (1U << 2U)) {
- res += 2;
- v >>= 2;
- }
- if (v >= (1U << 1U)) {
- res += 1;
- v >>= 1;
- }
- if (v >= 1)
- res += 1;
-
- return res;
-}
-
-/*
- * output the alignment
- */
-static void TEMPLATE_dump_align(struct obstack *obst, int align)
-{
- int h = highest_bit(align);
-
- if ((1 << h) < align)
- ++h;
- align = (1 << h);
-
- if (align > 1)
- obstack_printf(obst, "\t.align %d\n", align);
-}
-
-static void dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
-{
- switch (bytes) {
-
- case 1:
- obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
- break;
-
- case 2:
- obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 4:
- obstack_printf(obst, "0x%02x%02x%02x%02x",
- get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 8:
- obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
- get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
- get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 10:
- case 12:
- break;
-
- default:
- fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
- assert(0);
- }
-}
-
-/*
- * dump an arithmetic tarval
- */
-static void TEMPLATE_dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
-{
- switch (bytes) {
-
- case 1:
- obstack_printf(obst, "\t.byte\t");
- break;
-
- case 2:
- obstack_printf(obst, "\t.value\t");
- break;
-
- case 4:
- obstack_printf(obst, "\t.long\t");
- break;
-
- case 8:
- obstack_printf(obst, "\t.quad\t");
- break;
-
- case 10:
- case 12:
- break;
-
- default:
- fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
- assert(0);
- }
- dump_arith_tarval(obst, tv, bytes);
-}
-
-
-/*
- * dump an atomic value
- */
-static void do_dump_atomic_init(struct obstack *obst, ir_node *init)
-{
- ir_mode *mode = get_irn_mode(init);
- int bytes = get_mode_size_bytes(mode);
- tarval *tv;
-
- switch (get_irn_opcode(init)) {
-
- case iro_Cast:
- do_dump_atomic_init(obst, get_Cast_op(init));
- return;
-
- case iro_Conv:
- do_dump_atomic_init(obst, get_Conv_op(init));
- return;
-
- case iro_Const:
- tv = get_Const_tarval(init);
-
- /* beware of old stuff */
- assert(! mode_is_reference(mode));
-
- /* it's a arithmetic value */
- dump_arith_tarval(obst, tv, bytes);
- return;
-
- case iro_SymConst:
- switch (get_SymConst_kind(init)) {
- case symconst_addr_name:
- obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
- break;
-
- case symconst_addr_ent:
- obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
- break;
-
- case symconst_ofs_ent:
- obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
- break;
-
- case symconst_type_size:
- obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
- break;
-
- case symconst_type_align:
- obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
- break;
-
- default:
- assert(0 && "dump_atomic_init(): don't know how to init from this SymConst");
- }
- return;
-
- case iro_Add:
- do_dump_atomic_init(obst, get_Add_left(init));
- obstack_printf(obst, " + ");
- do_dump_atomic_init(obst, get_Add_right(init));
- return;
-
- case iro_Sub:
- do_dump_atomic_init(obst, get_Sub_left(init));
- obstack_printf(obst, " - ");
- do_dump_atomic_init(obst, get_Sub_right(init));
- return;
-
- case iro_Mul:
- do_dump_atomic_init(obst, get_Mul_left(init));
- obstack_printf(obst, " * ");
- do_dump_atomic_init(obst, get_Mul_right(init));
- return;
-
- default:
- assert(0 && "dump_atomic_init(): unknown IR-node");
- }
-}
-
-/*
- * dump an atomic value
- */
-static void dump_atomic_init(struct obstack *obst, ir_node *init)
-{
- ir_mode *mode = get_irn_mode(init);
- int bytes = get_mode_size_bytes(mode);
-
- switch (bytes) {
-
- case 1:
- obstack_printf(obst, "\t.byte\t");
- break;
-
- case 2:
- obstack_printf(obst, "\t.value\t");
- break;
-
- case 4:
- obstack_printf(obst, "\t.long\t");
- break;
-
- case 8:
- obstack_printf(obst, "\t.quad\t");
- break;
-
- case 10:
- case 12:
- /* handled in arith */
- break;
-
- default:
- fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
- assert(0);
- }
-
- do_dump_atomic_init(obst, init);
- obstack_printf(obst, "\n");
-}
-
-/************************************************************************/
-/* Routines to dump global variables */
-/************************************************************************/
-
-/**
- * Determine if an ir_entity is a string constant
- * @param ent The ir_entity
- * @return 1 if it is a string constant, 0 otherwise
- */
-static int ent_is_string_const(ir_entity *ent)
-{
- int res = 0;
- ir_type *ty;
-
- ty = get_entity_type(ent);
-
- /* if it's an array */
- if (is_Array_type(ty)) {
- ir_type *elm_ty = get_array_element_type(ty);
-
- /* and the array's element type is primitive */
- if (is_Primitive_type(elm_ty)) {
- ir_mode *mode = get_type_mode(elm_ty);
-
- /*
- * and the mode of the element type is an int of
- * the same size as the byte mode
- */
- if (mode_is_int(mode)
- && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
- {
- int i, c, n;
-
- n = get_compound_ent_n_values(ent);
- for (i = 0; i < n; ++i) {
- ir_node *irn = get_compound_ent_value(ent, i);
- if(get_irn_opcode(irn) != iro_Const)
- return 0;
-
- c = (int) get_tarval_long(get_Const_tarval(irn));
-
- if((i < n - 1 && !(isgraph(c) || isspace(c)))
- || (i == n - 1 && c != '\0'))
- return 0;
- }
-
- res = 1;
- }
- }
- }
-
- return res;
-}
-
-/**
- * Dump a atring constant.
- * No checks are made!!
- * @param obst The obst to dump on.
- * @param ent The ir_entity to dump.
- */
-static void dump_string_cst(struct obstack *obst, ir_entity *ent)
-{
- int i, n;
-
- obstack_printf(obst, "\t.string \"");
- n = get_compound_ent_n_values(ent);
-
- for (i = 0; i < n-1; ++i) {
- ir_node *irn;
- int c;
-
- irn = get_compound_ent_value(ent, i);
- c = (int) get_tarval_long(get_Const_tarval(irn));
-
- switch (c) {
- case '"' : obstack_printf(obst, "\\\""); break;
- case '\n': obstack_printf(obst, "\\n"); break;
- case '\r': obstack_printf(obst, "\\r"); break;
- case '\t': obstack_printf(obst, "\\t"); break;
- default :
- if (isprint(c))
- obstack_printf(obst, "%c", c);
- else
- obstack_printf(obst, "\\%o", c);
- break;
- }
- }
- obstack_printf(obst, "\"\n");
-}
-
-struct arr_info {
- int n_elems;
- int visit_cnt;
- int size;
-};
-
-/*
- * Dumps the initialization of global variables that are not
- * "uninitialized".
- */
-static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack, ir_entity *ent)
-{
- ir_type *ty = get_entity_type(ent);
- const char *ld_name = get_entity_ld_name(ent);
- int align, h;
- struct obstack *obst = data_obstack;
-
- /*
- * FIXME: did NOT work for partly constant values
- */
- if (! is_Method_type(ty)) {
- ir_variability variability = get_entity_variability(ent);
- ir_visibility visibility = get_entity_visibility(ent);
-
- if (variability == variability_constant) {
- /* a constant ir_entity, put it on the rdata */
- obst = rdata_obstack;
- }
-
- /* check, wether it is initialized, if yes create data */
- if (variability != variability_uninitialized) {
- if (visibility == visibility_external_visible) {
- obstack_printf(obst, ".globl\t%s\n", ld_name);
- }
- obstack_printf(obst, "\t.type\t%s,@object\n", ld_name);
- obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3);
-
- align = get_type_alignment_bytes(ty);
- TEMPLATE_dump_align(obst, align);
-
- obstack_printf(obst, "%s:\n", ld_name);
-
- if (is_atomic_type(ty)) {
- if (get_entity_visibility(ent) != visibility_external_allocated)
- dump_atomic_init(obst, get_atomic_ent_value(ent));
- }
- else {
- int i, size = 0;
-
- if (ent_is_string_const(ent)) {
- dump_string_cst(obst, ent);
- }
- else if (is_Array_type(ty)) {
- int filler;
-
- /* potential spare values should be already included! */
- for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
- ir_entity *step = get_compound_ent_value_member(ent, i);
- ir_type *stype = get_entity_type(step);
-
- if (get_type_mode(stype)) {
- int align = (get_type_alignment_bits(stype) + 7) >> 3;
- int n = size % align;
-
- if (n > 0) {
- obstack_printf(obst, "\t.zero\t%d\n", align - n);
- size += align - n;
- }
- }
- dump_atomic_init(obst, get_compound_ent_value(ent, i));
- size += get_type_size_bytes(stype);
- }
- filler = get_type_size_bytes(ty) - size;
-
- if (filler > 0)
- obstack_printf(obst, "\t.zero\t%d\n", filler);
- }
- else if (is_compound_type(ty)) {
- ir_node **vals;
- int type_size, j;
-
- /* Compound entities are NOT sorted.
- * The sorting strategy used doesn't work for `value' compound fields nor
- * for partially_constant entities.
- */
-
- /*
- * in the worst case, every ir_entity allocates one byte, so the type
- * size should be equal or bigger the number of fields
- */
- type_size = get_type_size_bytes(ty);
- vals = xcalloc(type_size, sizeof(*vals));
-
- /* collect the values and store them at the offsets */
- for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
- int graph_length, aipos, offset;
- struct arr_info *ai;
- int all_n = 1;
- compound_graph_path *path = get_compound_ent_value_path(ent, i);
-
- /* get the access path to the costant value */
- graph_length = get_compound_graph_path_length(path);
- ai = xcalloc(graph_length, sizeof(struct arr_info));
-
- /* We wanna know how many arrays are on the path to the ir_entity. We also have to know how
- * many elements each array holds to calculate the offset for the ir_entity. */
- for (j = 0; j < graph_length; j++) {
- ir_entity *step = get_compound_graph_path_node(path, j);
- ir_type *step_type = get_entity_type(step);
- int ty_size = (get_type_size_bits(step_type) + 7) >> 3;
- int k, n = 0;
-
- if (is_Array_type(step_type))
- for (k = 0; k < get_array_n_dimensions(step_type); k++)
- n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k)));
- if (n) all_n *= n;
- ai[j].n_elems = n ? all_n + 1 : 0;
- ai[j].visit_cnt = 0;
- ai[j].size = ty_size;
- }
-
- aipos = graph_length - 1;
- if (aipos) aipos--;
-
- for (offset = j = 0; j < graph_length; j++) {
- ir_entity *step = get_compound_graph_path_node(path, j);
- ir_type *step_type = get_entity_type(step);
- int ent_ofs = get_entity_offset_bytes(step);
- int stepsize = 0;
-
- /* add all positive offsets (= offsets in structs) */
- if (ent_ofs >= 0) offset += ent_ofs;
-
- if (j == graph_length - 1) {
- stepsize = (get_type_size_bits(step_type) + 7) >> 3;
-
- /* Search the next free position in vals depending on the information from above (ai). */
- while (vals[offset]) {
- if (ai[aipos].visit_cnt < ai[aipos].n_elems) {
- offset += stepsize;
- ai[aipos].visit_cnt++;
- }
- else
- while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) {
- stepsize = ai[aipos--].size;
- offset += stepsize;
- }
- }
-
- assert(aipos >= 0 && "couldn't store ir_entity");
- vals[offset] = get_compound_ent_value(ent, i);
- }
- }
-
- free(ai);
- }
-
- /* now write them sorted */
- for(i = 0; i < type_size; ) {
- if (vals[i]) {
- dump_atomic_init(obst, vals[i]);
- i += (get_mode_size_bytes(get_irn_mode(vals[i])));
- }
- else {
- /* a gap */
- obstack_printf(obst, "\t.byte\t0\n");
- ++i;
- }
- }
- free(vals);
- }
- else {
- assert(0 && "unsupported type");
- }
- }
- obstack_printf(obst, "\n");
- }
- else if (visibility != visibility_external_allocated) {
- if (visibility == visibility_local) {
- obstack_printf(comm_obstack, "\t.local\t%s\n", ld_name);
- }
-
- /* calculate the alignment */
- align = get_type_alignment_bytes(ty);
- h = highest_bit(align);
-
- if ((1 << h) < align)
- ++h;
- align = (1 << h);
-
- if (align < 1)
- align = 1;
-
- obstack_printf(comm_obstack, "\t.comm\t%s,%d,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3, align);
- }
- }
-}
-
-/*
- * Dumps declarations of global variables and the initialization code.
- */
-void TEMPLATE_dump_globals(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack)
-{
- ir_type *gt = get_glob_type();
- int i, n = get_class_n_members(gt);
-
- for (i = 0; i < n; i++)
- dump_global(rdata_obstack, data_obstack, comm_obstack, get_class_member(gt, i));
-}
-
-/************************************************************************/
-
-void TEMPLATE_gen_decls(FILE *out) {
- struct obstack rodata, data, comm;
- int size;
- char *cp;
-
- obstack_init(&rodata);
- obstack_init(&data);
- obstack_init(&comm);
-
- TEMPLATE_dump_globals(&rodata, &data, &comm);
-
- size = obstack_object_size(&data);
- cp = obstack_finish(&data);
- if (size > 0) {
- fprintf(out, "\t.data\n");
- fwrite(cp, 1, size, out);
- }
-
- size = obstack_object_size(&rodata);
- cp = obstack_finish(&rodata);
- if (size > 0) {
- fprintf(out, "\t.section\t.rodata\n");
- fwrite(cp, 1, size, out);
- }
-
- size = obstack_object_size(&comm);
- cp = obstack_finish(&comm);
- if (size > 0) {
- fprintf(out, "\t.common\n");
- fwrite(cp, 1, size, out);
- }
-
- obstack_free(&rodata, NULL);
- obstack_free(&data, NULL);
- obstack_free(&comm, NULL);
-}
+++ /dev/null
-#ifndef _TEMPLATE_GEN_DECLS_H_
-#define _TEMPLATE_GEN_DECLS_H_
-
-/**
- * Generate all entities.
- */
-void TEMPLATE_gen_decls(FILE *out);
-
-#endif /* _TEMPLATE_GEN_DECLS_H_ */
* |_|
***********************************************************************************/
-/**
- * Returns a string containing the names of all registers within the limited bitset
- */
-static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- char *p = buf;
- int size = 0;
- int i, cnt;
-
- req->limited(NULL, bs);
-
- for (i = 0; i < req->cls->n_regs; i++) {
- if (bitset_is_set(bs, i)) {
- cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
- if (cnt < 0) {
- fprintf(stderr, "dumper problem, exiting\n");
- exit(1);
- }
-
- p += cnt;
- size += cnt;
-
- if (size >= max)
- break;
- }
- }
-
- return buf;
-}
-
/**
* Dumps the register requirements for either in or out.
*/
-static void dump_reg_req(FILE *F, ir_node *n, const TEMPLATE_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
+ int inout) {
char *dir = inout ? "out" : "in";
int max = inout ? get_TEMPLATE_n_res(n) : get_irn_arity(n);
- char *buf = alloca(1024);
+ char buf[1024];
int i;
- memset(buf, 0, 1024);
+ memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
- if (reqs[i]->req.type == arch_register_req_type_none) {
+ if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
- if (reqs[i]->req.type & arch_register_req_type_normal) {
- fprintf(F, " %s", reqs[i]->req.cls->name);
+ if (reqs[i]->type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->cls->name);
}
- if (reqs[i]->req.type & arch_register_req_type_limited) {
- fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ if (reqs[i]->type & arch_register_req_type_limited) {
+ fprintf(F, " %s",
+ arch_register_req_format(buf, sizeof(buf), reqs[i], n));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
- ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
- ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->other_different));
}
fprintf(F, "\n");
}
fprintf(F, "\n");
- }
- else {
+ } else {
fprintf(F, "%sreq = N/A\n", dir);
}
}
int bad = 0;
int i;
TEMPLATE_attr_t *attr;
- const TEMPLATE_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t **slots;
switch (reason) {
/**
* Returns the argument register requirements of a TEMPLATE node.
*/
-const TEMPLATE_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
return attr->in_req;
}
/**
* Returns the result register requirements of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
return attr->out_req;
}
/**
* Returns the argument register requirement at position pos of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
-void set_TEMPLATE_req_out(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
+void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
attr->out_req[pos] = req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_TEMPLATE_req_in(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
+void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
attr->in_req[pos] = req;
}
return attr->n_res;
}
+/**
+ * Initializes the nodes attributes.
+ */
+void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
+ const arch_register_req_t **in_reqs,
+ const arch_register_req_t **out_reqs,
+ const be_execution_unit_t ***execution_units,
+ int n_res, unsigned latency)
+{
+ TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+
+ attr->flags = flags;
+ attr->out_req = out_reqs;
+ attr->in_req = in_reqs;
+ attr->n_res = n_res;
+ memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
+}
/***************************************************************************************
* _ _ _
/**
* Returns the argument register requirements of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node);
+const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node);
/**
* Returns the result register requirements of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node);
+const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos);
+const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos);
/**
* Returns the result register requirements of an TEMPLATE node.
*/
-const TEMPLATE_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos);
+const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
-void set_TEMPLATE_req_out(ir_node *node, const TEMPLATE_register_req_t *req, int pos);
+void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the IN register requirements at position pos.
*/
-void set_TEMPLATE_req_in(ir_node *node, const TEMPLATE_register_req_t *req, int pos);
+void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the register flag of an TEMPLATE node.
#include "../bearch.h"
-typedef struct _TEMPLATE_register_req_t {
- const arch_register_req_t req;
- int same_pos; /**< in case of "should be same" we need to remember the pos to get the irn */
- int different_pos; /**< in case of "should be different" we need to remember the pos to get the irn */
-} TEMPLATE_register_req_t;
-
-
typedef struct _TEMPLATE_attr_t {
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
int n_res; /**< number of results for this node */
- const TEMPLATE_register_req_t **in_req; /**< register requirements for arguments */
- const TEMPLATE_register_req_t **out_req; /**< register requirements for results */
+ const arch_register_req_t **in_req; /**< register requirements for arguments */
+ const arch_register_req_t **out_req; /**< register requirements for results */
/* must be last, dynamically allocated */
const arch_register_t *slots[1]; /**< register slots for assigned registers */
# $Id$
# This is a template specification for the Firm-Backend
+$new_emit_syntax = 1;
+
# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
$arch = "TEMPLATE";
-# this strings mark the beginning and the end of a comment in emit
-$comment_string = "/*";
-$comment_string_end = "*/";
-
# The node description is done as a perl hash initializer with the
# following structure:
#
# %nodes = (
#
# <op-name> => {
-# "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
-# "irn_flags" => "R|N|I"
-# "arity" => "0|1|2|3 ... |variable|dynamic|any",
-# "state" => "floats|pinned|mem_pinned|exc_pinned",
-# "args" => [
-# { "type" => "type 1", "name" => "name 1" },
-# { "type" => "type 2", "name" => "name 2" },
+# op_flags => "N|L|C|X|I|F|Y|H|c|K",
+# irn_flags => "R|N|I"
+# arity => "0|1|2|3 ... |variable|dynamic|any",
+# state => "floats|pinned|mem_pinned|exc_pinned",
+# args => [
+# { type => "type 1", name => "name 1" },
+# { type => "type 2", name => "name 2" },
# ...
# ],
-# "comment" => "any comment for constructor",
-# "reg_req" => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
-# "cmp_attr" => "c source code for comparing node attributes",
-# "emit" => "emit code with templates",
-# "rd_constructor" => "c source code which constructs an ir_node"
+# comment => "any comment for constructor",
+# reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
+# cmp_attr => "c source code for comparing node attributes",
+# emit => "emit code with templates",
+# rd_constructor => "c source code which constructs an ir_node"
# },
#
# ... # (all nodes you need to describe)
# 4 - ignore (do not assign this register)
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
%reg_classes = (
- "general_purpose" => [
- { "name" => "r0", "type" => 1 },
- { "name" => "r1", "type" => 1 },
- { "name" => "r2", "type" => 1 },
- { "name" => "r3", "type" => 1 },
- { "name" => "r4", "type" => 1 },
- { "name" => "r5", "type" => 1 },
- { "name" => "r6", "type" => 6 }, # this is our stackpointer
- { "name" => "r7", "type" => 6 }, # this is out basepointer
- { "name" => "r8", "type" => 2 },
- { "name" => "r9", "type" => 2 },
- { "name" => "r10", "type" => 2 },
- { "name" => "r11", "type" => 2 },
- { "name" => "r12", "type" => 2 },
- { "name" => "r13", "type" => 2 },
- { "name" => "r14", "type" => 2 },
- { "name" => "r15", "type" => 2 },
- { "mode" => "mode_P" }
- ],
- "floating_point" => [
- { "name" => "f0", "type" => 1 },
- { "name" => "f1", "type" => 1 },
- { "name" => "f2", "type" => 1 },
- { "name" => "f3", "type" => 1 },
- { "name" => "f4", "type" => 1 },
- { "name" => "f5", "type" => 1 },
- { "name" => "f6", "type" => 1 },
- { "name" => "f7", "type" => 1 },
- { "name" => "f8", "type" => 1 },
- { "name" => "f9", "type" => 1 },
- { "name" => "f10", "type" => 1 },
- { "name" => "f11", "type" => 1 },
- { "name" => "f12", "type" => 1 },
- { "name" => "f13", "type" => 1 },
- { "name" => "f14", "type" => 1 },
- { "name" => "f15", "type" => 1 },
- { "mode" => "mode_D" }
- ]
+ general_purpose => [
+ { name => "r0", type => 1 },
+ { name => "r1", type => 1 },
+ { name => "r2", type => 1 },
+ { name => "r3", type => 1 },
+ { name => "r4", type => 1 },
+ { name => "r5", type => 1 },
+ { name => "r6", type => 1 },
+ { name => "r7", type => 2 },
+ { name => "r8", type => 2 },
+ { name => "r9", type => 2 },
+ { name => "r10", type => 2 },
+ { name => "r11", type => 2 },
+ { name => "r12", type => 2 },
+ { name => "r13", type => 2 },
+ { name => "sp", realname => "r14", type => 4 }, # this is our stackpointer
+ { name => "bp", realname => "r15", type => 4 }, # this is out basepointer
+ { mode => "mode_Iu" }
+ ],
+ floating_point => [
+ { name => "f0", type => 1 },
+ { name => "f1", type => 1 },
+ { name => "f2", type => 1 },
+ { name => "f3", type => 1 },
+ { name => "f4", type => 1 },
+ { name => "f5", type => 1 },
+ { name => "f6", type => 1 },
+ { name => "f7", type => 1 },
+ { name => "f8", type => 1 },
+ { name => "f9", type => 1 },
+ { name => "f10", type => 1 },
+ { name => "f11", type => 1 },
+ { name => "f12", type => 1 },
+ { name => "f13", type => 1 },
+ { name => "f14", type => 1 },
+ { name => "f15", type => 1 },
+ { mode => "mode_D" }
+ ]
); # %reg_classes
+%emit_templates = (
+ S1 => "${arch}_emit_source_register(env, node, 0);",
+ S2 => "${arch}_emit_source_register(env, node, 1);",
+ S3 => "${arch}_emit_source_register(env, node, 2);",
+ S4 => "${arch}_emit_source_register(env, node, 3);",
+ S5 => "${arch}_emit_source_register(env, node, 4);",
+ S6 => "${arch}_emit_source_register(env, node, 5);",
+ D1 => "${arch}_emit_dest_register(env, node, 0);",
+ D2 => "${arch}_emit_dest_register(env, node, 1);",
+ D3 => "${arch}_emit_dest_register(env, node, 2);",
+ D4 => "${arch}_emit_dest_register(env, node, 3);",
+ D5 => "${arch}_emit_dest_register(env, node, 4);",
+ D6 => "${arch}_emit_dest_register(env, node, 5);",
+ C => "${arch}_emit_immediate(env, node);"
+);
+
#--------------------------------------------------#
# _ #
# (_) #
# commutative operations
-"Add" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. add %S1, %S2, %D1\t\t\t/* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
+Add => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct Add: Add(a, b) = Add(b, a) = a + b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. add %S1, %S2, %D1'
},
-"Add_i" => {
- "irn_flags" => "R",
- "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. add %S1, %C, %D1\t\t\t/* Add(%C, %S1) -> %D1, (%A1, const) */'
+Add_i => {
+ irn_flags => "R",
+ comment => "construct Add: Add(a, const) = Add(const, a) = a + const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. add %S1, %C, %D1'
},
-"Mul" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" =>'. mul %S1, %S2, %D1\t\t\t/* Mul(%S1, %S2) -> %D1, (%A1, %A2) */'
+Mul => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit =>'. mul %S1, %S2, %D1'
},
-"Mul_i" => {
- "irn_flags" => "R",
- "comment" => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. mul %S1, %C, %D1\t\t\t/* signed Mul(%C, %S1) -> %D1, (%A1, const) */'
+Mul_i => {
+ irn_flags => "R",
+ comment => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. mul %S1, %C, %D1'
},
-"And" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct And: And(a, b) = And(b, a) = a AND b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. and %S1, %S2, %D1\t\t\t/* And(%S1, %S2) -> %D1, (%A1, %A2) */'
+And => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct And: And(a, b) = And(b, a) = a AND b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. and %S1, %S2, %D1'
},
-"And_i" => {
- "irn_flags" => "R",
- "comment" => "construct And: And(a, const) = And(const, a) = a AND const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. and %S1, %C, %D1\t\t\t/* And(%C, %S1) -> %D1, (%A1, const) */'
+And_i => {
+ irn_flags => "R",
+ comment => "construct And: And(a, const) = And(const, a) = a AND const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. and %S1, %C, %D1'
},
-"Or" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. or %S1, %S2, %D1\t\t\t/* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
+Or => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct Or: Or(a, b) = Or(b, a) = a OR b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. or %S1, %S2, %D1'
},
-"Or_i" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. or %S1, %C, %D1\t\t\t/* Or(%C, %S1) -> %D1, (%A1, const) */'
+Or_i => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct Or: Or(a, const) = Or(const, a) = a OR const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. or %S1, %C, %D1'
},
-"Eor" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. xor %S1, %S2, %D1\t\t\t/* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
+Eor => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. xor %S1, %S2, %D1'
},
-"Eor_i" => {
- "irn_flags" => "R",
- "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. xor %S1, %C, %D1\t\t\t/* Xor(%C, %S1) -> %D1, (%A1, const) */'
+Eor_i => {
+ irn_flags => "R",
+ comment => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. xor %S1, %C, %D1'
},
# not commutative operations
-"Sub" => {
- "irn_flags" => "R",
- "comment" => "construct Sub: Sub(a, b) = a - b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. sub %S1, %S2, %D1\t\t\t/* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
+Sub => {
+ irn_flags => "R",
+ comment => "construct Sub: Sub(a, b) = a - b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. sub %S1, %S2, %D1'
},
-"Sub_i" => {
- "irn_flags" => "R",
- "comment" => "construct Sub: Sub(a, const) = a - const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. subl %S1, %C, %D1\t\t\t/* Sub(%S1, %C) -> %D1, (%A1, const) */'
+Sub_i => {
+ irn_flags => "R",
+ comment => "construct Sub: Sub(a, const) = a - const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. subl %S1, %C, %D1'
},
-"Shl" => {
- "irn_flags" => "R",
- "comment" => "construct Shl: Shl(a, b) = a << b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. shl %S1, %S2, %D1\t\t\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
+Shl => {
+ irn_flags => "R",
+ comment => "construct Shl: Shl(a, b) = a << b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. shl %S1, %S2, %D1'
},
-"Shl_i" => {
- "irn_flags" => "R",
- "comment" => "construct Shl: Shl(a, const) = a << const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. shl %S1, %C, %D1\t\t\t/* Shl(%S1, %C) -> %D1, (%A1, const) */'
+Shl_i => {
+ irn_flags => "R",
+ comment => "construct Shl: Shl(a, const) = a << const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. shl %S1, %C, %D1'
},
-"Shr" => {
- "irn_flags" => "R",
- "comment" => "construct Shr: Shr(a, b) = a >> b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. shr %S2, %D1\t\t\t/* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
+Shr => {
+ irn_flags => "R",
+ comment => "construct Shr: Shr(a, b) = a >> b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "in_r1" ] },
+ emit => '. shr %S2, %D1'
},
-"Shr_i" => {
- "irn_flags" => "R",
- "comment" => "construct Shr: Shr(a, const) = a >> const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. shr %S1, %C, %D1\t\t\t/* Shr(%S1, %C) -> %D1, (%A1, const) */'
+Shr_i => {
+ irn_flags => "R",
+ comment => "construct Shr: Shr(a, const) = a >> const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. shr %S1, %C, %D1'
},
-"RotR" => {
- "irn_flags" => "R",
- "comment" => "construct RotR: RotR(a, b) = a ROTR b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. ror %S1, %S2, %D1\t\t\t/* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
+RotR => {
+ irn_flags => "R",
+ comment => "construct RotR: RotR(a, b) = a ROTR b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. ror %S1, %S2, %D1'
},
-"RotL" => {
- "irn_flags" => "R",
- "comment" => "construct RotL: RotL(a, b) = a ROTL b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. rol %S1, %S2, %D1\t\t\t/* RotL(%S1, %S2) -> %D1, (%A1, %A2) */'
+RotL => {
+ irn_flags => "R",
+ comment => "construct RotL: RotL(a, b) = a ROTL b",
+ reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. rol %S1, %S2, %D1'
},
-"RotL_i" => {
- "irn_flags" => "R",
- "comment" => "construct RotL: RotL(a, const) = a ROTL const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. rol %S1, %C, %D1\t\t\t/* RotL(%S1, %C) -> %D1, (%A1, const) */'
+RotL_i => {
+ irn_flags => "R",
+ comment => "construct RotL: RotL(a, const) = a ROTL const",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. rol %S1, %C, %D1'
},
-"Minus" => {
- "irn_flags" => "R",
- "comment" => "construct Minus: Minus(a) = -a",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. neg %S1, %D1\t\t\t/* Neg(%S1) -> %D1, (%A1) */'
+Minus => {
+ irn_flags => "R",
+ comment => "construct Minus: Minus(a) = -a",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. neg %S1, %D1'
},
-"Inc" => {
- "irn_flags" => "R",
- "comment" => "construct Increment: Inc(a) = a++",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. inc %S1, %D1\t\t\t/* Inc(%S1) -> %D1, (%A1) */'
+Inc => {
+ irn_flags => "R",
+ comment => "construct Increment: Inc(a) = a++",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. inc %S1, %D1'
},
-"Dec" => {
- "irn_flags" => "R",
- "comment" => "construct Decrement: Dec(a) = a--",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. dec %S1, %D1\t\t\t/* Dec(%S1) -> %D1, (%A1) */'
+Dec => {
+ irn_flags => "R",
+ comment => "construct Decrement: Dec(a) = a--",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. dec %S1, %D1'
},
-"Not" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Not: Not(a) = !a",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. not %S1, %D1\t\t\t/* Not(%S1) -> %D1, (%A1) */'
+Not => {
+ arity => 1,
+ remat => 1,
+ comment => "construct Not: Not(a) = !a",
+ reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
+ emit => '. not %S1, %D1'
},
# other operations
-"Const" => {
- "op_flags" => "c",
- "irn_flags" => "R",
- "comment" => "represents an integer constant",
- "reg_req" => { "out" => [ "general_purpose" ] },
- "emit" => '. mov %C, %D1\t\t\t/* Mov Const into register */',
- "cmp_attr" =>
+Const => {
+ op_flags => "c",
+ irn_flags => "R",
+ comment => "represents an integer constant",
+ reg_req => { out => [ "general_purpose" ] },
+ emit => '. mov %C, %D1',
+ cmp_attr =>
'
/* TODO: compare Const attributes */
return 1;
# Load / Store
-"Load" => {
- "op_flags" => "L|F",
- "irn_flags" => "R",
- "state" => "exc_pinned",
- "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
- "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] },
- "emit" => '. mov %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1, (%A1) */'
+Load => {
+ op_flags => "L|F",
+ irn_flags => "R",
+ state => "exc_pinned",
+ comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ reg_req => { in => [ "general_purpose", "none" ], out => [ "general_purpose" ] },
+ emit => '. mov (%S1), %D1'
},
-"Store" => {
- "op_flags" => "L|F",
- "irn_flags" => "R",
- "state" => "exc_pinned",
- "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] },
- "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+Store => {
+ op_flags => "L|F",
+ irn_flags => "R",
+ state => "exc_pinned",
+ comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ reg_req => { in => [ "general_purpose", "general_purpose", "none" ] },
+ emit => '. movl %S2, (%S1)'
},
#--------------------------------------------------------#
# commutative operations
-"fAdd" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" => '. fadd %S1, %S2, %D1\t\t\t/* FP Add(%S1, %S2) -> %D1 */'
+fAdd => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit => '. fadd %S1, %S2, %D1'
},
-"fMul" => {
- "op_flags" => "C",
- "comment" => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" =>'. fmul %S1, %S2, %D1\t\t\t/* FP Mul(%S1, %S2) -> %D1 */'
+fMul => {
+ op_flags => "C",
+ comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit =>'. fmul %S1, %S2, %D1'
},
-"fMax" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" =>'. fmax %S1, %S2, %D1\t\t\t/* FP Max(%S1, %S2) -> %D1 */'
+fMax => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit =>'. fmax %S1, %S2, %D1'
},
-"fMin" => {
- "op_flags" => "C",
- "irn_flags" => "R",
- "comment" => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" =>'. fmin %S1, %S2, %D1\t\t\t/* FP Min(%S1, %S2) -> %D1 */'
+fMin => {
+ op_flags => "C",
+ irn_flags => "R",
+ comment => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit =>'. fmin %S1, %S2, %D1'
},
# not commutative operations
-"fSub" => {
- "irn_flags" => "R",
- "comment" => "construct FP Sub: Sub(a, b) = a - b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" => '. fsub %S1, %S2, %D1\t\t\t/* FP Sub(%S1, %S2) -> %D1 */'
+fSub => {
+ irn_flags => "R",
+ comment => "construct FP Sub: Sub(a, b) = a - b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit => '. fsub %S1, %S2, %D1'
},
-"fDiv" => {
- "comment" => "construct FP Div: Div(a, b) = a / b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] },
- "emit" => '. fdiv %S1, %S2, %D1\t\t\t/* FP Div(%S1, %S2) -> %D1 */'
+fDiv => {
+ comment => "construct FP Div: Div(a, b) = a / b",
+ reg_req => { in => [ "floating_point", "floating_point" ], out => [ "floating_point" ] },
+ emit => '. fdiv %S1, %S2, %D1'
},
-"fMinus" => {
- "irn_flags" => "R",
- "comment" => "construct FP Minus: Minus(a) = -a",
- "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] },
- "emit" => '. fneg %S1, %D1\t\t\t/* FP Minus(%S1) -> %D1 */'
+fMinus => {
+ irn_flags => "R",
+ comment => "construct FP Minus: Minus(a) = -a",
+ reg_req => { in => [ "floating_point" ], out => [ "floating_point" ] },
+ emit => '. fneg %S1, %D1'
},
# other operations
-"fConst" => {
- "op_flags" => "c",
- "irn_flags" => "R",
- "comment" => "represents a FP constant",
- "reg_req" => { "out" => [ "floating_point" ] },
- "emit" => '. fmov %C, %D1\t\t\t/* Mov fConst into register */',
- "cmp_attr" =>
+fConst => {
+ op_flags => "c",
+ irn_flags => "R",
+ comment => "represents a FP constant",
+ reg_req => { out => [ "floating_point" ] },
+ emit => '. fmov %C, %D1',
+ cmp_attr =>
'
/* TODO: compare fConst attributes */
return 1;
# Load / Store
-"fLoad" => {
- "op_flags" => "L|F",
- "irn_flags" => "R",
- "state" => "exc_pinned",
- "comment" => "construct FP Load: Load(ptr, mem) = LD ptr",
- "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] },
- "emit" => '. fmov %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */'
-},
-
-"fStore" => {
- "op_flags" => "L|F",
- "irn_flags" => "R",
- "state" => "exc_pinned",
- "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "general_purpose", "floating_point", "none" ] },
- "emit" => '. fmov %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+fLoad => {
+ op_flags => "L|F",
+ irn_flags => "R",
+ state => "exc_pinned",
+ comment => "construct FP Load: Load(ptr, mem) = LD ptr",
+ reg_req => { in => [ "general_purpose", "none" ], out => [ "floating_point" ] },
+ emit => '. fmov (%S1), %D1'
+},
+
+fStore => {
+ op_flags => "L|F",
+ irn_flags => "R",
+ state => "exc_pinned",
+ comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ reg_req => { in => [ "general_purpose", "floating_point", "none" ] },
+ emit => '. fmov %S2, (%S1)'
},
); # end of %nodes
-/**
- * Creates an TEMPLATE RotL.
- *
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created TEMPLATE RotL node
- */
-static ir_node *gen_RotL(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_TEMPLATE_RotL(env->dbg, env->irg, env->block, op1, op2, env->mode);
-}
-
-
-
/**
* Transforms a Minus node.
*
#include "../be.h"
#include "../beabi.h"
#include "../bemodule.h"
+#include "../begnuas.h"
#include "bearch_TEMPLATE_t.h"
#include "TEMPLATE_new_nodes.h" /* TEMPLATE nodes interface */
#include "gen_TEMPLATE_regalloc_if.h" /* the generated interface (register type and class defenitions) */
-#include "TEMPLATE_gen_decls.h" /* interface declaration emitter */
#include "TEMPLATE_transform.h"
#include "TEMPLATE_emitter.h"
#include "TEMPLATE_map_regs.h"
-#define DEBUG_MODULE "firm.be.TEMPLATE.isa"
-
/* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
static set *cur_reg_set = NULL;
* |___/
**************************************************/
-static ir_node *my_skip_proj(const ir_node *n) {
- while (is_Proj(n))
- n = get_Proj_pred(n);
- return (ir_node *)n;
-}
-
/**
* Return register requirements for a TEMPLATE node.
* If the node returns a tuple (mode_T) then the proj's
* will be asked for this information.
*/
-static const arch_register_req_t *TEMPLATE_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
- const TEMPLATE_register_req_t *irn_req;
+static const
+arch_register_req_t *TEMPLATE_get_irn_reg_req(const void *self,
+ const ir_node *node, int pos) {
long node_pos = pos == -1 ? 0 : pos;
- ir_mode *mode = get_irn_mode(irn);
- FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
+ ir_mode *mode = get_irn_mode(node);
if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
- return NULL;
+ return arch_no_register_req;
}
- DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
-
- if (is_Proj(irn)) {
+ if (is_Proj(node)) {
/* in case of a proj, we need to get the correct OUT slot */
/* of the node corresponding to the proj number */
if (pos == -1) {
- node_pos = TEMPLATE_translate_proj_pos(irn);
- }
- else {
+ node_pos = TEMPLATE_translate_proj_pos(node);
+ } else {
node_pos = pos;
}
- irn = my_skip_proj(irn);
-
- DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+ node = skip_Proj_const(node);
}
/* get requirements for our own nodes */
- if (is_TEMPLATE_irn(irn)) {
+ if (is_TEMPLATE_irn(node)) {
+ const arch_register_req_t *req;
if (pos >= 0) {
- irn_req = get_TEMPLATE_in_req(irn, pos);
- }
- else {
- irn_req = get_TEMPLATE_out_req(irn, node_pos);
+ req = get_TEMPLATE_in_req(node, pos);
+ } else {
+ req = get_TEMPLATE_out_req(node, node_pos);
}
- DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
+ assert(req != NULL);
- memcpy(req, &(irn_req->req), sizeof(*req));
-
- if (arch_register_req_is(&(irn_req->req), should_be_same)) {
- assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
- req->other_same = get_irn_n(irn, irn_req->same_pos);
- }
-
- if (arch_register_req_is(&(irn_req->req), should_be_different)) {
- assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
- req->other_different = get_irn_n(irn, irn_req->different_pos);
- }
- }
- /* get requirements for FIRM nodes */
- else {
- /* treat Phi like Const with default requirements */
- if (is_Phi(irn)) {
- DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
-
- if (mode_is_float(mode)) {
- memcpy(req, &(TEMPLATE_default_req_TEMPLATE_floating_point.req), sizeof(*req));
- }
- else if (mode_is_int(mode) || mode_is_reference(mode)) {
- memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose.req), sizeof(*req));
- }
- else if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
- return NULL;
- }
- else {
- assert(0 && "unsupported Phi-Mode");
- }
- }
- else {
- DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
- req = NULL;
- }
+ return req;
}
- return req;
+ /* unknowns should be transformed already */
+ assert(!is_Unknown(node));
+
+ return arch_no_register_req;
}
static void TEMPLATE_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
if (is_Proj(irn)) {
pos = TEMPLATE_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj(irn);
}
if (is_TEMPLATE_irn(irn)) {
if (is_Proj(irn)) {
pos = TEMPLATE_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
}
if (is_TEMPLATE_irn(irn)) {
}
static arch_irn_class_t TEMPLATE_classify(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_cfop(irn)) {
return arch_irn_class_branch;
}
static arch_irn_flags_t TEMPLATE_get_flags(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_TEMPLATE_irn(irn)) {
return get_TEMPLATE_flags(irn);
return 0;
}
-static ir_entity *TEMPLATE_get_frame_entity(const void *self, const ir_node *irn) {
+static ir_entity *TEMPLATE_get_frame_entity(const void *self, const ir_node *node) {
/* TODO: return the ir_entity assigned to the frame */
return NULL;
}
-static void TEMPLATE_set_frame_entity(const void *self, const ir_node *irn, ir_entity *ent) {
+static void TEMPLATE_set_frame_entity(const void *self, ir_node *node, ir_entity *ent) {
/* TODO: set the ir_entity assigned to the frame */
}
/* Some stuff you need to do after scheduling but before register allocation */
}
-static void TEMPLATE_before_ra(void *self, be_irg_t *birg) {
+static void TEMPLATE_before_ra(void *self) {
/* Some stuff you need to do after scheduling but before register allocation */
}
static void TEMPLATE_emit_and_done(void *self) {
TEMPLATE_code_gen_t *cg = self;
ir_graph *irg = cg->irg;
- FILE *out = cg->isa->out;
- if (cg->emit_decls) {
- TEMPLATE_gen_decls(out);
- cg->emit_decls = 0;
- }
-
- TEMPLATE_gen_routine(out, irg, cg);
+ TEMPLATE_gen_routine(cg, irg);
cur_reg_set = NULL;
free(self);
}
-static void *TEMPLATE_cg_init(const be_irg_t *birg);
+static void *TEMPLATE_cg_init(be_irg_t *birg);
static const arch_code_generator_if_t TEMPLATE_code_gen_if = {
TEMPLATE_cg_init,
+ NULL, /* before abi introduce hook */
TEMPLATE_prepare_graph,
+ NULL, /* spill hook */
TEMPLATE_before_sched, /* before scheduling hook */
TEMPLATE_before_ra, /* before register allocation hook */
TEMPLATE_after_ra, /* after register allocation hook */
/**
* Initializes the code generator.
*/
-static void *TEMPLATE_cg_init(const be_irg_t *birg) {
+static void *TEMPLATE_cg_init(be_irg_t *birg) {
TEMPLATE_isa_t *isa = (TEMPLATE_isa_t *)birg->main_env->arch_env->isa;
TEMPLATE_code_gen_t *cg = xmalloc(sizeof(*cg));
cg->birg = birg;
FIRM_DBG_REGISTER(cg->mod, "firm.be.TEMPLATE.cg");
- isa->num_codegens++;
-
- if (isa->num_codegens > 1)
- cg->emit_decls = 0;
- else
- cg->emit_decls = 1;
-
cur_reg_set = cg->reg_set;
TEMPLATE_irn_ops.cg = cg;
*****************************************************************/
static TEMPLATE_isa_t TEMPLATE_isa_template = {
- &TEMPLATE_isa_if,
- &TEMPLATE_general_purpose_regs[REG_R6],
- &TEMPLATE_general_purpose_regs[REG_R7],
- -1,
- 0
+ {
+ &TEMPLATE_isa_if, /* isa interface implementation */
+ &TEMPLATE_general_purpose_regs[REG_SP], /* stack pointer register */
+ &TEMPLATE_general_purpose_regs[REG_BP], /* base pointer register */
+ -1, /* stack direction */
+ NULL, /* main environment */
+ },
+ {}, /* emitter environment */
};
/**
* Initializes the backend ISA and opens the output file.
*/
static void *TEMPLATE_init(FILE *outfile) {
- static int inited = 0;
+ static int run_once = 0;
TEMPLATE_isa_t *isa;
- if(inited)
+ if(run_once)
return NULL;
+ run_once = 1;
isa = xcalloc(1, sizeof(*isa));
memcpy(isa, &TEMPLATE_isa_template, sizeof(*isa));
- isa->out = outfile;
+ be_emit_init_env(&isa->emit, outfile);
TEMPLATE_register_init(isa);
TEMPLATE_create_opcodes();
- inited = 1;
-
return isa;
}
* Closes the output file and frees the ISA structure.
*/
static void TEMPLATE_done(void *self) {
+ TEMPLATE_isa_t *isa = self;
+
+ /* emit now all global declarations */
+ be_gas_emit_decls(&isa->emit, isa->arch_isa.main_env);
+
+ be_emit_destroy_env(&isa->emit);
free(self);
}
* @return The between type of for that call.
*/
static ir_type *TEMPLATE_get_between_type(void *self) {
- TEMPLATE_abi_env_t *env = self;
+ //TEMPLATE_abi_env_t *env = self;
static ir_type *between_type = NULL;
static ir_entity *old_bp_ent = NULL;
/* Build the epilog */
static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map) {
- TEMPLATE_abi_env_t *env = self;
+ //TEMPLATE_abi_env_t *env = self;
}
static const be_abi_callbacks_t TEMPLATE_abi_callbacks = {
#include "bearch_TEMPLATE.h"
#include "TEMPLATE_nodes_attr.h"
#include "../be.h"
+#include "../beemitter.h"
#include "set.h"
typedef struct _TEMPLATE_isa_t TEMPLATE_isa_t;
ir_graph *irg; /**< current irg */
const arch_env_t *arch_env; /**< the arch env */
set *reg_set; /**< set to memorize registers for FIRM nodes (e.g. phi) */
- int emit_decls; /**< flag indicating if decls were already emitted */
TEMPLATE_isa_t *isa; /**< the isa instance */
const be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */
DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */
} TEMPLATE_code_gen_t;
struct _TEMPLATE_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. */
- int num_codegens;
- FILE *out; /**< output file */
+ arch_isa_t arch_isa; /**< must be derived from arch_isa */
+ be_emit_env_t emit; /**< emit datastructure */
};
ir_node **projs;
int n_projs;
int block_nr;
- int default_block_num;
+ int default_block_num = -1;
block_nr = get_irn_node_nr(irn);
n_projs = get_arm_n_projs(irn);
projs[get_Proj_proj(proj)] = proj;
}
+ assert(default_block_num >= 0);
// CMP %1S, n_projs - 1
// BHI default
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef HAVE_MALLOC_H
#include "arm_nodes_attr.h"
#include "arm_new_nodes.h"
-#include "gen_arm_regalloc_if.h"
+#include "gen_arm_regalloc_if_t.h"
#include "../beabi.h"
#include "bearch_arm_t.h"
* |_|
***********************************************************************************/
-/**
- * Returns a string containing the names of all registers within the limited bitset
- */
-static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- char *p = buf;
- int size = 0;
- int i, cnt;
-
- req->limited(NULL, bs);
-
- for (i = 0; i < req->cls->n_regs; i++) {
- if (bitset_is_set(bs, i)) {
- cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
- if (cnt < 0) {
- fprintf(stderr, "dumper problem, exiting\n");
- exit(1);
- }
-
- p += cnt;
- size += cnt;
-
- if (size >= max)
- break;
- }
- }
-
- return buf;
-}
-
/**
* Dumps the register requirements for either in or out.
*/
-static void dump_reg_req(FILE *F, ir_node *n, const arm_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, const ir_node *node,
+ const arch_register_req_t **reqs, int inout) {
char *dir = inout ? "out" : "in";
- int max = inout ? get_arm_n_res(n) : get_irn_arity(n);
- char *buf = alloca(1024);
+ int max = inout ? get_arm_n_res(node) : get_irn_arity(node);
+ char buf[1024];
int i;
- memset(buf, 0, 1024);
+ memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
- if (reqs[i]->req.type == arch_register_req_type_none) {
+ if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
- if (reqs[i]->req.type & arch_register_req_type_normal) {
- fprintf(F, " %s", reqs[i]->req.cls->name);
+ if (reqs[i]->type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->cls->name);
}
- if (reqs[i]->req.type & arch_register_req_type_limited) {
- fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ if (reqs[i]->type & arch_register_req_type_limited) {
+ fprintf(F, " %s",
+ arch_register_req_format(buf, sizeof(buf), reqs[i], node));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
- ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(node, reqs[i]->other_same));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
- ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(node, reqs[i]->other_different));
}
fprintf(F, "\n");
}
fprintf(F, "\n");
- }
- else {
+ } else {
fprintf(F, "%sreq = N/A\n", dir);
}
}
int bad = 0;
int i;
arm_attr_t *attr = get_arm_attr(n);
- const arm_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t **slots;
arm_shift_modifier mod;
/**
* Returns the argument register requirements of a arm node.
*/
-const arm_register_req_t **get_arm_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_arm_in_req_all(const ir_node *node) {
arm_attr_t *attr = get_arm_attr(node);
return attr->in_req;
}
/**
* Returns the result register requirements of an arm node.
*/
-const arm_register_req_t **get_arm_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_arm_out_req_all(const ir_node *node) {
arm_attr_t *attr = get_arm_attr(node);
return attr->out_req;
}
/**
* Returns the argument register requirement at position pos of an arm node.
*/
-const arm_register_req_t *get_arm_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos) {
arm_attr_t *attr = get_arm_attr(node);
return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an arm node.
*/
-const arm_register_req_t *get_arm_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos) {
arm_attr_t *attr = get_arm_attr(node);
return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
-void set_arm_req_out(ir_node *node, const arm_register_req_t *req, int pos) {
+void set_arm_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
arm_attr_t *attr = get_arm_attr(node);
attr->out_req[pos] = req;
}
/**
* Sets the complete OUT requirements of node.
*/
-void set_arm_req_out_all(ir_node *node, const arm_register_req_t **reqs) {
+void set_arm_req_out_all(ir_node *node, const arch_register_req_t **reqs) {
arm_attr_t *attr = get_arm_attr(node);
attr->out_req = reqs;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_arm_req_in(ir_node *node, const arm_register_req_t *req, int pos) {
+void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
arm_attr_t *attr = get_arm_attr(node);
attr->in_req[pos] = req;
}
}
/* Set the ARM machine node attributes to default values. */
-void init_arm_attributes(ir_node *node, int flags, const arm_register_req_t ** in_reqs,
- const arm_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
+void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
+ const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
int n_res, unsigned latency) {
arm_attr_t *attr = get_arm_attr(node);
attr->in_req = in_reqs;
*
***************************************************************************************/
-/* limit the possible registers for sp in arm_StoreStackM4Inc */
-static void limit_reg_arm_StoreStackM4Inc_sp(void *_unused, bitset_t *bs) {
- bs = bitset_clear_all(bs); /* disallow all register (positive constraints given) */
- bitset_set(bs, 14); /* allow r13 */
- bitset_clear(bs, 13); /* disallow ignore reg r12 */
- bitset_clear(bs, 14); /* disallow ignore reg r13 */
- bitset_clear(bs, 15); /* disallow ignore reg r15 */
- bitset_clear(bs, 16); /* disallow ignore reg rxx */
-}
-
-static const arm_register_req_t _arm_req_sp = {
- {
- arch_register_req_type_limited,
- &arm_reg_classes[CLASS_arm_gp],
- limit_reg_arm_StoreStackM4Inc_sp,
- NULL, /* limit environment */
- NULL, /* same node */
- NULL /* different node */
- },
- 0,
- 0
+#ifdef BIT
+#undef BIT
+#endif
+#define BIT(x) (1 << (x % 32))
+
+static unsigned arm_req_sp_limited[] = { BIT(REG_SP) };
+static const arch_register_req_t _arm_req_sp = {
+ arch_register_req_type_limited,
+ &arm_reg_classes[CLASS_arm_gp],
+ arm_req_sp_limited,
+ -1,
+ -1
};
/* construct Store: Store(ptr, val, mem) = ST ptr,val */
-ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem, ir_node *sp,
- int n_regs, ir_node **regs, ir_mode *mode) {
- ir_node *res;
- ir_node *in[16];
- int flags = 0;
- static const arm_register_req_t *_in_req_arm_StoreStackM4Inc[] =
- {
- &arm_default_req_none,
- &_arm_req_sp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- &arm_default_req_arm_gp,
- };
-
- assert(n_regs <= 15);
-
- in[0] = mem;
- in[1] = sp;
- memcpy(&in[2], regs, n_regs * sizeof(in[0]));
- res = new_ir_node(NULL, irg, block, op_arm_StoreStackM4Inc, mode, 2 + n_regs, in);
- flags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */
-
- /* init node attributes */
- init_arm_attributes(res, flags, _in_req_arm_StoreStackM4Inc, NULL, NULL, 0, 1);
-
- res = optimize_node(res);
- irn_vrfy_irg(res, irg);
-
- return res;
+ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem,
+ ir_node *sp, int n_regs, ir_node **regs,
+ ir_mode *mode) {
+ ir_node *res;
+ ir_node *in[16];
+ int flags = 0;
+ static const arch_register_req_t *_in_req_arm_StoreStackM4Inc[] =
+ {
+ &arm_StoreStackM4Inc_reg_req_in_0,
+ &arm_StoreStackM4Inc_reg_req_in_1,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ &arm_StoreStackM4Inc_reg_req_in_2,
+ };
+
+ assert(n_regs <= 15);
+
+ in[0] = mem;
+ in[1] = sp;
+ memcpy(&in[2], regs, n_regs * sizeof(in[0]));
+ res = new_ir_node(NULL, irg, block, op_arm_StoreStackM4Inc, mode, 2 + n_regs, in);
+ flags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */
+
+ /* init node attributes */
+ init_arm_attributes(res, flags, _in_req_arm_StoreStackM4Inc, NULL, NULL, 0, 1);
+
+ res = optimize_node(res);
+ irn_vrfy_irg(res, irg);
+
+ return res;
}
/************************************************
/**
* Returns the argument register requirements of an arm node.
*/
-const arm_register_req_t **get_arm_in_req_all(const ir_node *node);
+const arch_register_req_t **get_arm_in_req_all(const ir_node *node);
/**
* Returns the result register requirements of an arm node.
*/
-const arm_register_req_t **get_arm_out_req_all(const ir_node *node);
+const arch_register_req_t **get_arm_out_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an arm node.
*/
-const arm_register_req_t *get_arm_in_req(const ir_node *node, int pos);
+const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos);
/**
* Returns the result register requirements of an arm node.
*/
-const arm_register_req_t *get_arm_out_req(const ir_node *node, int pos);
+const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
-void set_arm_req_out(ir_node *node, const arm_register_req_t *req, int pos);
+void set_arm_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the complete OUT requirements of node.
*/
-void set_arm_req_out_all(ir_node *node, const arm_register_req_t **reqs);
+void set_arm_req_out_all(ir_node *node, const arch_register_req_t **reqs);
/**
* Sets the IN register requirements at position pos.
*/
-void set_arm_req_in(ir_node *node, const arm_register_req_t *req, int pos);
+void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the register flag of an arm node.
/**
* Set the ARM machine node attributes to default values.
*/
-void init_arm_attributes(ir_node *node, int flags, const arm_register_req_t ** in_reqs,
- const arm_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
+void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
+ const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
/**
* Returns the tarval
#include "../bearch.h"
#include "../../common/firm_types.h"
-/** A register requirement. */
-typedef struct _arm_register_req_t {
- const arch_register_req_t req;
- int same_pos; /**< in case of "should be same" we need to remember the pos to get the irn */
- int different_pos; /**< in case of "should be different" we need to remember the pos to get the irn */
-} arm_register_req_t;
-
/**
* Possible ARM register shift types.
*/
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
int n_res; /**< number of results for this node */
- const arm_register_req_t **in_req; /**< register requirements for arguments */
- const arm_register_req_t **out_req; /**< register requirements for results */
+ const arch_register_req_t **in_req; /**< register requirements for arguments */
+ const arch_register_req_t **out_req; /**< register requirements for results */
ir_mode *op_mode; /**< operation mode */
unsigned instr_fl; /**< condition code, shift modifier */
* |___/
**************************************************/
-static ir_node *my_skip_proj(const ir_node *n) {
- while (is_Proj(n))
- n = get_Proj_pred(n);
- return (ir_node *)n;
-}
-
/**
* Return register requirements for a arm node.
* If the node returns a tuple (mode_T) then the proj's
* will be asked for this information.
*/
-static const arch_register_req_t *arm_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
- const arm_register_req_t *irn_req;
+static const
+arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
+ int pos) {
long node_pos = pos == -1 ? 0 : pos;
- ir_mode *mode = get_irn_mode(irn);
+ ir_mode *mode = get_irn_mode(node);
FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
- if (is_Block(irn) || mode == mode_X || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
- return NULL;
+ if (is_Block(node) || mode == mode_X || mode == mode_M) {
+ DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", node));
+ return arch_no_register_req;
}
if (mode == mode_T && pos < 0) {
- DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", irn));
- return NULL;
+ DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", node));
+ return arch_no_register_req;
}
- DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
+ DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, node));
- if (is_Proj(irn)) {
+ if (is_Proj(node)) {
/* in case of a proj, we need to get the correct OUT slot */
/* of the node corresponding to the proj number */
if (pos == -1) {
- node_pos = arm_translate_proj_pos(irn);
+ node_pos = arm_translate_proj_pos(node);
}
else {
node_pos = pos;
}
- irn = my_skip_proj(irn);
+ node = skip_Proj_const(node);
- DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+ DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", node, node_pos));
}
/* get requirements for our own nodes */
- if (is_arm_irn(irn)) {
+ if (is_arm_irn(node)) {
+ const arch_register_req_t *req;
if (pos >= 0) {
- irn_req = get_arm_in_req(irn, pos);
+ req = get_arm_in_req(node, pos);
+ } else {
+ req = get_arm_out_req(node, node_pos);
}
- else {
- irn_req = get_arm_out_req(irn, node_pos);
- }
-
- DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
-
- memcpy(req, &(irn_req->req), sizeof(*req));
- if (arch_register_req_is(&(irn_req->req), should_be_same)) {
- assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
- req->other_same = get_irn_n(irn, irn_req->same_pos);
- }
-
- if (arch_register_req_is(&(irn_req->req), should_be_different)) {
- assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
- req->other_different = get_irn_n(irn, irn_req->different_pos);
- }
+ DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", node, pos));
+ return req;
}
- /* get requirements for FIRM nodes */
- else {
- /* treat Phi like Const with default requirements */
- if (is_Phi(irn)) {
- DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
- if (mode_is_float(mode)) {
- memcpy(req, &(arm_default_req_arm_fpa.req), sizeof(*req));
- }
- else if (mode_is_int(mode) || mode_is_reference(mode)) {
- memcpy(req, &(arm_default_req_arm_gp.req), sizeof(*req));
- }
- else if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
- return NULL;
- }
- else {
- assert(0 && "unsupported Phi-Mode");
- }
- }
- else {
- DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
- req = NULL;
- }
- }
+ /* unknown should be tranformed by now */
+ assert(!is_Unknown(node));
+ DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", node));
- return req;
+ return arch_no_register_req;
}
static void arm_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
}
pos = arm_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj(irn);
}
if (is_arm_irn(irn)) {
}
pos = arm_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
}
if (is_arm_irn(irn)) {
}
static arch_irn_class_t arm_classify(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_cfop(irn)) {
return arch_irn_class_branch;
}
static arch_irn_flags_t arm_get_flags(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_arm_irn(irn)) {
return get_arm_flags(irn);
// ir_node *regs[16];
// int n_regs = 0;
arch_register_class_t *gp = &arm_reg_classes[CLASS_arm_gp];
- static const arm_register_req_t *fp_req[] = {
- &arm_default_req_arm_gp_r11
- };
ir_node *fp = be_abi_reg_map_get(reg_map, env->isa->bp);
ir_node *ip = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R12]);
// set_arm_req_out(sp, &arm_default_req_arm_gp_sp, 0);
// arch_set_irn_register(env->arch_env, sp, env->isa->sp);
store = new_rd_arm_StoreStackM4Inc(NULL, irg, block, sp, fp, ip, lr, pc, *mem);
- set_arm_req_out(store, &arm_default_req_arm_gp_sp, 0);
-// arch_set_irn_register(env->arch_env, store, env->isa->sp);
+ // TODO
+ // set_arm_req_out(store, &arm_default_req_arm_gp_sp, 0);
+ // arch_set_irn_register(env->arch_env, store, env->isa->sp);
sp = new_r_Proj(irg, block, store, env->isa->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr);
- arch_set_irn_register(env->arch_env, sp, env->isa->sp);
+ arch_set_irn_register(env->arch_env, sp, env->isa->sp);
*mem = new_r_Proj(irg, block, store, mode_M, pn_arm_StoreStackM4Inc_M);
keep = be_new_CopyKeep_single(gp, irg, block, ip, sp, get_irn_mode(ip));
- be_node_set_reg_class(keep, 1, gp);
- arch_set_irn_register(env->arch_env, keep, &arm_gp_regs[REG_R12]);
- be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
+ be_node_set_reg_class(keep, 1, gp);
+ arch_set_irn_register(env->arch_env, keep, &arm_gp_regs[REG_R12]);
+ be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
fp = new_rd_arm_Sub_i(NULL, irg, block, keep, get_irn_mode(fp),
new_tarval_from_long(4, get_irn_mode(fp)));
- set_arm_req_out_all(fp, fp_req);
- //set_arm_req_out(fp, &arm_default_req_arm_gp_r11, 0);
- arch_set_irn_register(env->arch_env, fp, env->isa->bp);
+ // TODO...
+ //set_arm_req_out_all(fp, fp_req);
+ //set_arm_req_out(fp, &arm_default_req_arm_gp_r11, 0);
+ arch_set_irn_register(env->arch_env, fp, env->isa->bp);
// be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R0], r0);
// be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R1], r1);
ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
ir_node *curr_pc = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_PC]);
ir_node *curr_lr = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_LR]);
- static const arm_register_req_t *sub12_req[] = {
- &arm_default_req_arm_gp_sp
- };
-// TODO: Activate Omit fp in epilogue
+ // TODO: Activate Omit fp in epilogue
if(env->flags.try_omit_fp) {
curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK);
add_irn_dep(curr_sp, *mem);
ir_node *load_node;
tarval *tv = new_tarval_from_long(12,mode_Iu);
sub12_node = new_rd_arm_Sub_i(NULL, env->irg, bl, curr_bp, mode_Iu, tv);
- set_arm_req_out_all(sub12_node, sub12_req);
+ // FIXME
+ //set_arm_req_out_all(sub12_node, sub12_req);
arch_set_irn_register(env->arch_env, sub12_node, env->isa->sp);
load_node = new_rd_arm_LoadStackM3( NULL, env->irg, bl, sub12_node, *mem );
- set_arm_req_out(load_node, &arm_default_req_arm_gp_r11, 0);
- set_arm_req_out(load_node, &arm_default_req_arm_gp_sp, 1);
- set_arm_req_out(load_node, &arm_default_req_arm_gp_pc, 2);
+ // FIXME
+ //set_arm_req_out(load_node, &arm_default_req_arm_gp_r11, 0);
+ //set_arm_req_out(load_node, &arm_default_req_arm_gp_sp, 1);
+ //set_arm_req_out(load_node, &arm_default_req_arm_gp_pc, 2);
curr_bp = new_r_Proj(env->irg, bl, load_node, env->isa->bp->reg_class->mode, pn_arm_LoadStackM3_res0);
curr_sp = new_r_Proj(env->irg, bl, load_node, env->isa->sp->reg_class->mode, pn_arm_LoadStackM3_res1);
curr_pc = new_r_Proj(env->irg, bl, load_node, mode_Iu, pn_arm_LoadStackM3_res2);
struct _be_main_env_t {
struct obstack obst;
- struct _be_node_factory_t *node_factory;
struct _arch_env_t *arch_env;
struct _be_options_t *options;
struct _arch_code_generator_t *cg;
* @date 7.3.2005
* @cvsid $Id$
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "height.h"
#include "pdeq.h"
#include "irtools.h"
+#include "raw_bitset.h"
#include "be.h"
#include "beabi.h"
pmap *keep_map; /**< mapping blocks to keep nodes. */
pset *ignore_regs; /**< Additional registers which shall be ignored. */
+ arch_register_req_t sp_req;
+ arch_register_req_t sp_cls_req;
+
arch_irn_handler_t irn_handler;
arch_irn_ops_t irn_ops;
DEBUG_ONLY(firm_dbg_module_t *dbg;) /**< The debugging module. */
*/
be_node_set_reg_class(low_call, be_pos_Call_ptr, call->cls_addr);
- /* Set input requirement for stack pointer. */
- be_node_set_reg_class(low_call, be_pos_Call_sp, arch_get_irn_reg_class(isa->main_env->arch_env, curr_sp, -1));
-
DBG((env->dbg, LEVEL_3, "\tcreated backend call %+F\n", low_call));
/* Set the register classes and constraints of the Call parameters. */
pmap_entry *ent;
ir_node *dummy;
optimization_state_t state;
+ unsigned *limited_bitset;
be_omit_fp = birg->main_env->options->omit_fp;
env->dce_survivor = new_survive_dce();
env->birg = birg;
env->stack_phis = pset_new_ptr(16);
+
+ env->sp_req.type = arch_register_req_type_limited;
+ env->sp_req.cls = arch_register_get_class(env->isa->sp);
+ limited_bitset = rbitset_obstack_alloc(&env->obst, env->sp_req.cls->n_regs);
+ rbitset_set(limited_bitset, arch_register_get_index(env->isa->sp));
+ env->sp_req.limited = limited_bitset;
+
+ env->sp_cls_req.type = arch_register_req_type_normal;
+ env->sp_cls_req.cls = arch_register_get_class(env->isa->sp);
+
/* Beware: later we replace this node by the real one, ensure it is not CSE'd
to another Unknown or the stack pointer gets used */
save_optimization_state(&state);
/* Make some important node pointers survive the dead node elimination. */
survive_dce_register_irn(env->dce_survivor, &env->init_sp);
- pmap_foreach(env->regs, ent)
+ pmap_foreach(env->regs, ent) {
survive_dce_register_irn(env->dce_survivor, (ir_node **) &ent->value);
+ }
arch_env_push_irn_handler(env->birg->main_env->arch_env, &env->irn_handler);
return res;
}
-static void be_abi_limited(void *data, bitset_t *bs)
-{
- be_abi_irg_t *abi = data;
- bitset_clear_all(bs);
- bitset_set(bs, abi->isa->sp->index);
-}
-
-static const arch_register_req_t *abi_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
+static
+const arch_register_req_t *abi_get_irn_reg_req(const void *self,
+ const ir_node *irn, int pos)
{
- be_abi_irg_t *abi = get_abi_from_ops(self);
- const arch_register_t *reg = abi->isa->sp;
-
- memset(req, 0, sizeof(req[0]));
+ be_abi_irg_t *abi = get_abi_from_ops(self);
if(pos == BE_OUT_POS(0)) {
- req->cls = reg->reg_class;
- req->type = arch_register_req_type_limited;
- req->limited = be_abi_limited;
- req->limited_env = abi;
- }
-
- else if(pos >= 0 && pos < get_irn_arity(irn)) {
- req->cls = reg->reg_class;
- req->type = arch_register_req_type_normal;
+ return &abi->sp_req;
+ } else if(pos >= 0 && pos < get_irn_arity(irn)) {
+ return &abi->sp_cls_req;
}
- return req;
+ return arch_no_register_req;
}
static void abi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
*
* $Id$
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef HAVE_ALLOCA_H
#include "bitset.h"
#include "pset.h"
#include "entity.h"
+#include "raw_bitset.h"
#include "irprintf.h"
/* Initialize the architecture environment struct. */
arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
{
- memset(env, 0, sizeof(*env));
- env->isa = isa_if->init(file_handle);
- env->isa->main_env = main_env;
- return env;
+ memset(env, 0, sizeof(*env));
+ env->isa = isa_if->init(file_handle);
+ env->isa->main_env = main_env;
+ return env;
}
arch_env_t *arch_env_push_irn_handler(arch_env_t *env,
- const arch_irn_handler_t *handler)
+ const arch_irn_handler_t *handler)
{
- assert(env->handlers_tos < ARCH_MAX_HANDLERS);
- env->handlers[env->handlers_tos++] = handler;
- return env;
+ assert(env->handlers_tos < ARCH_MAX_HANDLERS);
+ env->handlers[env->handlers_tos++] = handler;
+ return env;
}
const arch_irn_handler_t *arch_env_pop_irn_handler(arch_env_t *env)
{
- assert(env->handlers_tos > 0 && env->handlers_tos <= ARCH_MAX_HANDLERS);
- return env->handlers[--env->handlers_tos];
+ assert(env->handlers_tos > 0 && env->handlers_tos <= ARCH_MAX_HANDLERS);
+ return env->handlers[--env->handlers_tos];
}
static const arch_irn_ops_t *fallback_irn_ops = NULL;
int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs)
{
- if(bs) {
- int i, n;
- for(i = 0, n = cls->n_regs; i < n; ++i)
- bitset_set(bs, i);
- }
+ if(bs) {
+ int i, n;
+ for(i = 0, n = cls->n_regs; i < n; ++i)
+ bitset_set(bs, i);
+ }
- return cls->n_regs;
+ return cls->n_regs;
}
/**
static INLINE const arch_irn_ops_t *
get_irn_ops(const arch_env_t *env, const ir_node *irn)
{
- int i;
+ int i;
- for(i = env->handlers_tos - 1; i >= 0; --i) {
- const arch_irn_handler_t *handler = env->handlers[i];
- const arch_irn_ops_t *ops = handler->get_irn_ops(handler, irn);
+ for(i = env->handlers_tos - 1; i >= 0; --i) {
+ const arch_irn_handler_t *handler = env->handlers[i];
+ const arch_irn_ops_t *ops = handler->get_irn_ops(handler, irn);
- if(ops)
- return ops;
- }
+ if(ops)
+ return ops;
+ }
- return fallback_irn_ops;
+ return fallback_irn_ops;
}
const arch_irn_ops_t *arch_get_irn_ops(const arch_env_t *env, const ir_node *irn) {
}
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)
+ const ir_node *irn, int pos)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- req->type = arch_register_req_type_none;
- return ops->impl->get_irn_reg_req(ops, req, irn, pos);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ return ops->impl->get_irn_reg_req(ops, irn, pos);
}
void arch_set_frame_offset(const arch_env_t *env, ir_node *irn, int offset)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- ops->impl->set_frame_offset(ops, irn, offset);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ ops->impl->set_frame_offset(ops, irn, offset);
}
ir_entity *arch_get_frame_entity(const arch_env_t *env, ir_node *irn)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- return ops->impl->get_frame_entity(ops, irn);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ return ops->impl->get_frame_entity(ops, irn);
}
void arch_set_frame_entity(const arch_env_t *env, ir_node *irn, ir_entity *ent)
arch_inverse_t *arch_get_inverse(const arch_env_t *env, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- if(ops->impl->get_inverse) {
- return ops->impl->get_inverse(ops, irn, i, inverse, obstack);
- } else {
- return NULL;
- }
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+
+ if(ops->impl->get_inverse) {
+ return ops->impl->get_inverse(ops, irn, i, inverse, obstack);
+ } else {
+ return NULL;
+ }
}
int arch_possible_memory_operand(const arch_env_t *env, const ir_node *irn, unsigned int i) {
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+
if(ops->impl->possible_memory_operand) {
return ops->impl->possible_memory_operand(ops, irn, i);
} else {
void arch_perform_memory_operand(const arch_env_t *env, ir_node *irn, ir_node *spill, unsigned int i) {
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+
if(ops->impl->perform_memory_operand) {
ops->impl->perform_memory_operand(ops, irn, spill, i);
} else {
int arch_get_op_estimated_cost(const arch_env_t *env, const ir_node *irn)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- if(ops->impl->get_op_estimated_cost) {
- return ops->impl->get_op_estimated_cost(ops, irn);
- } else {
- return 1;
- }
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+
+ if(ops->impl->get_op_estimated_cost) {
+ return ops->impl->get_op_estimated_cost(ops, irn);
+ } else {
+ return 1;
+ }
}
int arch_is_possible_memory_operand(const arch_env_t *env, const ir_node *irn, int i)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- if(ops->impl->possible_memory_operand) {
- return ops->impl->possible_memory_operand(ops, irn, i);
- } else {
- return 0;
- }
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+
+ if(ops->impl->possible_memory_operand) {
+ return ops->impl->possible_memory_operand(ops, irn, i);
+ } else {
+ return 0;
+ }
}
int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn, int pos, bitset_t *bs)
{
- arch_register_req_t local_req;
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
-
- if(req->type == arch_register_req_type_none) {
- bitset_clear_all(bs);
- return 0;
- }
-
- if(arch_register_req_is(req, limited)) {
- req->limited(req->limited_env, bs);
- return bitset_popcnt(bs);
- }
-
- arch_register_class_put(req->cls, bs);
- return req->cls->n_regs;
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
+
+ if(req->type == arch_register_req_type_none) {
+ bitset_clear_all(bs);
+ return 0;
+ }
+
+ if(arch_register_req_is(req, limited)) {
+ rbitset_copy_to_bitset(req->limited, bs);
+ return bitset_popcnt(bs);
+ }
+
+ arch_register_class_put(req->cls, bs);
+ return req->cls->n_regs;
}
void arch_put_non_ignore_regs(const arch_env_t *env, const arch_register_class_t *cls, bitset_t *bs)
int arch_is_register_operand(const arch_env_t *env,
const ir_node *irn, int pos)
{
- arch_register_req_t local_req;
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
+ const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
+
return req != NULL;
}
int arch_reg_is_allocatable(const arch_env_t *env, const ir_node *irn,
int pos, const arch_register_t *reg)
{
- arch_register_req_t req;
+ const arch_register_req_t *req;
- arch_get_register_req(env, &req, irn, pos);
+ req = arch_get_register_req(env, irn, pos);
- if(req.type == arch_register_req_type_none)
+ if(req->type == arch_register_req_type_none)
return 0;
- if(arch_register_req_is(&req, limited)) {
- bitset_t *bs = bitset_alloca(req.cls->n_regs);
- req.limited(req.limited_env, bs);
- return bitset_is_set(bs, arch_register_get_index(reg));
+ if(arch_register_req_is(req, limited)) {
+ assert(arch_register_get_class(reg) == req->cls);
+ return rbitset_is_set(req->limited, arch_register_get_index(reg));
}
- return req.cls == reg->reg_class;
+ return req->cls == reg->reg_class;
}
const arch_register_class_t *
arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos)
{
- arch_register_req_t local_req;
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
- return req ? req->cls : NULL;
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, irn, pos);
+
+ assert(req->type != arch_register_req_type_none || req->cls == NULL);
+
+ return req->cls;
}
extern const arch_register_t *
arch_get_irn_register(const arch_env_t *env, const ir_node *irn)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- return ops->impl->get_irn_reg(ops, irn);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ return ops->impl->get_irn_reg(ops, irn);
}
extern void arch_set_irn_register(const arch_env_t *env,
ir_node *irn, const arch_register_t *reg)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- ops->impl->set_irn_reg(ops, irn, reg);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ ops->impl->set_irn_reg(ops, irn, reg);
}
extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- return ops->impl->classify(ops, irn);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ return ops->impl->classify(ops, irn);
}
extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn)
{
- const arch_irn_ops_t *ops = get_irn_ops(env, irn);
- return ops->impl->get_flags(ops, irn);
+ const arch_irn_ops_t *ops = get_irn_ops(env, irn);
+ return ops->impl->get_flags(ops, irn);
}
extern const char *arch_irn_flag_str(arch_irn_flags_t fl)
return "n/a";
}
-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)
{
char tmp[128];
snprintf(buf, len, "class: %s", req->cls->name);
if(arch_register_req_is(req, limited)) {
- bitset_pos_t elm;
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- req->limited(req->limited_env, bs);
+ unsigned n_regs = req->cls->n_regs;
+ unsigned i;
+
strncat(buf, " limited:", len);
- bitset_foreach(bs, elm) {
- strncat(buf, " ", len);
- strncat(buf, req->cls->regs[elm].name, len);
+ for(i = 0; i < n_regs; ++i) {
+ if(rbitset_is_set(req->limited, i)) {
+ const arch_register_t *reg = &req->cls->regs[i];
+ strncat(buf, " ", len);
+ strncat(buf, reg->name, len);
+ }
}
}
if(arch_register_req_is(req, should_be_same)) {
- ir_snprintf(tmp, sizeof(tmp), " same to: %+F", req->other_different);
+ const ir_node *same = get_irn_n(node, req->other_same);
+ ir_snprintf(tmp, sizeof(tmp), " same to: %+F", same);
strncat(buf, tmp, len);
}
if(arch_register_req_is(req, should_be_different)) {
- ir_snprintf(tmp, sizeof(tmp), " different to: %+F", req->other_different);
+ const ir_node *different = get_irn_n(node, req->other_different);
+ ir_snprintf(tmp, sizeof(tmp), " different to: %+F", different);
strncat(buf, tmp, len);
}
return buf;
}
+
+static const arch_register_req_t no_requirement = {
+ arch_register_req_type_none,
+ NULL,
+ NULL,
+ -1,
+ -1
+};
+const arch_register_req_t *arch_no_register_req = &no_requirement;
#include "bemachine.h"
#include "beirg.h"
-struct _be_node_factory_t;
-
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_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;
/**
* 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. */
+ 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_env; /**< This must passed to limited. */
+ const unsigned *limited; /**< allowed register bitset */
- 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). */
+ 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);
/**
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.
* 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. */
};
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
+#include <config.h>
+#endif
#include "beblocksched.h"
#include <lpp/lpp_net.h>
#endif /* WITH_ILP */
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
typedef enum _blocksched_algos_t {
BLOCKSCHED_NAIV, BLOCKSCHED_EXTBB, BLOCKSCHED_GREEDY, BLOCKSCHED_ILP
} blocksched_algos_t;
edge_t *edges;
pdeq *worklist;
int blockcount;
- DEBUG_ONLY(firm_dbg_module_t *dbg;)
} blocksched_env_t;
/**
continue;
/* schedule the 2 blocks behind each other */
- DBG((env->dbg, LEVEL_1, "Coalesce (Jump) %+F -> %+F (%.3g)\n",
+ DBG((dbg, LEVEL_1, "Coalesce (Jump) %+F -> %+F (%.3g)\n",
pred_entry->block, entry->block, edge->execfreq));
pred_entry->next = entry;
entry->prev = pred_entry;
continue;
/* schedule the 2 blocks behind each other */
- DBG((env->dbg, LEVEL_1, "Coalesce (CondJump) %+F -> %+F (%.3g)\n",
+ DBG((dbg, LEVEL_1, "Coalesce (CondJump) %+F -> %+F (%.3g)\n",
pred_entry->block, entry->block, edge->execfreq));
pred_entry->next = entry;
entry->prev = pred_entry;
env->blockcount++;
mark_irn_visited(block);
- DBG((env->dbg, LEVEL_1, "Pick succ of %+F\n", block));
+ DBG((dbg, LEVEL_1, "Pick succ of %+F\n", block));
/* put all successors into the worklist */
foreach_block_succ(block, edge) {
if (irn_visited(succ_entry->block))
continue;
- DBG((env->dbg, LEVEL_1, "Put %+F into worklist\n", succ_entry->block));
+ DBG((dbg, LEVEL_1, "Put %+F into worklist\n", succ_entry->block));
pdeq_putr(env->worklist, succ_entry->block);
}
return;
}
- DBG((env->dbg, LEVEL_1, "deciding...\n"));
+ DBG((dbg, LEVEL_1, "deciding...\n"));
best_succ_execfreq = -1;
/* no successor yet: pick the successor block with the highest execution
}
if (succ == NULL) {
- DBG((env->dbg, LEVEL_1, "pick from worklist\n"));
+ DBG((dbg, LEVEL_1, "pick from worklist\n"));
do {
if (pdeq_empty(env->worklist)) {
- DBG((env->dbg, LEVEL_1, "worklist empty\n"));
+ DBG((dbg, LEVEL_1, "worklist empty\n"));
return;
}
succ = pdeq_getl(env->worklist);
blocksched_entry_t *entry;
block_list = NEW_ARR_D(ir_node *, obst, count);
- DBG((env->dbg, LEVEL_1, "Blockschedule:\n"));
+ DBG((dbg, LEVEL_1, "Blockschedule:\n"));
for (entry = first; entry != NULL; entry = entry->next) {
assert(i < count);
block_list[i++] = entry->block;
- DBG((env->dbg, LEVEL_1, "\t%+F\n", entry->block));
+ DBG((dbg, LEVEL_1, "\t%+F\n", entry->block));
}
assert(i == count);
env.edges = NEW_ARR_F(edge_t, 0);
env.worklist = NULL;
env.blockcount = 0;
- FIRM_DBG_REGISTER(env.dbg, "firm.be.blocksched");
// collect edge execution frequencies
irg_block_walk_graph(irg, collect_egde_frequency, NULL, &env);
pred = get_Block_cfgpred_block(block, edge->pos);
entry = get_irn_link(pred);
- DBG((env->env.dbg, LEVEL_1, "Adding out cst to %+F from %+F,%d\n",
+ DBG((dbg, LEVEL_1, "Adding out cst to %+F from %+F,%d\n",
pred, block, edge->pos));
lpp_set_factor_fast(env->lpp, entry->out_cst, edge->ilpvar, 1.0);
}
env.env.worklist = NULL;
env.env.blockcount = 0;
env.ilpedges = NEW_ARR_F(ilp_edge_t, 0);
- FIRM_DBG_REGISTER(env.env.dbg, "firm.be.blocksched");
env.lpp = new_lpp("blockschedule", lpp_minimize);
lpp_set_time_limit(env.lpp, 20);
lc_opt_entry_t *blocksched_grp = lc_opt_get_grp(be_grp, "blocksched");
lc_opt_add_table(blocksched_grp, be_blocksched_options);
+
+ FIRM_DBG_REGISTER(dbg, "firm.be.blocksched");
}
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_blocksched);
#include "pset.h"
#include "list.h"
#include "bitset.h"
+#include "raw_bitset.h"
#include "iterator.h"
#include "bipartite.h"
#include "hungarian.h"
return bs;
}
- assert(o1->req.cls == o2->req.cls);
+ assert(o1->req->cls == o2->req->cls);
if(bitset_contains(o1->regs, o2->regs))
bitset_copy(bs, o1->regs);
static ir_node *prepare_constr_insn(be_chordal_env_t *env, ir_node *irn)
{
const arch_env_t *aenv = env->birg->main_env->arch_env;
- bitset_t *def_constr = bitset_alloca(env->cls->n_regs);
bitset_t *tmp = bitset_alloca(env->cls->n_regs);
+ bitset_t *def_constr = bitset_alloca(env->cls->n_regs);
ir_node *bl = get_nodes_block(irn);
be_lv_t *lv = env->birg->lv;
ir_node *op = get_irn_n(irn, i);
ir_node *copy;
const arch_register_t *reg;
- arch_register_req_t req;
+ const arch_register_req_t *req;
if (arch_get_irn_reg_class(aenv, irn, i) != env->cls)
continue;
if(arch_register_type_is(reg, joker))
continue;
- arch_get_register_req(aenv, &req, irn, i);
- if (!arch_register_req_is(&req, limited))
+ req = arch_get_register_req(aenv, irn, i);
+ if (!arch_register_req_is(req, limited))
continue;
- bitset_clear_all(tmp);
- req.limited(req.limited_env, tmp);
-
- if (bitset_is_set(tmp, reg->index))
+ if (rbitset_is_set(req->limited, reg->index))
continue;
copy = be_new_Copy(env->cls, env->irg, bl, op);
int n_total;
const be_operand_t *op = &insn->ops[i];
- if (! values_interfere(lv, op->irn, op->carrier) && ! op->partner) {
- bitset_clear_all(bs);
- bitset_copy(bs, op->regs);
- bitset_and(bs, out_op->regs);
- n_total = bitset_popcnt(op->regs) + bitset_popcnt(out_op->regs);
+ if (op->partner != NULL)
+ continue;
+ if (values_interfere(lv, op->irn, op->carrier))
+ continue;
- if (bitset_popcnt(bs) > 0 && n_total < smallest_n_regs) {
- smallest = i;
- smallest_n_regs = n_total;
- }
+ bitset_clear_all(bs);
+ bitset_copy(bs, op->regs);
+ bitset_and(bs, out_op->regs);
+ n_total = bitset_popcnt(op->regs) + bitset_popcnt(out_op->regs);
+
+ if (bitset_popcnt(bs) > 0 && n_total < smallest_n_regs) {
+ smallest = i;
+ smallest_n_regs = n_total;
}
}
}
-static ir_node *pre_process_constraints(be_chordal_alloc_env_t *alloc_env, be_insn_t **the_insn)
+static ir_node *pre_process_constraints(be_chordal_alloc_env_t *alloc_env,
+ be_insn_t **the_insn)
{
be_chordal_env_t *env = alloc_env->chordal_env;
const arch_env_t *aenv = env->birg->main_env->arch_env;
be_insn_t *insn = *the_insn;
- ir_node *bl = get_nodes_block(insn->irn);
- ir_node *copy = NULL;
ir_node *perm = NULL;
bitset_t *out_constr = bitset_alloca(env->cls->n_regs);
- bitset_t *bs = bitset_alloca(env->cls->n_regs);
be_lv_t *lv = env->birg->lv;
- DEBUG_ONLY(firm_dbg_module_t *dbg = alloc_env->constr_dbg;)
-
+ const ir_edge_t *edge;
int i;
assert(insn->has_constraints && "only do this for constrained nodes");
bitset_or(out_constr, op->regs);
}
- (void) bl;
- (void) copy;
- (void) bs;
- DEBUG_ONLY((void) dbg;)
-
/*
Make the Perm, recompute liveness and re-scan the insn since the
in operands are now the Projs of the Perm.
perm = insert_Perm_after(aenv, lv, env->cls, env->birg->dom_front, sched_prev(insn->irn));
/* Registers are propagated by insert_Perm_after(). Clean them here! */
- if(perm) {
- const ir_edge_t *edge;
+ if(perm == NULL)
+ return NULL;
- be_stat_ev("constr_perm", get_irn_arity(perm));
- foreach_out_edge(perm, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- arch_set_irn_register(aenv, proj, NULL);
- }
+ be_stat_ev("constr_perm", get_irn_arity(perm));
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ arch_set_irn_register(aenv, proj, NULL);
+ }
- /*
- We also have to re-build the insn since the input operands are now the Projs of
- the Perm. Recomputing liveness is also a good idea if a Perm is inserted, since
- the live sets may change.
- */
- // be_liveness_recompute(lv);
- obstack_free(&env->obst, insn);
- *the_insn = insn = chordal_scan_insn(env, insn->irn);
+ /*
+ We also have to re-build the insn since the input operands are now the Projs of
+ the Perm. Recomputing liveness is also a good idea if a Perm is inserted, since
+ the live sets may change.
+ */
+ // be_liveness_recompute(lv);
+ obstack_free(&env->obst, insn);
+ *the_insn = insn = chordal_scan_insn(env, insn->irn);
+ /*
+ Copy the input constraints of the insn to the Perm as output
+ constraints. Succeeding phases (coalescing) will need that.
+ */
+ for(i = insn->use_start; i < insn->n_ops; ++i) {
+ be_operand_t *op = &insn->ops[i];
+ ir_node *proj = op->carrier;
/*
- Copy the input constraints of the insn to the Perm as output
- constraints. Succeeding phases (coalescing will need that).
+ Note that the predecessor must not be a Proj of the Perm,
+ since ignore-nodes are not Perm'ed.
*/
- for(i = insn->use_start; i < insn->n_ops; ++i) {
- be_operand_t *op = &insn->ops[i];
- ir_node *proj = op->carrier;
- /*
- Note that the predecessor must not be a Proj of the Perm,
- since ignore-nodes are not Perm'ed.
- */
- if(op->has_constraints && is_Proj(proj) && get_Proj_pred(proj) == perm) {
- be_set_constr_limited(perm, BE_OUT_POS(get_Proj_proj(proj)), &op->req);
- }
+ if(op->has_constraints && is_Proj(proj) && get_Proj_pred(proj) == perm) {
+ be_set_constr_limited(perm, BE_OUT_POS(get_Proj_proj(proj)), op->req);
}
}
static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env, ir_node *irn, int *silent)
{
+ const arch_env_t *aenv;
+ int n_regs;
+ bitset_t *bs;
+ ir_node **alloc_nodes;
+ hungarian_problem_t *bp;
+ int *assignment;
+ pmap *partners;
+ DEBUG_ONLY(firm_dbg_module_t *dbg);
+ int i, n_alloc;
+ long col;
+ const ir_edge_t *edge;
+ ir_node *perm = NULL;
+ int match_res, cost;
be_chordal_env_t *env = alloc_env->chordal_env;
void *base = obstack_base(&env->obst);
be_insn_t *insn = chordal_scan_insn(env, irn);
Perms inserted before the constraint handling phase are considered to be
correctly precolored. These Perms arise during the ABI handling phase.
*/
- if(insn->has_constraints) {
- const arch_env_t *aenv = env->birg->main_env->arch_env;
- int n_regs = env->cls->n_regs;
- bitset_t *bs = bitset_alloca(n_regs);
- ir_node **alloc_nodes = alloca(n_regs * sizeof(alloc_nodes[0]));
- hungarian_problem_t *bp= hungarian_new(n_regs, n_regs, 2, HUNGARIAN_MATCH_PERFECT);
-// bipartite_t *bp = bipartite_new(n_regs, n_regs);
- int *assignment = alloca(n_regs * sizeof(assignment[0]));
- pmap *partners = pmap_create();
- DEBUG_ONLY(firm_dbg_module_t *dbg = alloc_env->constr_dbg;)
-
- int i, n_alloc;
- long col;
- const ir_edge_t *edge;
- ir_node *perm = NULL;
- int match_res, cost;
+ if(!insn->has_constraints)
+ goto end;
- /*
- prepare the constraint handling of this node.
- Perms are constructed and Copies are created for constrained values
- interfering with the instruction.
- */
- perm = pre_process_constraints(alloc_env, &insn);
+ aenv = env->birg->main_env->arch_env;
+ n_regs = env->cls->n_regs;
+ bs = bitset_alloca(n_regs);
+ alloc_nodes = alloca(n_regs * sizeof(alloc_nodes[0]));
+ bp = hungarian_new(n_regs, n_regs, 2, HUNGARIAN_MATCH_PERFECT);
+ // bipartite_t *bp = bipartite_new(n_regs, n_regs);
+ assignment = alloca(n_regs * sizeof(assignment[0]));
+ partners = pmap_create();
+ DEBUG_ONLY(dbg = alloc_env->constr_dbg;)
- /* find suitable in operands to the out operands of the node. */
- pair_up_operands(alloc_env, insn);
+ /*
+ prepare the constraint handling of this node.
+ Perms are constructed and Copies are created for constrained values
+ interfering with the instruction.
+ */
+ perm = pre_process_constraints(alloc_env, &insn);
- /*
- look at the in/out operands and add each operand (and its possible partner)
- to a bipartite graph (left: nodes with partners, right: admissible colors).
- */
- for(i = 0, n_alloc = 0; i < insn->n_ops; ++i) {
- be_operand_t *op = &insn->ops[i];
+ /* find suitable in operands to the out operands of the node. */
+ pair_up_operands(alloc_env, insn);
- /*
- If the operand has no partner or the partner has not been marked
- for allocation, determine the admissible registers and mark it
- for allocation by associating the node and its partner with the
- set of admissible registers via a bipartite graph.
- */
- if(!op->partner || !pmap_contains(partners, op->partner->carrier)) {
+ /*
+ look at the in/out operands and add each operand (and its possible partner)
+ to a bipartite graph (left: nodes with partners, right: admissible colors).
+ */
+ for(i = 0, n_alloc = 0; i < insn->n_ops; ++i) {
+ be_operand_t *op = &insn->ops[i];
- pmap_insert(partners, op->carrier, op->partner ? op->partner->carrier : NULL);
- alloc_nodes[n_alloc] = op->carrier;
+ /*
+ If the operand has no partner or the partner has not been marked
+ for allocation, determine the admissible registers and mark it
+ for allocation by associating the node and its partner with the
+ set of admissible registers via a bipartite graph.
+ */
+ if(!op->partner || !pmap_contains(partners, op->partner->carrier)) {
- DBG((dbg, LEVEL_2, "\tassociating %+F and %+F\n", op->carrier, op->partner ? op->partner->carrier : NULL));
+ pmap_insert(partners, op->carrier, op->partner ? op->partner->carrier : NULL);
+ alloc_nodes[n_alloc] = op->carrier;
- bitset_clear_all(bs);
- get_decisive_partner_regs(bs, op, op->partner);
+ DBG((dbg, LEVEL_2, "\tassociating %+F and %+F\n", op->carrier, op->partner ? op->partner->carrier : NULL));
- DBG((dbg, LEVEL_2, "\tallowed registers for %+F: %B\n", op->carrier, bs));
+ bitset_clear_all(bs);
+ get_decisive_partner_regs(bs, op, op->partner);
- bitset_foreach(bs, col)
- hungarian_add(bp, n_alloc, col, 1);
-// bipartite_add(bp, n_alloc, col);
+ DBG((dbg, LEVEL_2, "\tallowed registers for %+F: %B\n", op->carrier, bs));
- n_alloc++;
+ bitset_foreach(bs, col) {
+ hungarian_add(bp, n_alloc, col, 1);
+ // bipartite_add(bp, n_alloc, col);
}
+
+ n_alloc++;
}
+ }
- /*
- Put all nodes which live through the constrained instruction also to the
- allocation bipartite graph. They are considered unconstrained.
- */
- if(perm) {
- foreach_out_edge(perm, edge) {
- ir_node *proj = get_edge_src_irn(edge);
+ /*
+ Put all nodes which live through the constrained instruction also to the
+ allocation bipartite graph. They are considered unconstrained.
+ */
+ if(perm != NULL) {
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
- assert(is_Proj(proj));
+ assert(is_Proj(proj));
- if(values_interfere(lv, proj, irn) && !pmap_contains(partners, proj)) {
- assert(n_alloc < n_regs);
- alloc_nodes[n_alloc] = proj;
- pmap_insert(partners, proj, NULL);
+ if(!values_interfere(lv, proj, irn) || pmap_contains(partners, proj))
+ continue;
- bitset_clear_all(bs);
- arch_put_non_ignore_regs(aenv, env->cls, bs);
- bitset_andnot(bs, env->ignore_colors);
- bitset_foreach(bs, col)
- hungarian_add(bp, n_alloc, col, 1);
-// bipartite_add(bp, n_alloc, col);
+ assert(n_alloc < n_regs);
+ alloc_nodes[n_alloc] = proj;
+ pmap_insert(partners, proj, NULL);
- n_alloc++;
- }
+ bitset_clear_all(bs);
+ arch_put_non_ignore_regs(aenv, env->cls, bs);
+ bitset_andnot(bs, env->ignore_colors);
+ bitset_foreach(bs, col) {
+ hungarian_add(bp, n_alloc, col, 1);
+ // bipartite_add(bp, n_alloc, col);
}
+
+ n_alloc++;
}
+ }
- /* Compute a valid register allocation. */
- hungarian_prepare_cost_matrix(bp, HUNGARIAN_MODE_MAXIMIZE_UTIL);
- match_res = hungarian_solve(bp, assignment, &cost, 1);
- assert(match_res == 0 && "matching failed");
- //bipartite_matching(bp, assignment);
+ /* Compute a valid register allocation. */
+ hungarian_prepare_cost_matrix(bp, HUNGARIAN_MODE_MAXIMIZE_UTIL);
+ match_res = hungarian_solve(bp, assignment, &cost, 1);
+ assert(match_res == 0 && "matching failed");
+ //bipartite_matching(bp, assignment);
- /* Assign colors obtained from the matching. */
- for(i = 0; i < n_alloc; ++i) {
- const arch_register_t *reg;
- ir_node *nodes[2];
- int j;
+ /* Assign colors obtained from the matching. */
+ for(i = 0; i < n_alloc; ++i) {
+ const arch_register_t *reg;
+ ir_node *nodes[2];
+ int j;
- assert(assignment[i] >= 0 && "there must have been a register assigned");
- reg = arch_register_for_index(env->cls, assignment[i]);
+ assert(assignment[i] >= 0 && "there must have been a register assigned");
+ reg = arch_register_for_index(env->cls, assignment[i]);
- nodes[0] = alloc_nodes[i];
- nodes[1] = pmap_get(partners, alloc_nodes[i]);
+ nodes[0] = alloc_nodes[i];
+ nodes[1] = pmap_get(partners, alloc_nodes[i]);
- for(j = 0; j < 2; ++j) {
- if(!nodes[j])
- continue;
+ for(j = 0; j < 2; ++j) {
+ if(!nodes[j])
+ continue;
- arch_set_irn_register(aenv, nodes[j], reg);
- (void) pset_hinsert_ptr(alloc_env->pre_colored, nodes[j]);
- DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", nodes[j], reg->name));
- }
+ arch_set_irn_register(aenv, nodes[j], reg);
+ (void) pset_hinsert_ptr(alloc_env->pre_colored, nodes[j]);
+ DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", nodes[j], reg->name));
}
+ }
+ /* Allocate the non-constrained Projs of the Perm. */
+ if(perm != NULL) {
+ bitset_clear_all(bs);
- /* Allocate the non-constrained Projs of the Perm. */
- if(perm) {
-
- bitset_clear_all(bs);
-
- /* Put the colors of all Projs in a bitset. */
- foreach_out_edge(perm, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- const arch_register_t *reg = arch_get_irn_register(aenv, proj);
+ /* Put the colors of all Projs in a bitset. */
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_t *reg = arch_get_irn_register(aenv, proj);
- if(reg != NULL)
- bitset_set(bs, reg->index);
- }
+ if(reg != NULL)
+ bitset_set(bs, reg->index);
+ }
- /* Assign the not yet assigned Projs of the Perm a suitable color. */
- foreach_out_edge(perm, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- const arch_register_t *reg = arch_get_irn_register(aenv, proj);
+ /* Assign the not yet assigned Projs of the Perm a suitable color. */
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_t *reg = arch_get_irn_register(aenv, proj);
- DBG((dbg, LEVEL_2, "\tchecking reg of %+F: %s\n", proj, reg ? reg->name : "<none>"));
+ DBG((dbg, LEVEL_2, "\tchecking reg of %+F: %s\n", proj, reg ? reg->name : "<none>"));
- if(reg == NULL) {
- col = get_next_free_reg(alloc_env, bs);
- reg = arch_register_for_index(env->cls, col);
- bitset_set(bs, reg->index);
- arch_set_irn_register(aenv, proj, reg);
- pset_insert_ptr(alloc_env->pre_colored, proj);
- DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", proj, reg->name));
- }
+ if(reg == NULL) {
+ col = get_next_free_reg(alloc_env, bs);
+ reg = arch_register_for_index(env->cls, col);
+ bitset_set(bs, reg->index);
+ arch_set_irn_register(aenv, proj, reg);
+ pset_insert_ptr(alloc_env->pre_colored, proj);
+ DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", proj, reg->name));
}
}
-
- //bipartite_free(bp);
- hungarian_free(bp);
- pmap_destroy(partners);
}
+ //bipartite_free(bp);
+ hungarian_free(bp);
+ pmap_destroy(partners);
+
end:
obstack_free(&env->obst, base);
return res;
const arch_register_t *reg;
int col = NO_COLOR;
- if(pset_find_ptr(alloc_env->pre_colored, irn) || ignore) {
+ if(ignore || pset_find_ptr(alloc_env->pre_colored, irn)) {
reg = arch_get_irn_register(arch_env, irn);
col = reg->index;
assert(!bitset_is_set(colors, col) && "pre-colored register must be free");
- }
-
- else {
+ } else {
col = get_next_free_reg(alloc_env, colors);
reg = arch_register_for_index(env->cls, col);
assert(arch_get_irn_register(arch_env, irn) == NULL && "This node must not have been assigned a register yet");
* conflicts is the best one.
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef HAVE_ALLOCA_H
#include "becopystat.h"
#include "benodesets.h"
#include "bitset.h"
+#include "raw_bitset.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
*/
if (irn != trigger) {
bitset_t *free_cols = bitset_alloca(cls->n_regs);
- arch_register_req_t req;
+ const arch_register_req_t *req;
ir_node *curr;
int free_col;
bitset_flip_all(free_cols);
/* Exclude colors not assignable to the irn */
- arch_get_register_req(arch_env, &req, irn, -1);
- if (arch_register_req_is(&req, limited)) {
+ req = arch_get_register_req(arch_env, irn, -1);
+ if (arch_register_req_is(req, limited)) {
bitset_t *limited = bitset_alloca(cls->n_regs);
- req.limited(req.limited_env, limited);
+ rbitset_copy_to_bitset(req->limited, limited);
bitset_and(free_cols, limited);
}
-
/**
* More experiments on coalescing.
* @author Sebastian Hack
* @date 14.04.2006
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <libcore/lc_opts.h>
#include "list.h"
#include "pdeq.h"
#include "bitset.h"
+#include "raw_bitset.h"
#include "debug.h"
#include "bitfiddle.h"
static INLINE bitset_t *get_adm(co2_t *env, co2_irn_t *ci)
{
- if(!ci->adm_cache) {
- arch_register_req_t req;
+ if(ci->adm_cache == NULL) {
+ const arch_register_req_t *req;
ci->adm_cache = bitset_obstack_alloc(phase_obst(&env->ph), env->n_regs);
- arch_get_register_req(env->co->aenv, &req, ci->irn, BE_OUT_POS(0));
- if(arch_register_req_is(&req, limited)) {
- req.limited(req.limited_env, ci->adm_cache);
+ req = arch_get_register_req(env->co->aenv, ci->irn, BE_OUT_POS(0));
+
+ if(arch_register_req_is(req, limited)) {
+ int i, n;
+
+ n = env->n_regs;
+ for(i = 0; i < n; ++i) {
+ if(rbitset_is_set(req->limited, i))
+ bitset_set(ci->adm_cache, i);
+ }
ci->is_constrained = 1;
- }
- else {
+ } else {
bitset_copy(ci->adm_cache, env->ignore_regs);
bitset_flip_all(ci->adm_cache);
}
static void incur_constraint_costs(co2_t *env, ir_node *irn, col_cost_pair_t *col_costs, int costs)
{
- bitset_t *aux = bitset_alloca(env->co->cls->n_regs);
- arch_register_req_t req;
+ const arch_register_req_t *req;
- arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
+ req = arch_get_register_req(env->co->aenv, irn, BE_OUT_POS(0));
- if(arch_register_req_is(&req, limited)) {
- bitset_pos_t elm;
- int n_constr;
+ if(arch_register_req_is(req, limited)) {
+ unsigned n_regs = env->co->cls->n_regs;
+ unsigned n_constr = 0;
+ int i;
- req.limited(req.limited_env, aux);
- n_constr = bitset_popcnt(aux);
- bitset_foreach(aux, elm) {
- col_costs[elm].costs = add_saturated(col_costs[elm].costs, costs / n_constr);
+ n_constr = rbitset_popcnt(req->limited, n_regs);
+ for(i = 0; i < n_regs; ++i) {
+ if(rbitset_is_set(req->limited, i)) {
+ col_costs[i].costs = add_saturated(col_costs[i].costs, costs / n_constr);
+ }
}
}
}
static const char *get_dot_shape_name(co2_t *env, co2_irn_t *ci)
{
- arch_register_req_t req;
+ const arch_register_req_t *req;
- arch_get_register_req(env->co->aenv, &req, ci->irn, BE_OUT_POS(0));
- if(arch_register_req_is(&req, limited))
+ req = arch_get_register_req(env->co->aenv, ci->irn, BE_OUT_POS(0));
+ if(arch_register_req_is(req, limited))
return "diamond";
if(ci->fixed)
-
/**
* More experiments on coalescing.
* @author Sebastian Hack
* @date 25.07.2006
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <libcore/lc_opts.h>
#include "debug.h"
#include "bitfiddle.h"
#include "bitset.h"
+#include "raw_bitset.h"
#include "irphase_t.h"
#include "irgraph_t.h"
static void set_admissible_regs(be_java_coal_t *coal, copy_opt_t *co, ir_node *irn, int t_idx, int *col_map)
{
- unsigned i;
- arch_register_req_t req;
- unsigned n_regs = co->cls->n_regs;
+ const arch_register_req_t *req;
+
+ req = arch_get_register_req(co->aenv, irn, BE_OUT_POS(0));
// ir_printf("%+F\n", irn);
- arch_get_register_req(co->aenv, &req, irn, BE_OUT_POS(0));
- if(arch_register_req_is(&req, limited)) {
- bitset_t *adm = bitset_alloca(n_regs);
- req.limited(req.limited_env, adm);
- for(i = 0; i < n_regs; ++i)
- if(!bitset_is_set(adm, i) && col_map[i] >= 0) {
- // printf("\tforbidding color: %d\n", i);
+ if(arch_register_req_is(req, limited)) {
+ unsigned i;
+ unsigned n_regs = co->cls->n_regs;
+
+ for(i = 0; i < n_regs; ++i) {
+ if(!rbitset_is_set(req->limited, i) && col_map[i] >= 0) {
be_java_coal_forbid_color(coal, t_idx, col_map[i]);
}
+ }
}
}
static int time_limit = 60;
static int solve_net = 1;
static int solve_log = 0;
-static int dump_flags = 0;
+static unsigned dump_flags = 0;
static const lc_opt_enum_mask_items_t dump_items[] = {
{ "ilp", DUMP_ILP },
while (redo) {
redo = 0;
be_ifg_foreach_node(ifg, iter, irn) {
- arch_register_req_t req;
+ const arch_register_req_t *req;
- arch_get_register_req(sr->co->aenv, &req, irn, -1);
+ req = arch_get_register_req(sr->co->aenv, irn, -1);
- if (!arch_register_req_is(&req, limited) && !sr_is_removed(sr, irn) && !co_gs_is_optimizable(sr->co, irn)) {
+ if (!arch_register_req_is(req, limited) && !sr_is_removed(sr, irn) && !co_gs_is_optimizable(sr->co, irn)) {
if (sr_is_simplicial(sr, irn)) {
coloring_suffix_t *cs = obstack_alloc(&sr->ob, sizeof(*cs));
#ifdef WITH_ILP
-#include <bitset.h>
+#include "bitset.h"
+#include "raw_bitset.h"
#include "pdeq.h"
#include "irtools.h"
be_ifg_foreach_node(ifg, iter, irn)
if (!sr_is_removed(ienv->sr, irn)) {
int col, cst_idx;
- arch_register_req_t req;
+ const arch_register_req_t *req;
int curr_node_color = get_irn_col(ienv->co, irn);
int node_nr = (int)get_irn_node_nr(irn);
local_env_t *lenv = ienv->env;
pmap_insert(lenv->nr_2_irn, INT_TO_PTR(node_nr), irn);
- arch_get_register_req(ienv->co->aenv, &req, irn, -1);
+ req = arch_get_register_req(ienv->co->aenv, irn, -1);
/* get assignable colors */
- if (arch_register_req_is(&req, limited))
- req.limited(req.limited_env, colors);
- else {
- arch_register_class_put(req.cls, colors);
+ if (arch_register_req_is(req, limited)) {
+ rbitset_copy_to_bitset(req->limited, colors);
+ } else {
+ arch_register_class_put(req->cls, colors);
// bitset_andnot(colors, ienv->co->cenv->ignore_colors);
}
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef HAVE_ALLOCA_H
#include "xmalloc.h"
#include "debug.h"
#include "pmap.h"
+#include "raw_bitset.h"
#include "irgraph.h"
#include "irgwalk.h"
#include "irprog.h"
}
int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) {
- arch_register_req_t req;
+ const arch_register_req_t *req;
const arch_register_t *reg;
if (arch_irn_is(co->aenv, irn, ignore))
if (arch_register_type_is(reg, ignore))
return 0;
- if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(co->aenv, irn, &req))
+ req = arch_get_register_req(co->aenv, irn, -1);
+ if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(req))
return 1;
return 0;
ir_node *n = edge->src;
if (!nodes_interfere(co->cenv, irn, n) || irn == n) {
- arch_register_req_t req;
- arch_get_register_req(co->aenv, &req, n, -1);
+ const arch_register_req_t *req;
+ req = arch_get_register_req(co->aenv, n, -1);
if(is_Reg_Phi(n) ||
is_Perm(co->aenv, n) ||
- (arch_register_req_is(&req, should_be_same) && req.other_same == irn)
- )
- return 1;
+ (arch_register_req_is(req, should_be_same))) {
+ ir_node *other = get_irn_n(irn, req->other_same);
+ if(other == irn)
+ return 1;
+ }
}
}
static void co_collect_units(ir_node *irn, void *env) {
copy_opt_t *co = env;
unit_t *unit;
- arch_register_req_t req;
if (!is_curr_reg_class(co, irn))
return;
unit->nodes[0] = irn;
unit->nodes[1] = get_Perm_src(irn);
unit->costs[1] = co->get_costs(co, irn, unit->nodes[1], -1);
- } else
-
- /* Src == Tgt of a 2-addr-code instruction */
- if (is_2addr_code(co->aenv, irn, &req)) {
- ir_node *other = req.other_same;
- if (!nodes_interfere(co->cenv, irn, other)) {
- unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
- unit->costs = xmalloc(2 * sizeof(*unit->costs));
- unit->node_count = 2;
- unit->nodes[0] = irn;
- unit->nodes[1] = other;
- unit->costs[1] = co->get_costs(co, irn, other, -1);
+ } else {
+ const arch_register_req_t *req =
+ arch_get_register_req(co->aenv, irn, -1);
+
+ /* Src == Tgt of a 2-addr-code instruction */
+ if (is_2addr_code(req)) {
+ ir_node *other = get_irn_n(irn, req->other_same);
+ if (!nodes_interfere(co->cenv, irn, other)) {
+ unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
+ unit->costs = xmalloc(2 * sizeof(*unit->costs));
+ unit->node_count = 2;
+ unit->nodes[0] = irn;
+ unit->nodes[1] = other;
+ unit->costs[1] = co->get_costs(co, irn, other, -1);
+ }
+ } else {
+ assert(0 && "This is not an optimizable node!");
}
- } else
- assert(0 && "This is not an optimizable node!");
+ }
/* Insert the new unit at a position according to its costs */
if (unit->node_count > 1) {
static void build_graph_walker(ir_node *irn, void *env) {
copy_opt_t *co = env;
int pos, max;
- arch_register_req_t req;
const arch_register_t *reg;
if (!is_curr_reg_class(co, irn) || arch_irn_is(co->aenv, irn, ignore))
}
/* 2-address code */
- else if (is_2addr_code(co->aenv, irn, &req))
- add_edges(co, irn, req.other_same, co->get_costs(co, irn, req.other_same, 0));
+ else {
+ const arch_register_req_t *req =
+ arch_get_register_req(co->aenv, irn, -1);
+ if (is_2addr_code(req)) {
+ ir_node *other = get_irn_n(irn, req->other_same);
+ add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
+ }
+ }
}
void co_build_graph_structure(copy_opt_t *co) {
{
be_ifg_t *ifg = co->cenv->ifg;
int *color_map = alloca(co->cls->n_regs * sizeof(color_map[0]));
- bitset_t *adm = bitset_alloca(co->cls->n_regs);
ir_node *irn;
void *it, *nit;
int idx = PTR_TO_INT(get_irn_link(irn));
affinity_node_t *a = get_affinity_info(co, irn);
- arch_register_req_t req;
+ const arch_register_req_t *req;
ir_node *adj;
- arch_get_register_req(co->aenv, &req, irn, BE_OUT_POS(0));
- if(arch_register_req_is(&req, limited)) {
- bitset_clear_all(adm);
- req.limited(req.limited_env, adm);
- for(i = 0; i < co->cls->n_regs; ++i)
- if(!bitset_is_set(adm, i) && color_map[i] >= 0)
+ req = arch_get_register_req(co->aenv, irn, BE_OUT_POS(0));
+ if(arch_register_req_is(req, limited)) {
+ for(i = 0; i < co->cls->n_regs; ++i) {
+ if(!rbitset_is_set(req->limited, i) && color_map[i] >= 0)
fprintf(f, "%d %d -1\n", color_map[i], idx);
-
+ }
}
{
co_ifg_dump_t *env = self;
const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
- arch_register_req_t req;
+ const arch_register_req_t *req;
int limited;
- arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
- limited = arch_register_req_is(&req, limited);
+ req = arch_get_register_req(env->co->aenv, irn, BE_OUT_POS(0));
+ limited = arch_register_req_is(req, limited);
if(env->flags & CO_IFG_DUMP_LABELS) {
ir_fprintf(f, "label=\"%+F", irn);
+#if 0
+ // TODO fix this...
if((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
req.limited(req.limited_env, bs);
ir_fprintf(f, "\\n%B", bs);
}
+#endif
ir_fprintf(f, "\" ");
- }
-
- else
+ } else {
fprintf(f, "label=\"\" shape=point " );
+ }
if(env->flags & CO_IFG_DUMP_SHAPE)
fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
#define is_Perm(arch_env, irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
#define is_Perm_Proj(arch_env, irn) (is_Proj(irn) && is_Perm(arch_env, get_Proj_pred(irn)))
-#define is_2addr_code(arch_env, irn, req) (arch_get_register_req(arch_env, req, irn, -1)->type == arch_register_req_type_should_be_same)
-
-
+static INLINE int is_2addr_code(const arch_register_req_t *req)
+{
+ return req->type == arch_register_req_type_should_be_same;
+}
/******************************************************************************
____ _ _ _ _ _ _____ _
--- /dev/null
+/*
+ * Author: Matthias Braun
+ * Date: 12.03.2007
+ * Copyright: (c) Universitaet Karlsruhe
+ * License: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "beemitter.h"
+#include "xmalloc.h"
+#include "irprintf.h"
+
+void be_emit_init_env(be_emit_env_t *env, FILE *F)
+{
+ memset(env, 0, sizeof(env[0]));
+
+ env->F = F;
+ obstack_init(&env->obst);
+ env->linelength = 0;
+}
+
+void be_emit_destroy_env(be_emit_env_t *env)
+{
+ obstack_free(&env->obst, NULL);
+}
+
+void be_emit_ident(be_emit_env_t *env, ident *id)
+{
+ size_t len = get_id_strlen(id);
+ const char *str = get_id_str(id);
+
+ be_emit_string_len(env, str, len);
+}
+
+void be_emit_irvprintf(be_emit_env_t *env, const char *fmt, va_list args)
+{
+ char buf[256];
+
+ ir_vsnprintf(buf, sizeof(buf), fmt, args);
+ be_emit_string(env, buf);
+}
+
+void be_emit_irprintf(be_emit_env_t *env, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ be_emit_irvprintf(env, fmt, ap);
+ va_end(ap);
+}
+
+void be_emit_write_line(be_emit_env_t *env)
+{
+ char *finished_line = obstack_finish(&env->obst);
+
+ fwrite(finished_line, env->linelength, 1, env->F);
+ env->linelength = 0;
+ obstack_free(&env->obst, finished_line);
+}
+
+void be_emit_pad_comment(be_emit_env_t *env)
+{
+ while(env->linelength <= 30) {
+ be_emit_char(env, ' ');
+ }
+ be_emit_cstring(env, " ");
+}
+
+void be_emit_finish_line_gas(be_emit_env_t *env, const ir_node *node)
+{
+ dbg_info *dbg;
+ const char *sourcefile;
+ unsigned lineno;
+
+ if(node == NULL) {
+ be_emit_char(env, '\n');
+ be_emit_write_line(env);
+ return;
+ }
+
+ be_emit_pad_comment(env);
+ be_emit_cstring(env, "/* ");
+ be_emit_irprintf(env, "%+F ", node);
+
+ dbg = get_irn_dbg_info(node);
+ sourcefile = be_retrieve_dbg_info(dbg, &lineno);
+ if(sourcefile != NULL) {
+ be_emit_string(env, sourcefile);
+ be_emit_irprintf(env, ":%u", lineno);
+ }
+ be_emit_cstring(env, " */\n");
+ be_emit_write_line(env);
+}
--- /dev/null
+/*
+ * Author: Matthias Braun
+ * Date: 12.03.2007
+ * Copyright: (c) Universitaet Karlsruhe
+ * License: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef BESPILLMORGAN_H_
+#define BESPILLMORGAN_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "obst.h"
+#include "ident.h"
+#include "irnode.h"
+#include "be.h"
+
+/* framework for emitting data (usually the final assembly code) */
+
+typedef struct be_emit_env_t {
+ FILE *F;
+ struct obstack obst;
+ int linelength;
+} be_emit_env_t;
+
+static INLINE void be_emit_char(be_emit_env_t *env, char c)
+{
+ obstack_1grow(&env->obst, c);
+ env->linelength++;
+}
+
+static INLINE void be_emit_string_len(be_emit_env_t *env, const char *str,
+ size_t l)
+{
+ obstack_grow(&env->obst, str, l);
+ env->linelength += l;
+}
+
+static INLINE void be_emit_string(be_emit_env_t *env, const char *str)
+{
+ size_t len = strlen(str);
+ be_emit_string_len(env, str, len);
+}
+
+#define be_emit_cstring(env,x) { be_emit_string_len(env, x, sizeof(x)-1); }
+
+void be_emit_init_env(be_emit_env_t *env, FILE *F);
+void be_emit_destroy_env(be_emit_env_t *env);
+
+void be_emit_ident(be_emit_env_t *env, ident *id);
+void be_emit_irprintf(be_emit_env_t *env, const char *fmt, ...);
+void be_emit_irvprintf(be_emit_env_t *env, const char *fmt, va_list args);
+void be_emit_write_line(be_emit_env_t *env);
+
+/* appends a gas-style comment with the node number and writes the line */
+void be_emit_finish_line_gas(be_emit_env_t *env, const ir_node *node);
+void be_emit_pad_comment(be_emit_env_t *env);
+
+#endif
--- /dev/null
+/**
+ * Dumps global variables and constants as gas assembler.
+ * @author Christian Wuerdig, Matthias Braun
+ * @date 04.11.2005
+ * @version $Id$
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "begnuas.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "obst.h"
+#include "tv.h"
+#include "irnode.h"
+#include "entity.h"
+#include "irprog.h"
+#include "error.h"
+
+#include "be_t.h"
+#include "beemitter.h"
+#include "be_dbgout.h"
+
+typedef struct obstack obstack_t;
+
+/** by default, we generate assembler code for the Linux gas */
+be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_NORMAL;
+
+static const char* get_section_name(be_gas_section_t section) {
+ static const char *text[GAS_FLAVOUR_MAX][GAS_SECTION_MAX] = {
+ {
+ ".section\t.text",
+ ".section\t.data",
+ ".section\t.rodata",
+ ".section\t.bss",
+ ".section\t.tbss,\"awT\",@nobits",
+ ".section\t.ctors,\"aw\",@progbits"
+ },
+ {
+ ".section\t.text",
+ ".section\t.data",
+ ".section .rdata,\"dr\"",
+ ".section\t.bss",
+ ".section\t.tbss,\"awT\",@nobits",
+ ".section\t.ctors,\"aw\",@progbits"
+ }
+ };
+
+ assert(be_gas_flavour >= 0 && be_gas_flavour < GAS_FLAVOUR_MAX);
+ assert(section >= 0 && section < GAS_SECTION_MAX);
+ return text[be_gas_flavour][section];
+}
+
+void be_gas_emit_switch_section(be_emit_env_t *env, be_gas_section_t section) {
+ be_emit_char(env, '\t');
+ be_emit_string(env, get_section_name(section));
+ be_emit_char(env, '\n');
+ be_emit_write_line(env);
+}
+
+typedef struct _ia32_decl_env {
+ obstack_t *rodata_obst;
+ obstack_t *data_obst;
+ obstack_t *bss_obst;
+ obstack_t *ctor_obst;
+ const be_main_env_t *main_env;
+} ia32_decl_env_t;
+
+/************************************************************************/
+
+/**
+ * output a tarval
+ */
+static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
+{
+ switch (bytes) {
+
+ case 1:
+ obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
+ break;
+
+ case 2:
+ obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+ break;
+
+ case 4:
+ obstack_printf(obst, "0x%02x%02x%02x%02x",
+ get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+ break;
+
+ case 8:
+ obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
+ get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+ break;
+
+ case 10:
+ case 12:
+ break;
+
+ case 16:
+ obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x",
+ get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 16),
+ get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12),
+ get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10),
+ get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8),
+ get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6),
+ get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
+ get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2),
+ get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+ break;
+
+
+ default:
+ fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
+ assert(0);
+ }
+}
+
+/**
+ * Return the tarval of an atomic initializer.
+ */
+static tarval *get_atomic_init_tv(ir_node *init)
+{
+ for (;;) {
+ ir_mode *mode = get_irn_mode(init);
+
+ switch (get_irn_opcode(init)) {
+
+ case iro_Cast:
+ init = get_Cast_op(init);
+ continue;
+
+ case iro_Conv:
+ init = get_Conv_op(init);
+ continue;
+
+ case iro_Const:
+ return get_Const_tarval(init);
+
+ case iro_SymConst:
+ switch (get_SymConst_kind(init)) {
+ case symconst_ofs_ent:
+ return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
+
+ case symconst_type_size:
+ return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
+
+ case symconst_type_align:
+ return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
+
+ case symconst_enum_const:
+ return get_enumeration_value(get_SymConst_enum(init));
+
+ default:
+ return NULL;
+ }
+
+ default:
+ return NULL;
+ }
+ }
+}
+
+/**
+ * dump an atomic value
+ */
+static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
+{
+ ir_mode *mode = get_irn_mode(init);
+ int bytes = get_mode_size_bytes(mode);
+ tarval *tv;
+
+ switch (get_irn_opcode(init)) {
+
+ case iro_Cast:
+ do_dump_atomic_init(obst, get_Cast_op(init));
+ return;
+
+ case iro_Conv:
+ do_dump_atomic_init(obst, get_Conv_op(init));
+ return;
+
+ case iro_Const:
+ tv = get_Const_tarval(init);
+
+ /* it's a arithmetic value */
+ dump_arith_tarval(obst, tv, bytes);
+ return;
+
+ case iro_SymConst:
+ switch (get_SymConst_kind(init)) {
+ case symconst_addr_name:
+ obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
+ break;
+
+ case symconst_addr_ent:
+ obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
+ break;
+
+ case symconst_ofs_ent:
+ obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
+ break;
+
+ case symconst_type_size:
+ obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
+ break;
+
+ case symconst_type_align:
+ obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
+ break;
+
+ case symconst_enum_const:
+ tv = get_enumeration_value(get_SymConst_enum(init));
+ dump_arith_tarval(obst, tv, bytes);
+ break;
+
+ default:
+ assert(!"dump_atomic_init(): don't know how to init from this SymConst");
+ }
+ return;
+
+ case iro_Add:
+ do_dump_atomic_init(obst, get_Add_left(init));
+ obstack_printf(obst, " + ");
+ do_dump_atomic_init(obst, get_Add_right(init));
+ return;
+
+ case iro_Sub:
+ do_dump_atomic_init(obst, get_Sub_left(init));
+ obstack_printf(obst, " - ");
+ do_dump_atomic_init(obst, get_Sub_right(init));
+ return;
+
+ case iro_Mul:
+ do_dump_atomic_init(obst, get_Mul_left(init));
+ obstack_printf(obst, " * ");
+ do_dump_atomic_init(obst, get_Mul_right(init));
+ return;
+
+ default:
+ assert(0 && "dump_atomic_init(): unknown IR-node");
+ }
+}
+
+/**
+ * dumps the type for given size (.byte, .long, ...)
+ */
+static void dump_size_type(obstack_t *obst, int size) {
+ switch (size) {
+
+ case 1:
+ obstack_printf(obst, "\t.byte\t");
+ break;
+
+ case 2:
+ obstack_printf(obst, "\t.value\t");
+ break;
+
+ case 4:
+ obstack_printf(obst, "\t.long\t");
+ break;
+
+ case 8:
+ obstack_printf(obst, "\t.quad\t");
+ break;
+
+ case 10:
+ case 12:
+ /* handled in arith */
+ break;
+
+ case 16:
+ obstack_printf(obst, "\t.octa\t");
+ break;
+
+ default:
+ fprintf(stderr, "Try to dump a type with %d bytes\n", size);
+ assert(0);
+ }
+}
+
+/**
+ * dump an atomic value to an obstack
+ */
+static void dump_atomic_init(obstack_t *obst, ir_node *init)
+{
+ ir_mode *mode = get_irn_mode(init);
+ int bytes = get_mode_size_bytes(mode);
+
+ dump_size_type(obst, bytes);
+ do_dump_atomic_init(obst, init);
+ obstack_printf(obst, "\n");
+}
+
+/************************************************************************/
+/* Routines to dump global variables */
+/************************************************************************/
+
+/**
+ * Determine if an entity is a string constant
+ * @param ent The entity
+ * @return 1 if it is a string constant, 0 otherwise
+ */
+static int ent_is_string_const(ir_entity *ent)
+{
+ ir_type *type, *element_type;
+ ir_mode *mode;
+ int i, c, n;
+
+ type = get_entity_type(ent);
+
+ /* if it's an array */
+ if (!is_Array_type(type))
+ return 0;
+
+ element_type = get_array_element_type(type);
+
+ /* and the array's element type is primitive */
+ if (!is_Primitive_type(element_type))
+ return 0;
+
+ /* and the mode of the element type is an int of
+ * the same size as the byte mode */
+ mode = get_type_mode(element_type);
+ if (!mode_is_int(mode)
+ || get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
+ return 0;
+
+ /* if it contains only printable chars and a 0 at the end */
+ n = get_compound_ent_n_values(ent);
+ for (i = 0; i < n; ++i) {
+ ir_node *irn = get_compound_ent_value(ent, i);
+ if(get_irn_opcode(irn) != iro_Const)
+ return 0;
+
+ c = (int) get_tarval_long(get_Const_tarval(irn));
+
+ if((i < n - 1 && !(isgraph(c) || isspace(c)))
+ || (i == n - 1 && c != '\0'))
+ return 0;
+ }
+
+ /* then we can emit it as a string constant */
+ return 1;
+}
+
+/**
+ * Dump a string constant.
+ * No checks are made!!
+ * @param obst The obst to dump on.
+ * @param ent The entity to dump.
+ */
+static void dump_string_cst(obstack_t *obst, ir_entity *ent)
+{
+ int i, n;
+
+ obstack_printf(obst, "\t.string \"");
+ n = get_compound_ent_n_values(ent);
+
+ for (i = 0; i < n-1; ++i) {
+ ir_node *irn;
+ int c;
+
+ irn = get_compound_ent_value(ent, i);
+ c = (int) get_tarval_long(get_Const_tarval(irn));
+
+ switch (c) {
+ case '"' : obstack_printf(obst, "\\\""); break;
+ case '\n': obstack_printf(obst, "\\n"); break;
+ case '\r': obstack_printf(obst, "\\r"); break;
+ case '\t': obstack_printf(obst, "\\t"); break;
+ case '\\': obstack_printf(obst, "\\\\"); break;
+ default :
+ if (isprint(c))
+ obstack_printf(obst, "%c", c);
+ else
+ obstack_printf(obst, "\\%o", c);
+ break;
+ }
+ }
+ obstack_printf(obst, "\"\n");
+}
+
+static void dump_array_init(obstack_t *obst, ir_entity *ent)
+{
+ const ir_type *ty = get_entity_type(ent);
+ int i;
+ int filler;
+ int size = 0;
+
+ /* potential spare values should be already included! */
+ for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
+ ir_entity *step = get_compound_ent_value_member(ent, i);
+ ir_type *stype = get_entity_type(step);
+
+ if (get_type_mode(stype)) {
+ int align = (get_type_alignment_bits(stype) + 7) >> 3;
+ int n = size % align;
+
+ if (n > 0) {
+ obstack_printf(obst, "\t.zero\t%d\n", align - n);
+ size += align - n;
+ }
+ }
+ dump_atomic_init(obst, get_compound_ent_value(ent, i));
+ size += get_type_size_bytes(stype);
+ }
+ filler = get_type_size_bytes(ty) - size;
+
+ if (filler > 0)
+ obstack_printf(obst, "\t.skip\t%d\n", filler);
+}
+
+enum normal_or_bitfield_kind {
+ NORMAL = 0,
+ BITFIELD
+};
+
+typedef struct {
+ enum normal_or_bitfield_kind kind;
+ union {
+ ir_node *value;
+ unsigned char bf_val;
+ } v;
+} normal_or_bitfield;
+
+/**
+ * Dump an initializer for a compound entity.
+ */
+static void dump_compound_init(obstack_t *obst, ir_entity *ent)
+{
+ normal_or_bitfield *vals;
+ int i, j, n = get_compound_ent_n_values(ent);
+ int last_ofs;
+
+ /* Find the initializer size. Sorrily gcc support a nasty feature:
+ The last field of a compound may be a flexible array. This allows
+ initializers bigger than the type size. */
+ last_ofs = 0;
+ for (i = 0; i < n; ++i) {
+ int offset = get_compound_ent_value_offset_bytes(ent, i);
+ int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
+ const compound_graph_path *path = get_compound_ent_value_path(ent, i);
+ int path_len = get_compound_graph_path_length(path);
+ ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
+ int value_len = get_type_size_bits(get_entity_type(last_ent));
+
+ offset += (value_len + bits_remainder + 7) >> 3;
+
+ if (offset > last_ofs) {
+ last_ofs = offset;
+ }
+ }
+
+ /*
+ * In the worst case, every initializer allocates one byte.
+ * Moreover, initializer might be big, do not allocate on stack.
+ */
+ vals = xcalloc(last_ofs, sizeof(vals[0]));
+
+ /* collect the values and store them at the offsets */
+ for (i = 0; i < n; ++i) {
+ const compound_graph_path *path = get_compound_ent_value_path(ent, i);
+ int path_len = get_compound_graph_path_length(path);
+ int offset = get_compound_ent_value_offset_bytes(ent, i);
+ int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
+ ir_node *value = get_compound_ent_value(ent, i);
+ ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
+ int value_len = get_type_size_bits(get_entity_type(last_ent));
+ assert(offset >= 0);
+ assert(offset_bits >= 0);
+
+ if (offset_bits != 0 ||
+ (value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
+ tarval *shift, *shifted;
+ tarval *tv = get_atomic_init_tv(value);
+ if (tv == NULL) {
+ panic("Couldn't get numeric value for bitfield initializer '%s'\n",
+ get_entity_ld_name(ent));
+ }
+ tv = tarval_convert_to(tv, mode_Lu);
+ shift = new_tarval_from_long(offset_bits, mode_Is);
+ shifted = tarval_shl(tv, shift);
+ if (shifted == tarval_bad || shifted == tarval_undefined) {
+ panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
+ get_entity_ld_name(ent));
+ }
+
+ for (j = 0; value_len > 0; ++j) {
+ assert(offset + j < last_ofs);
+ assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
+ vals[offset + j].kind = BITFIELD;
+ vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
+ value_len -= 8 - offset_bits;
+ offset_bits = 0;
+ }
+ } else {
+ assert(offset < last_ofs);
+ assert(vals[offset].kind == NORMAL);
+ assert(vals[offset].v.value == NULL);
+ vals[offset].v.value = value;
+ }
+ }
+
+ /* now write them sorted */
+ for (i = 0; i < last_ofs; ) {
+ int space = 0, skip = 0;
+ if (vals[i].kind == NORMAL) {
+ if(vals[i].v.value != NULL) {
+ dump_atomic_init(obst, vals[i].v.value);
+ skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
+ } else {
+ space = 1;
+ }
+ } else {
+ assert(vals[i].kind == BITFIELD);
+ obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
+ }
+
+ ++i;
+ space = 0;
+ while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
+ ++space;
+ ++i;
+ }
+ space -= skip;
+ assert(space >= 0);
+
+ /* a gap */
+ if (space > 0)
+ obstack_printf(obst, "\t.skip\t%d\n", space);
+ }
+ xfree(vals);
+}
+
+/**
+ * Dump a global entity.
+ */
+static void dump_global(ia32_decl_env_t *env, ir_entity *ent, int emit_commons)
+{
+ obstack_t *obst;
+ ir_type *type = get_entity_type(ent);
+ const char *ld_name = get_entity_ld_name(ent);
+ ir_variability variability = get_entity_variability(ent);
+ ir_visibility visibility = get_entity_visibility(ent);
+ int align = get_type_alignment_bytes(type);
+ int emit_as_common = 0;
+
+ obst = env->data_obst;
+ if (is_Method_type(type)) {
+ if (get_method_img_section(ent) == section_constructors) {
+ obst = env->ctor_obst;
+ obstack_printf(obst, ".balign\t%d\n", align);
+ dump_size_type(obst, align);
+ obstack_printf(obst, "%s\n", ld_name);
+ }
+ return;
+ } else if (variability == variability_constant) {
+ /* a constant entity, put it on the rdata */
+ obst = env->rodata_obst;
+ } else if (variability == variability_uninitialized) {
+ /* uninitialized entity put it in bss segment */
+ obst = env->bss_obst;
+ if(emit_commons && visibility != visibility_local)
+ emit_as_common = 1;
+ }
+
+ be_dbg_variable(env->main_env->db_handle, obst, ent);
+
+ /* global or not global */
+ if (visibility == visibility_external_visible && !emit_as_common) {
+ obstack_printf(obst, ".global\t%s\n", ld_name);
+ } else if(visibility == visibility_external_allocated) {
+ obstack_printf(obst, ".global\t%s\n", ld_name);
+ /* we can return now... */
+ return;
+ }
+ /* alignment */
+ if (align > 1 && !emit_as_common) {
+ obstack_printf(obst, ".balign\t%d\n", align);
+ }
+
+ if (!emit_as_common) {
+ obstack_printf(obst, "%s:\n", ld_name);
+ }
+
+ if (variability == variability_uninitialized) {
+ if(emit_as_common) {
+ obstack_printf(obst, "\t.comm %s,%d,%d\n",
+ ld_name, get_type_size_bytes(type), align);
+ } else {
+ obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
+ }
+ } else if (is_atomic_type(type)) {
+ dump_atomic_init(obst, get_atomic_ent_value(ent));
+ } else if (ent_is_string_const(ent)) {
+ dump_string_cst(obst, ent);
+ } else if (is_Array_type(type)) {
+ dump_array_init(obst, ent);
+ } else if (is_compound_type(type)) {
+ dump_compound_init(obst, ent);
+ } else {
+ assert(0 && "unsupported type");
+ }
+}
+
+/**
+ * Dumps declarations of global variables and the initialization code.
+ */
+static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env, int emit_commons)
+{
+ int i, n = get_compound_n_members(gt);
+
+ for (i = 0; i < n; i++) {
+ ir_entity *ent = get_compound_member(gt, i);
+ dump_global(env, ent, emit_commons);
+ }
+}
+
+/************************************************************************/
+
+void be_gas_emit_decls(be_emit_env_t *emit, const be_main_env_t *main_env) {
+ ia32_decl_env_t env;
+ obstack_t rodata, data, bss, ctor;
+ int size;
+ char *cp;
+
+ /* dump the global type */
+ obstack_init(&rodata);
+ obstack_init(&data);
+ obstack_init(&bss);
+ obstack_init(&ctor);
+
+ env.rodata_obst = &rodata;
+ env.data_obst = &data;
+ env.bss_obst = &bss;
+ env.ctor_obst = &ctor;
+ env.main_env = main_env;
+
+ ia32_dump_globals(get_glob_type(), &env, 1);
+
+ size = obstack_object_size(&data);
+ cp = obstack_finish(&data);
+ if (size > 0) {
+ be_gas_emit_switch_section(emit, GAS_SECTION_DATA);
+ be_emit_string_len(emit, cp, size);
+ be_emit_write_line(emit);
+ }
+
+ size = obstack_object_size(&rodata);
+ cp = obstack_finish(&rodata);
+ if (size > 0) {
+ be_gas_emit_switch_section(emit, GAS_SECTION_RODATA);
+ be_emit_string_len(emit, cp, size);
+ be_emit_write_line(emit);
+ }
+
+ size = obstack_object_size(&bss);
+ cp = obstack_finish(&bss);
+ if (size > 0) {
+ be_gas_emit_switch_section(emit, GAS_SECTION_COMMON);
+ be_emit_string_len(emit, cp, size);
+ be_emit_write_line(emit);
+ }
+
+ size = obstack_object_size(&ctor);
+ cp = obstack_finish(&ctor);
+ if (size > 0) {
+ be_gas_emit_switch_section(emit, GAS_SECTION_CTOR);
+ be_emit_string_len(emit, cp, size);
+ be_emit_write_line(emit);
+ }
+
+ obstack_free(&rodata, NULL);
+ obstack_free(&data, NULL);
+ obstack_free(&bss, NULL);
+ obstack_free(&ctor, NULL);
+
+ /* dump the Thread Local Storage */
+ obstack_init(&data);
+
+ env.rodata_obst = &data;
+ env.data_obst = &data;
+ env.bss_obst = &data;
+ env.ctor_obst = NULL;
+
+ ia32_dump_globals(get_tls_type(), &env, 0);
+
+ size = obstack_object_size(&data);
+ cp = obstack_finish(&data);
+ if (size > 0) {
+ be_gas_emit_switch_section(emit, GAS_SECTION_TLS);
+ be_emit_cstring(emit, ".balign\t32\n");
+ be_emit_write_line(emit);
+ be_emit_string_len(emit, cp, size);
+ be_emit_write_line(emit);
+ }
+
+ obstack_free(&data, NULL);
+}
--- /dev/null
+/**
+ * Header for ia32 assembler declarations dumper.
+ * @author Christian Wuerdig, Matthias Braun
+ * $Id$
+ */
+#ifndef _BE_GEN_DECLS_H_
+#define _BE_GEN_DECLS_H_
+
+#include "be.h"
+#include "beemitter.h"
+
+/**
+ * Sections.
+ */
+typedef enum section_t {
+ GAS_SECTION_TEXT = 0, /**< text section */
+ GAS_SECTION_DATA = 1, /**< data section */
+ GAS_SECTION_RODATA = 2, /**< rodata section */
+ GAS_SECTION_COMMON = 3, /**< common section */
+ GAS_SECTION_TLS = 4, /**< thread local storage section */
+ GAS_SECTION_CTOR = 5, /**< ctor section for instrumentation code init */
+ GAS_SECTION_MAX = 6
+} be_gas_section_t;
+
+typedef enum asm_flavour_t {
+ GAS_FLAVOUR_NORMAL = 0, /**< normal gas */
+ GAS_FLAVOUR_MINGW = 1, /**< MinGW variant */
+ GAS_FLAVOUR_MAX = 2
+} be_gas_flavour_t;
+
+extern be_gas_flavour_t be_gas_flavour;
+
+
+/**
+ * Generate all entities.
+ */
+void be_gas_emit_decls(be_emit_env_t *env, const be_main_env_t *main_env);
+
+void be_gas_emit_switch_section(be_emit_env_t *env, be_gas_section_t section);
+
+#endif
#include "debug.h"
#include "irtools.h"
#include "irdump.h"
+#include "irprintf.h"
#include "plist.h"
#include "irprintf.h"
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "irgraph_t.h"
#include "besched_t.h"
#include "beinsn_t.h"
#include "beabi.h"
+#include "raw_bitset.h"
be_insn_t *be_scan_insn(const be_insn_env_t *env, ir_node *irn)
{
for(p = sched_next(irn); is_Proj(p); p = sched_next(p)) {
if(arch_irn_consider_in_reg_alloc(arch_env, env->cls, p)) {
- arch_get_register_req(arch_env, &o.req, p, -1);
+ o.req = arch_get_register_req(arch_env, p, -1);
o.carrier = p;
o.irn = irn;
o.pos = -(get_Proj_proj(p) + 1);
o.partner = NULL;
- o.has_constraints = arch_register_req_is(&o.req, limited);
+ o.has_constraints = arch_register_req_is(o.req, limited);
obstack_grow(obst, &o, sizeof(o));
insn->n_ops++;
insn->out_constraints |= o.has_constraints;
}
insn->next_insn = p;
- }
- else if(arch_irn_consider_in_reg_alloc(arch_env, env->cls, irn)) {
- arch_get_register_req(arch_env, &o.req, irn, -1);
+ } else if(arch_irn_consider_in_reg_alloc(arch_env, env->cls, irn)) {
+ o.req = arch_get_register_req(arch_env, irn, -1);
o.carrier = irn;
o.irn = irn;
o.pos = -1;
o.partner = NULL;
- o.has_constraints = arch_register_req_is(&o.req, limited);
+ o.has_constraints = arch_register_req_is(o.req, limited);
obstack_grow(obst, &o, sizeof(o));
insn->n_ops++;
insn->out_constraints |= o.has_constraints;
pre_colored += arch_get_irn_register(arch_env, irn) != NULL;
}
- insn->pre_colored = pre_colored == insn->n_ops && insn->n_ops > 0;
+ if(pre_colored > 0) {
+ assert(pre_colored == insn->n_ops && "partly pre-colored nodes not supported");
+ insn->pre_colored = 1;
+ }
insn->use_start = insn->n_ops;
for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
if(!arch_irn_consider_in_reg_alloc(arch_env, env->cls, op))
continue;
- arch_get_register_req(arch_env, &o.req, irn, i);
+ o.req = arch_get_register_req(arch_env, irn, i);
o.carrier = op;
o.irn = irn;
o.pos = i;
o.partner = NULL;
- o.has_constraints = arch_register_req_is(&o.req, limited);
+ o.has_constraints = arch_register_req_is(o.req, limited);
obstack_grow(obst, &o, sizeof(o));
insn->n_ops++;
insn->in_constraints |= o.has_constraints;
/* Compute the admissible registers bitsets. */
for (i = 0; i < insn->n_ops; ++i) {
be_operand_t *op = &insn->ops[i];
+ const arch_register_req_t *req = op->req;
- if (op->req.cls == NULL && op->req.type == arch_register_req_type_none) {
- op->req.cls = env->cls;
- op->req.type = arch_register_req_type_normal;
+#if 0
+ // Matze: can we do without this?
+ if (req->cls == NULL && req->type == arch_register_req_type_none) {
+ req->cls = env->cls;
+ req->type = arch_register_req_type_normal;
}
+#endif
+
+ assert(req->cls == env->cls);
- assert(op->req.cls == env->cls);
op->regs = bitset_obstack_alloc(obst, env->cls->n_regs);
- if (arch_register_req_is(&op->req, limited))
- op->req.limited(op->req.limited_env, op->regs);
- else {
+ if (arch_register_req_is(req, limited)) {
+ rbitset_copy_to_bitset(req->limited, op->regs);
+ } else {
arch_put_non_ignore_regs(arch_env, env->cls, op->regs);
if (env->ignore_colors)
bitset_andnot(op->regs, env->ignore_colors);
ie->obst = obst;
ie->ignore_colors = bitset_obstack_alloc(obst, cls->n_regs);
be_abi_put_ignore_regs(birg->abi, cls, ie->ignore_colors);
+
return ie;
}
typedef struct _be_insn_env_t be_insn_env_t;
struct _be_operand_t {
- ir_node *irn;
- ir_node *carrier;
- be_operand_t *partner;
- bitset_t *regs;
- int pos;
- arch_register_req_t req;
- unsigned has_constraints : 1;
+ ir_node *irn; /**< firm node of the insn this operand blongs to */
+ ir_node *carrier; /**< node representing the operand value (proj or the node itself for defs, the value itself for uses */
+ be_operand_t *partner; /**< used in bechordal later... (TODO what does it do?) */
+ bitset_t *regs; /**< admissible register bitset */
+ int pos; /**< pos of the operand (0 to n are inputs, -1 to -n are outputs) */
+ const arch_register_req_t *req; /**< register constraints for the carrier node */
+ unsigned has_constraints : 1; /**< the carrier node has register constraints (the constraint type is limited) */
};
struct _be_insn_t {
- be_operand_t *ops;
- int n_ops;
- int use_start;
- ir_node *next_insn;
- ir_node *irn;
- unsigned in_constraints : 1;
- unsigned out_constraints : 1;
- unsigned has_constraints : 1;
- unsigned pre_colored : 1;
+ be_operand_t *ops; /**< the values used and defined by the insn */
+ int n_ops; /**< length of the ops array */
+ int use_start; /**< entries [0-use_start) in ops are defs,
+ [use_start-n_ops) uses */
+ ir_node *next_insn; /**< next instruction in schedule */
+ ir_node *irn; /**< ir_node of the instruction */
+ unsigned in_constraints : 1; /**< instruction has input contraints */
+ unsigned out_constraints : 1; /**< instruction has output constraints */
+ unsigned has_constraints : 1; /**< in_constraints or out_constraints true */
+ unsigned pre_colored : 1; /**< all defined values already have a register assigned */
};
struct _be_insn_env_t {
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <stdlib.h>
#include "beirgmod.h"
-#define DBG_MODULE "firm.be.irgmod"
#define DBG_LEVEL SET_LEVEL_0
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/*
____ _
{
ir_node *bl;
waitq *worklist = new_waitq();
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, DBG_MODULE);
/*
* Fill the worklist queue and the rest of the orig blocks array.
{
ir_node *curr_bl;
ir_node *start_irn;
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, DBG_MODULE);
curr_bl = get_nodes_block(usage);
int pos;
} *outs;
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, DBG_MODULE);
-
obstack_init(&obst);
/*
int save_optimize = get_optimize();
int save_normalize = get_opt_normalize();
int phis_set_created = 0;
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, DBG_MODULE);
ir_node *irn;
ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_graph *irg = get_irn_irg(bl);
pset *live = pset_new_ptr_default();
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, "be.node");
ir_node *curr, *irn, *perm, **nodes;
int i, n;
}
return changed;
}
+
+void be_init_irgmod(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.irgmod");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_irgmod);
* @author Sebastian Hack
* @cvs-id $Id$
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <stdio.h>
#include <libcore/lc_opts.h>
#include <libcore/lc_opts_enum.h>
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL);
+
#define BE_SCHED_NODE(irn) (be_is_Keep(irn) || be_is_CopyKeep(irn) || be_is_RegParams(irn))
enum {
nodeset *live; /**< simple liveness during scheduling */
const list_sched_selector_t *selector;
void *selector_block_env;
- DEBUG_ONLY(firm_dbg_module_t *dbg;)
} block_sched_env_t;
/**
if (env->selector->node_ready)
env->selector->node_ready(env->selector_block_env, irn, pred);
- DB((env->dbg, LEVEL_2, "\tmaking ready: %+F\n", irn));
+ DB((dbg, LEVEL_2, "\tmaking ready: %+F\n", irn));
return 1;
}
update_sched_liveness(env, irn);
sched_add_before(env->block, irn);
- DBG((env->dbg, LEVEL_2, "\tadding %+F\n", irn));
+ DBG((dbg, LEVEL_2, "\tadding %+F\n", irn));
}
/* notify the selector about the finally selected node. */
be.live = new_nodeset(get_irn_n_edges(block));
be.selector = selector;
be.sched_env = env;
- FIRM_DBG_REGISTER(be.dbg, "firm.be.sched");
- DBG((be.dbg, LEVEL_1, "scheduling %+F\n", block));
+ DBG((dbg, LEVEL_1, "scheduling %+F\n", block));
if (selector->init_block)
be.selector_block_env = selector->init_block(env->selector_env, block);
/* Make the node ready, if all operands live in a foreign block */
if (ready) {
- DBG((be.dbg, LEVEL_2, "\timmediately ready: %+F\n", irn));
+ DBG((dbg, LEVEL_2, "\timmediately ready: %+F\n", irn));
make_ready(&be, NULL, irn);
}
}
irn = be.selector->select(be.selector_block_env, be.cands, be.live);
}
- DB((be.dbg, LEVEL_2, "\tpicked node %+F\n", irn));
+ DB((dbg, LEVEL_2, "\tpicked node %+F\n", irn));
/* Add the node to the schedule. */
add_to_sched(&be, irn);
lc_opt_entry_t *sched_grp = lc_opt_get_grp(be_grp, "listsched");
lc_opt_add_table(sched_grp, list_sched_option_table);
+
+ FIRM_DBG_REGISTER(dbg, "firm.be.sched");
}
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_listsched);
* @date 6.12.2004
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "impl.h"
#include "beutil.h"
#include "belive_t.h"
#include "besched_t.h"
+#include "bemodule.h"
-#define DBG_MODULE "firm.be.liveness"
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
#define LV_STD_SIZE 128
#define LV_USE_BINARY_SEARCH
payload[n - 1].u.node.flags = 0;
--irn_live[0].u.head.n_members;
- DBG((li->dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
+ DBG((dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
return 1;
}
}
static INLINE void mark_live_in(be_lv_t *lv, ir_node *block, ir_node *irn)
{
struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
- DBG((lv->dbg, LEVEL_2, "marking %+F live in at %+F\n", irn, block));
+ DBG((dbg, LEVEL_2, "marking %+F live in at %+F\n", irn, block));
n->flags |= be_lv_state_in;
register_node(lv, irn);
}
static INLINE void mark_live_out(be_lv_t *lv, ir_node *block, ir_node *irn)
{
struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
- DBG((lv->dbg, LEVEL_2, "marking %+F live out at %+F\n", irn, block));
+ DBG((dbg, LEVEL_2, "marking %+F live out at %+F\n", irn, block));
n->flags |= be_lv_state_out | be_lv_state_end;
register_node(lv, irn);
}
static INLINE void mark_live_end(be_lv_t *lv, ir_node *block, ir_node *irn)
{
struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
- DBG((lv->dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
+ DBG((dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
n->flags |= be_lv_state_end;
register_node(lv, irn);
}
be_lv_t *lv = xmalloc(sizeof(lv[0]));
memset(lv, 0, sizeof(lv[0]));
- FIRM_DBG_REGISTER(lv->dbg, DBG_MODULE);
lv->irg = irg;
lv->nodes = bitset_malloc(2 * get_irg_last_idx(irg));
lv->hook_info.context = lv;
pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live)
{
int i, n;
- FIRM_DBG_REGISTER(firm_dbg_module_t *dbg, DBG_MODULE);
-
- DEBUG_ONLY(
- const ir_node *x;
- DBG((dbg, LEVEL_1, "%+F\n", irn));
- for(x = pset_first(live); x; x = pset_next(live))
- DBG((dbg, LEVEL_1, "\tlive: %+F\n", x));
- )
/* You should better break out of your loop when hitting the first phi function. */
assert(!is_Phi(irn) && "liveness_transfer produces invalid results for phi nodes");
return live;
}
+
+void be_init_live(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live);
ir_graph *irg;
bitset_t *nodes;
hook_entry_t hook_info;
- DEBUG_ONLY(firm_dbg_module_t *dbg;)
};
struct _be_lv_info_node_t {
* Compute register pressure in loops
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "set.h"
#include "belive.h"
#include "besched.h"
#include "beloopana.h"
+#include "bemodule.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL);
#define HASH_LOOP_INFO(info) (HASH_PTR((info)->loop) ^ HASH_PTR((info)->cls))
struct _be_loopana_t {
set *data;
be_irg_t *birg;
- DEBUG_ONLY(firm_dbg_module_t *dbg);
};
static int cmp_loop_info(const void *a, const void *b, size_t sz) {
ir_node *irn;
int max_live;
- DBG((loop_ana->dbg, LEVEL_1, "Processing Block %+F\n", block));
+ DBG((dbg, LEVEL_1, "Processing Block %+F\n", block));
/* determine largest pressure with this block */
live_nodes = be_liveness_end_of_block(loop_ana->birg->lv, aenv, cls, block, live_nodes);
max_live = MAX(cnt, max_live);
}
- DBG((loop_ana->dbg, LEVEL_1, "Finished with Block %+F (%s %u)\n", block, cls->name, max_live));
+ DBG((dbg, LEVEL_1, "Finished with Block %+F (%s %u)\n", block, cls->name, max_live));
del_pset(live_nodes);
return max_live;
unsigned pressure;
be_loop_info_t *entry, key;
- DBG((loop_ana->dbg, LEVEL_1, "\nProcessing Loop %d\n", loop->loop_nr));
+ DBG((dbg, LEVEL_1, "\nProcessing Loop %d\n", loop->loop_nr));
assert(get_loop_n_elements(loop) > 0);
pressure = 0;
pressure = MAX(pressure, son_pressure);
}
- DBG((loop_ana->dbg, LEVEL_1, "Done with loop %d, pressure %u for class %s\n", loop->loop_nr, pressure, cls->name));
+ DBG((dbg, LEVEL_1, "Done with loop %d, pressure %u for class %s\n", loop->loop_nr, pressure, cls->name));
/* update info in set */
key.loop = loop;
loop_ana->data = new_set(cmp_loop_info, 16);
loop_ana->birg = birg;
- FIRM_DBG_REGISTER(loop_ana->dbg, "firm.be.loopana");
- DBG((loop_ana->dbg, LEVEL_1, "\n=====================================================\n", cls->name));
- DBG((loop_ana->dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
- DBG((loop_ana->dbg, LEVEL_1, "=====================================================\n", cls->name));
+ DBG((dbg, LEVEL_1, "\n=====================================================\n", cls->name));
+ DBG((dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
+ DBG((dbg, LEVEL_1, "=====================================================\n", cls->name));
be_compute_loop_pressure(loop_ana, get_irg_loop(birg->irg), cls);
loop_ana->data = new_set(cmp_loop_info, 16);
loop_ana->birg = birg;
- FIRM_DBG_REGISTER(loop_ana->dbg, "firm.be.loopana");
for (i = arch_isa_get_n_reg_class(birg->main_env->arch_env->isa) - 1; i >= 0; --i) {
const arch_register_class_t *cls = arch_isa_get_reg_class(birg->main_env->arch_env->isa, i);
- DBG((loop_ana->dbg, LEVEL_1, "\n=====================================================\n", cls->name));
- DBG((loop_ana->dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
- DBG((loop_ana->dbg, LEVEL_1, "=====================================================\n", cls->name));
+ DBG((dbg, LEVEL_1, "\n=====================================================\n", cls->name));
+ DBG((dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
+ DBG((dbg, LEVEL_1, "=====================================================\n", cls->name));
be_compute_loop_pressure(loop_ana, irg_loop, cls);
}
del_set(loop_ana->data);
xfree(loop_ana);
}
+
+void be_init_loopana(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.loopana");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_loopana);
*/
static void assure_different_constraints(ir_node *irn, constraint_env_t *env) {
const arch_register_req_t *req;
- arch_register_req_t req_temp;
- req = arch_get_register_req(env->birg->main_env->arch_env, &req_temp, irn, -1);
+ req = arch_get_register_req(env->birg->main_env->arch_env, irn, -1);
- if (req) {
- if (arch_register_req_is(req, should_be_different)) {
- gen_assure_different_pattern(irn, req->other_different, env);
- }
- else if (arch_register_req_is(req, should_be_different_from_all)) {
- int i, n = get_irn_arity(belower_skip_proj(irn));
- for (i = 0; i < n; i++) {
- gen_assure_different_pattern(irn, get_irn_n(belower_skip_proj(irn), i), env);
- }
+ if (arch_register_req_is(req, should_be_different)) {
+ ir_node *different_from = get_irn_n(irn, req->other_different);
+ gen_assure_different_pattern(irn, different_from, env);
+ } else if (arch_register_req_is(req, should_be_different_from_all)) {
+ int i, n = get_irn_arity(belower_skip_proj(irn));
+ for (i = 0; i < n; i++) {
+ gen_assure_different_pattern(irn, get_irn_n(belower_skip_proj(irn), i), env);
}
}
}
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
void be_init_spillmorgan(void);
void be_init_spillremat(void);
void be_init_ifg(void);
+void be_init_irgmod(void);
+void be_init_loopana(void);
+void be_init_spillslots(void);
+void be_init_live(void);
void be_quit_copystat(void);
return;
run_once = 1;
+ be_init_irgmod();
+ be_init_loopana();
+ be_init_live();
+ be_init_spillslots();
be_init_sched();
be_init_blocksched();
be_init_spill();
be_init_ifg();
be_init_arch_ia32();
-#if 0
be_init_arch_ppc32();
be_init_arch_mips();
be_init_arch_arm();
-#endif
#ifdef WITH_ILP
be_init_ilpsched();
#include "fourcc.h"
#include "offset.h"
#include "bitfiddle.h"
+#include "raw_bitset.h"
#include "irop_t.h"
#include "irmode_t.h"
static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
-typedef enum {
- be_req_kind_old_limited,
- be_req_kind_negate_old_limited,
- be_req_kind_single_reg
-} be_req_kind_t;
-
typedef struct {
arch_register_req_t req;
- be_req_kind_t kind;
arch_irn_flags_t flags;
- union {
- struct {
- void (*old_limited)(void *ptr, bitset_t *bs);
- void *old_limited_env;
- } old_limited;
-
- const arch_register_t *single_reg;
- } x;
} be_req_t;
typedef struct {
const arch_register_t *reg;
- be_req_t req;
- be_req_t in_req;
+ be_req_t req;
+ be_req_t in_req;
} be_reg_data_t;
/** The generic be nodes attribute type. */
return 1;
}
+static INLINE be_req_t *get_be_req(const ir_node *node, int pos)
+{
+ int idx;
+ be_node_attr_t *attr;
+ be_reg_data_t *rd;
+
+ assert(is_be_node(node));
+ attr = get_irn_attr(node);
+
+ if(pos < 0) {
+ idx = -(pos + 1);
+ } else {
+ idx = pos;
+ assert(idx < get_irn_arity(node));
+ }
+ assert(idx < ARR_LEN(attr->reg_data));
+ rd = &attr->reg_data[idx];
+
+ return pos < 0 ? &rd->req : &rd->in_req;
+}
+
+static inline arch_register_req_t *get_req(const ir_node *node, int pos)
+{
+ be_req_t *bereq = get_be_req(node, pos);
+ return &bereq->req;
+}
+
void be_node_init(void) {
static int inited = 0;
return 0;
}
-static be_node_attr_t *retrieve_irn_attr(const ir_node *irn, int *the_pos)
+static be_reg_data_t *retrieve_reg_data(const ir_node *node)
{
- int dummy;
- be_node_attr_t *res = NULL;
- int *pos = the_pos ? the_pos : &dummy;
-
- *pos = -1;
- if(is_Proj(irn)) {
- ir_node *pred = get_Proj_pred(irn);
- int p = get_Proj_proj(irn);
+ be_node_attr_t *attr;
+ int pos = 0;
- if(is_be_node(pred)) {
- assert(get_irn_mode(pred) == mode_T);
- *pos = p;
- res = get_irn_attr(pred);
- assert(p >= 0 && p < ARR_LEN(res->reg_data) && "illegal proj number");
- }
- } else if(is_be_node(irn) && get_irn_mode(irn) != mode_T) {
- be_node_attr_t *a = get_irn_attr(irn);
- if(ARR_LEN(a->reg_data) > 0) {
- res = a;
- *pos = 0;
- }
+ if(is_Proj(node)) {
+ pos = get_Proj_proj(node);
+ node = get_Proj_pred(node);
}
- return res;
-}
+ assert(is_be_node(node));
+ attr = get_irn_attr(node);
+ assert(pos >= 0 && pos < ARR_LEN(attr->reg_data) && "illegal proj number");
-static be_reg_data_t *retrieve_reg_data(const ir_node *irn)
-{
- int pos;
- be_node_attr_t *a = retrieve_irn_attr(irn, &pos);
- return a ? &a->reg_data[pos] : NULL;
+ return &attr->reg_data[pos];
}
static void
be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
{
be_reg_data_t *r = retrieve_reg_data(irn);
-
- if(r)
- r->reg = reg;
+ r->reg = reg;
}
-
ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill)
{
assert(be_is_Spill(irn));
return get_irn_n(irn, be_pos_Spill_val);
}
+
ir_node *be_get_Spill_frame(const ir_node *irn)
{
assert(be_is_Spill(irn));
{
ir_node *in[1];
ir_node *res;
+ arch_register_req_t *req;
in[0] = op;
res = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
init_node_attr(res, 1);
be_node_set_reg_class(res, 0, cls);
be_node_set_reg_class(res, OUT_POS(0), cls);
+
+ req = get_req(res, OUT_POS(0));
+ req->cls = cls;
+ req->type = arch_register_req_type_should_be_same;
+ req->other_same = 0;
+
return res;
}
return get_irn_arity(irn) - 1;
}
-static void be_limited(void *data, bitset_t *bs)
+void be_set_constr_single_reg(ir_node *node, int pos, const arch_register_t *reg)
{
- be_req_t *req = data;
-
- switch(req->kind) {
- case be_req_kind_negate_old_limited:
- case be_req_kind_old_limited:
- req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
- if(req->kind == be_req_kind_negate_old_limited)
- bitset_flip_all(bs);
- break;
- case be_req_kind_single_reg:
- bitset_clear_all(bs);
- bitset_set(bs, req->x.single_reg->index);
- break;
- }
-}
-
-static INLINE be_req_t *get_req(ir_node *irn, int pos)
-{
- int idx = pos < 0 ? -(pos + 1) : pos;
- be_node_attr_t *a = get_irn_attr(irn);
- be_reg_data_t *rd = &a->reg_data[idx];
- be_req_t *r = pos < 0 ? &rd->req : &rd->in_req;
-
- assert(is_be_node(irn));
- assert(!(pos >= 0) || pos < get_irn_arity(irn));
- assert(!(pos < 0) || -(pos + 1) <= ARR_LEN(a->reg_data));
+ arch_register_req_t *req = get_req(node, pos);
+ const arch_register_class_t *cls = arch_register_get_class(reg);
+ ir_graph *irg = get_irn_irg(node);
+ struct obstack *obst = get_irg_obstack(irg);
+ unsigned *limited_bitset;
- return r;
-}
+ assert(req->cls == NULL || req->cls == cls);
+ assert(! (req->type & arch_register_req_type_limited));
+ assert(req->limited == NULL);
-void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
-{
- be_req_t *r = get_req(irn, pos);
+ limited_bitset = rbitset_obstack_alloc(obst, arch_register_class_n_regs(cls));
+ rbitset_set(limited_bitset, arch_register_get_index(reg));
- r->kind = be_req_kind_single_reg;
- r->x.single_reg = reg;
- r->req.limited = be_limited;
- r->req.limited_env = r;
- r->req.type = arch_register_req_type_limited;
- r->req.cls = reg->reg_class;
+ req->cls = cls;
+ req->type |= arch_register_req_type_limited;
+ req->limited = limited_bitset;
}
-void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
+void be_set_constr_limited(ir_node *node, int pos, const arch_register_req_t *req)
{
- be_req_t *r = get_req(irn, pos);
+ ir_graph *irg = get_irn_irg(node);
+ struct obstack *obst = get_irg_obstack(irg);
+ arch_register_req_t *r = get_req(node, pos);
assert(arch_register_req_is(req, limited));
-
- r->kind = be_req_kind_old_limited;
- r->req.limited = be_limited;
- r->req.limited_env = r;
- r->req.type = arch_register_req_type_limited;
- r->req.cls = req->cls;
-
- r->x.old_limited.old_limited = req->limited;
- r->x.old_limited.old_limited_env = req->limited_env;
+ assert(! (req->type & (arch_register_req_type_should_be_same | arch_register_req_type_should_be_different)));
+ memcpy(r, req, sizeof(r[0]));
+ r->limited = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
}
void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
{
- be_req_t *r = get_req(irn, pos);
- r->flags = flags;
+ be_req_t *bereq = get_be_req(irn, pos);
+ bereq->flags = flags;
}
void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
{
- be_req_t *r = get_req(irn, pos);
+ arch_register_req_t *req = get_req(irn, pos);
- r->req.cls = cls;
+ req->cls = cls;
if (cls == NULL) {
- r->req.type = arch_register_req_type_none;
- } else if (r->req.type == arch_register_req_type_none) {
- r->req.type = arch_register_req_type_normal;
+ req->type = arch_register_req_type_none;
+ } else if (req->type == arch_register_req_type_none) {
+ req->type = arch_register_req_type_normal;
}
}
void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
{
- be_req_t *r = get_req(irn, pos);
- r->req.type = type;
+ arch_register_req_t *req = get_req(irn, pos);
+ req->type = type;
}
ir_node *be_get_IncSP_pred(ir_node *irn) {
*/
-static void *put_out_reg_req(arch_register_req_t *req, const ir_node *irn, int out_pos)
+static const
+arch_register_req_t *get_out_reg_req(const ir_node *irn, int out_pos)
{
const be_node_attr_t *a = get_irn_attr(irn);
- if(out_pos < ARR_LEN(a->reg_data)) {
- memcpy(req, &a->reg_data[out_pos].req, sizeof(req[0]));
-
- if(be_is_Copy(irn)) {
- req->type |= arch_register_req_type_should_be_same;
- req->other_same = be_get_Copy_op(irn);
- }
- } else {
- req->type = arch_register_req_type_none;
- req->cls = NULL;
+ if(out_pos >= ARR_LEN(a->reg_data)) {
+ return arch_no_register_req;
}
- return req;
+ return &a->reg_data[out_pos].req.req;
}
-static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
+static const
+arch_register_req_t *get_in_reg_req(const ir_node *irn, int pos)
{
const be_node_attr_t *a = get_irn_attr(irn);
- if(pos < get_irn_arity(irn) && pos < ARR_LEN(a->reg_data)) {
- memcpy(req, &a->reg_data[pos].in_req, sizeof(req[0]));
- } else {
- req->type = arch_register_req_type_none;
- req->cls = NULL;
- }
+ if(pos >= get_irn_arity(irn) || pos >= ARR_LEN(a->reg_data))
+ return arch_no_register_req;
- return req;
+ return &a->reg_data[pos].in_req.req;
}
static const arch_register_req_t *
-be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
+be_node_get_irn_reg_req(const void *self, const ir_node *irn, int pos)
{
int out_pos = pos;
if (pos < 0) {
if (get_irn_mode(irn) == mode_T)
- return NULL;
+ return arch_no_register_req;
out_pos = redir_proj((const ir_node **)&irn);
assert(is_be_node(irn));
- return put_out_reg_req(req, irn, out_pos);
- }
-
- else {
- if (is_be_node(irn)) {
- /*
- For spills and reloads, we return "none" as requirement for frame pointer,
- so every input is ok. Some backends need this (e.g. STA). We use an arbitrary
- large number as pos, so put_in_reg_req will return "none" as requirement.
- */
- if ((be_is_Spill(irn) && pos == be_pos_Spill_frame) ||
+ return get_out_reg_req(irn, out_pos);
+ } else if (is_be_node(irn)) {
+ /*
+ * For spills and reloads, we return "none" as requirement for frame
+ * pointer, so every input is ok. Some backends need this (e.g. STA).
+ */
+ if ((be_is_Spill(irn) && pos == be_pos_Spill_frame) ||
(be_is_Reload(irn) && pos == be_pos_Reload_frame))
- return put_in_reg_req(req, irn, INT_MAX);
- else
- return put_in_reg_req(req, irn, pos);
- }
- return NULL;
+ return arch_no_register_req;
+
+ return get_in_reg_req(irn, pos);
}
- return req;
+ return arch_no_register_req;
}
const arch_register_t *
be_node_get_irn_reg(const void *_self, const ir_node *irn)
{
be_reg_data_t *r = retrieve_reg_data(irn);
- return r ? r->reg : NULL;
+ return r->reg;
}
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
return 0;
}
-static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
+static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *node)
{
- be_reg_data_t *r = retrieve_reg_data(irn);
- return r ? r->req.flags : 0;
+ be_req_t *bereq;
+ int pos = -1;
+
+ if(is_Proj(node)) {
+ pos = OUT_POS(get_Proj_proj(node));
+ node = skip_Proj_const(node);
+ }
+
+ bereq = get_be_req(node, pos);
+
+ return bereq->flags;
}
static ir_entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
*/
+typedef struct {
+ const arch_register_t *reg;
+ arch_register_req_t req;
+} phi_attr_t;
+
typedef struct {
arch_irn_handler_t irn_handler;
arch_irn_ops_t irn_ops;
const arch_env_t *arch_env;
- pmap *regs;
+ pmap *phi_attrs;
} phi_handler_t;
#define get_phi_handler_from_handler(h) container_of(h, phi_handler_t, irn_handler)
return is_Phi(irn) && mode_is_datab(get_irn_mode(irn)) ? &h->irn_ops : NULL;
}
+static INLINE phi_attr_t *get_Phi_attr(const phi_handler_t *handler,
+ const ir_node *phi)
+{
+ phi_attr_t *attr = pmap_get(handler->phi_attrs, (void*) phi);
+ if(attr == NULL) {
+ ir_graph *irg = get_irn_irg(phi);
+ struct obstack *obst = get_irg_obstack(irg);
+ attr = obstack_alloc(obst, sizeof(attr[0]));
+ memset(attr, 0, sizeof(attr[0]));
+ pmap_insert(handler->phi_attrs, phi, attr);
+ }
+
+ return attr;
+}
+
/**
* Get register class of a Phi.
- *
*/
-static const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h, arch_register_req_t *req, const ir_node *phi, pset **visited)
+static
+const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h,
+ const ir_node *phi,
+ pset **visited)
{
int n = get_irn_arity(phi);
ir_node *op;
for(i = 0; i < n; ++i) {
op = get_irn_n(phi, i);
+ /* Matze: don't we unnecessary constraint our phis with this?
+ * we only need to take the regclass IMO*/
if(!is_Phi(op))
- return arch_get_register_req(h->arch_env, req, op, BE_OUT_POS(0));
+ return arch_get_register_req(h->arch_env, op, BE_OUT_POS(0));
}
/*
- The operands of that Phi were all Phis themselves.
- We have to start a DFS for a non-Phi argument now.
- */
+ * The operands of that Phi were all Phis themselves.
+ * We have to start a DFS for a non-Phi argument now.
+ */
if(!*visited)
*visited = pset_new_ptr(16);
pset_insert_ptr(*visited, phi);
for(i = 0; i < n; ++i) {
+ const arch_register_req_t *req;
op = get_irn_n(phi, i);
- if(get_Phi_reg_req_recursive(h, req, op, visited))
+ req = get_Phi_reg_req_recursive(h, op, visited);
+ if(req != NULL)
return req;
}
return NULL;
}
-static const arch_register_req_t *phi_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
+static
+const arch_register_req_t *phi_get_irn_reg_req(const void *self,
+ const ir_node *irn, int pos)
{
phi_handler_t *phi_handler = get_phi_handler_from_ops(self);
- pset *visited = NULL;
+ phi_attr_t *attr;
+
+ if(!mode_is_datab(get_irn_mode(irn)))
+ return arch_no_register_req;
+
+ attr = get_Phi_attr(phi_handler, irn);
- get_Phi_reg_req_recursive(phi_handler, req, irn, &visited);
- /* Set the requirements type to normal, since an operand of the Phi could have had constraints. */
- req->type = arch_register_req_type_normal;
- if(visited)
- del_pset(visited);
+ if(attr->req.type == arch_register_req_type_none) {
+ pset *visited = NULL;
+ const arch_register_req_t *req;
+ req = get_Phi_reg_req_recursive(phi_handler, irn, &visited);
- return req;
+ memcpy(&attr->req, req, sizeof(req[0]));
+ assert(attr->req.cls != NULL);
+ attr->req.type = arch_register_req_type_normal;
+
+ if(visited != NULL)
+ del_pset(visited);
+ }
+
+ return &attr->req;
}
static void phi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
{
phi_handler_t *h = get_phi_handler_from_ops(self);
- pmap_insert(h->regs, irn, (void *) reg);
+ phi_attr_t *attr = get_Phi_attr(h, irn);
+ attr->reg = reg;
}
static const arch_register_t *phi_get_irn_reg(const void *self, const ir_node *irn)
{
phi_handler_t *h = get_phi_handler_from_ops(self);
- return pmap_get(h->regs, (void *) irn);
+ phi_attr_t *attr = get_Phi_attr(h, irn);
+ return attr->reg;
}
static arch_irn_class_t phi_classify(const void *_self, const ir_node *irn)
h->irn_handler.get_irn_ops = phi_get_irn_ops;
h->irn_ops.impl = &phi_irn_ops;
h->arch_env = arch_env;
- h->regs = pmap_create();
+ h->phi_attrs = pmap_create();
return (arch_irn_handler_t *) h;
}
void be_phi_handler_free(arch_irn_handler_t *handler)
{
phi_handler_t *h = (void *) handler;
- pmap_destroy(h->regs);
+ pmap_destroy(h->phi_attrs);
free(handler);
}
void be_phi_handler_reset(arch_irn_handler_t *handler)
{
phi_handler_t *h = get_phi_handler_from_handler(handler);
- if(h->regs)
- pmap_destroy(h->regs);
- h->regs = pmap_create();
+ if(h->phi_attrs)
+ pmap_destroy(h->phi_attrs);
+ h->phi_attrs = pmap_create();
}
/*
/**
* Dumps a register requirement to a file.
*/
-static void dump_node_req(FILE *f, int idx, be_req_t *req)
+static void dump_node_req(FILE *f, int idx, const arch_register_req_t *req,
+ const ir_node *node)
{
- unsigned i;
int did_something = 0;
char buf[16];
const char *prefix = buf;
snprintf(buf, sizeof(buf), "#%d ", idx);
buf[sizeof(buf) - 1] = '\0';
- if(req->flags != arch_irn_flags_none) {
- fprintf(f, "%sflags: ", prefix);
- prefix = "";
- for(i = arch_irn_flags_none; i <= log2_ceil(arch_irn_flags_last); ++i) {
- if(req->flags & (1 << i)) {
- fprintf(f, "%s%s", prefix, arch_irn_flag_str(1 << i));
- prefix = "|";
- }
- }
- prefix = ", ";
- did_something = 1;
- }
-
- if(req->req.cls != 0) {
+ if(req->cls != 0) {
char tmp[256];
fprintf(f, prefix);
- arch_register_req_format(tmp, sizeof(tmp), &req->req);
+ arch_register_req_format(tmp, sizeof(tmp), req, node);
fprintf(f, "%s", tmp);
did_something = 1;
}
/**
* Dumps node register requirements to a file.
*/
-static void dump_node_reqs(FILE *f, ir_node *irn)
+static void dump_node_reqs(FILE *f, ir_node *node)
{
int i;
- be_node_attr_t *a = get_irn_attr(irn);
+ be_node_attr_t *a = get_irn_attr(node);
int len = ARR_LEN(a->reg_data);
fprintf(f, "registers: \n");
fprintf(f, "#%d: %s\n", i, rd->reg->name);
}
- fprintf(f, "in requirements\n");
+ fprintf(f, "in requirements:\n");
for(i = 0; i < len; ++i) {
- dump_node_req(f, i, &a->reg_data[i].in_req);
+ dump_node_req(f, i, &a->reg_data[i].in_req.req, node);
}
- fprintf(f, "\nout requirements\n");
+ fprintf(f, "\nout requirements:\n");
for(i = 0; i < len; ++i) {
- dump_node_req(f, i, &a->reg_data[i].req);
+ dump_node_req(f, i, &a->reg_data[i].req.req, node);
}
}
be_node_attr_t *old_attr = get_irn_attr(old_node);
be_node_attr_t *new_attr = get_irn_attr(new_node);
struct obstack *obst = get_irg_obstack(get_irn_irg(new_node));
- int i, len;
+ unsigned i, len;
assert(is_be_node(old_node));
assert(is_be_node(new_node));
else
len = 0;
- if(be_is_Keep(old_node) || be_is_RegParams(old_node) || be_is_Barrier(old_node)) {
+ if(get_irn_op(old_node)->opar == oparity_dynamic
+ || be_is_RegParams(old_node)) {
new_attr->reg_data = NEW_ARR_F(be_reg_data_t, len);
} else {
new_attr->reg_data = NEW_ARR_D(be_reg_data_t, obst, len);
if(len > 0) {
memcpy(new_attr->reg_data, old_attr->reg_data, len * sizeof(be_reg_data_t));
-
for(i = 0; i < len; ++i) {
- be_req_t *r;
-
- r = &new_attr->reg_data[i].req;
- r->req.limited_env = r;
-
- r = &new_attr->reg_data[i].in_req;
- r->req.limited_env = r;
+ const be_reg_data_t *rd = &old_attr->reg_data[i];
+ be_reg_data_t *newrd = &new_attr->reg_data[i];
+ if(arch_register_req_is(&rd->req.req, limited)) {
+ const arch_register_req_t *req = &rd->req.req;
+ arch_register_req_t *new_req = &newrd->req.req;
+ new_req->limited
+ = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
+ }
+ if(arch_register_req_is(&rd->in_req.req, limited)) {
+ const arch_register_req_t *req = &rd->in_req.req;
+ arch_register_req_t *new_req = &newrd->in_req.req;
+ new_req->limited
+ = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
+ }
}
}
}
#include "pset.h"
#include "pmap.h"
#include "bitset.h"
+#include "raw_bitset.h"
#include "irprintf_t.h"
#include "irnode_t.h"
be_operand_t *op = &insn->ops[i];
if(op->has_constraints) {
- ir_node *cpy = be_new_Copy(op->req.cls, env->irg, bl, op->carrier);
+ ir_node *cpy = be_new_Copy(op->req->cls, env->irg, bl, op->carrier);
sched_add_before(insn->next_insn, cpy);
edges_reroute(op->carrier, cpy, env->irg);
}
be_operand_t *op = &insn->ops[i];
if(op->has_constraints) {
- ir_node *cpy = be_new_Copy(op->req.cls, env->irg, bl, op->carrier);
+ ir_node *cpy = be_new_Copy(op->req->cls, env->irg, bl, op->carrier);
sched_add_before(insn->irn, cpy);
set_irn_n(insn->irn, op->pos, cpy);
- be_set_constr_limited(cpy, BE_OUT_POS(0), &op->req);
+ be_set_constr_limited(cpy, BE_OUT_POS(0), op->req);
}
}
}
* If yes, dump it to FILE raenv->f
*/
static INLINE void dump_constraint(be_raext_env_t *raenv, ir_node *irn, int pos) {
- bitset_t *bs = bitset_alloca(raenv->cls->n_regs);
- arch_register_req_t req;
-
- arch_get_register_req(raenv->aenv, &req, irn, pos);
- if (arch_register_req_is(&req, limited)) {
- int reg_nr;
- req.limited(req.limited_env, bs);
- reg_nr = bitset_next_set(bs, 0);
+ const arch_register_req_t *req;
+
+ req = arch_get_register_req(raenv->aenv, irn, pos);
+ if (arch_register_req_is(req, limited)) {
+ unsigned reg_nr;
+
+ reg_nr = rbitset_next(req->limited, 0, 1);
fprintf(raenv->f, "<%d>", reg_nr);
- assert(-1 == bitset_next_set(bs, reg_nr+1) && "Constraints with more than 1 possible register are not supported");
+ assert(rbitset_popcnt(req->limited, raenv->cls->n_regs) <= 1
+ && "Constraints with more than 1 possible register are not supported");
}
}
static void dump_affinities_walker(ir_node *irn, void *env) {
be_raext_env_t *raenv = env;
- arch_register_req_t req;
+ const arch_register_req_t *req;
int pos, max;
be_var_info_t *vi1, *vi2;
/* should_be_equal constraints are affinites */
for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
- arch_get_register_req(raenv->aenv, &req, irn, pos);
+ req = arch_get_register_req(raenv->aenv, irn, pos);
- if (arch_register_req_is(&req, should_be_same) && arch_irn_is(raenv->aenv, req.other_same, ignore)) {
- vi2 = be_get_var_info(req.other_same);
+ if (arch_register_req_is(req, should_be_same)) {
+ ir_node *other = get_irn_n(irn, req->other_same);
+ if(arch_irn_is(raenv->aenv, other, ignore)) {
+ vi2 = be_get_var_info(other);
- fprintf(raenv->f, "(%d, %d, %d)\n", vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
+ fprintf(raenv->f, "(%d, %d, %d)\n", vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
+ }
}
}
}
be_next_use_t next_use;
loc_t loc;
loc.time = USES_INFINITY;
+ loc.irn = node;
if (!arch_irn_consider_in_reg_alloc(env->arch, env->cls, node)) {
loc.time = USES_INFINITY;
return loc;
}
- loc.irn = node;
-
/* We have to keep nonspillable nodes in the workingset */
if(arch_irn_get_flags(env->arch, node) & arch_irn_flags_dont_spill) {
loc.time = 0;
belady_env_t env;
ir_graph *irg = be_get_birg_irg(birg);
- FIRM_DBG_REGISTER(dbg, "firm.be.spill.belady");
- //firm_dbg_set_mask(dbg, DBG_SPILL);
-
be_invalidate_liveness(birg);
be_assure_liveness(birg);
/* construct control flow loop tree */
};
be_register_spiller("belady", &belady_spiller);
+ FIRM_DBG_REGISTER(dbg, "firm.be.spill.belady");
}
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady);
*
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "bespillmorgan.h"
ir_graph *irg = be_get_birg_irg(birg);
morgan_env_t env;
- FIRM_DBG_REGISTER(dbg, "ir.be.spillmorgan");
- //firm_dbg_set_mask(dbg, DBG_SPILLS | DBG_LOOPANA);
-
be_assure_liveness(birg);
env.arch = birg->main_env->arch_env;
};
be_register_spiller("morgan", &morgan_spiller);
+ FIRM_DBG_REGISTER(dbg, "ir.be.spillmorgan");
}
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillmorgan);
#define REMATS_NOINVERSE 2
#define REMATS_ALL 3
-static int opt_dump_flags = 0;
+static unsigned opt_dump_flags = 0;
static int opt_log = 0;
-static int opt_keep_alive = 0;
+static unsigned opt_keep_alive = 0;
static int opt_goodwin = 1;
static int opt_memcopies = 1;
static int opt_memoperands = 1;
static int opt_verify = VERIFY_MEMINTERF;
-static int opt_remats = REMATS_ALL;
+static unsigned opt_remats = REMATS_ALL;
static int opt_repair_schedule = 0;
static int opt_no_enlarge_liveness = 0;
static int opt_remat_while_live = 1;
pset *used;
pset *remat_defs;
keyval_t *keyval;
- ilp_cst_t one_memoperand;
+ ilp_cst_t one_memoperand = -1;
/* iterate only until first phi */
if(is_Phi(irn))
#include "benodesets.h"
#include "bestatevent.h"
#include "bespilloptions.h"
+#include "bemodule.h"
#define DBG_COALESCING 1
#define DBG_INTERFERENCES 2
env->reloads = NEW_ARR_F(ir_node*, 0);
env->affinity_edges = NEW_ARR_F(affinity_edge_t*, 0);
env->memperms = new_set(cmp_memperm, 10);
- FIRM_DBG_REGISTER(dbg, "firm.be.spillslots");
return env;
}
be_free_frame_entity_coalescer(env);
}
+
+void be_init_spillslots(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.spillslots");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillslots);
* @date 11.9.2006
* @cvsid $Id$
*/
-
#ifdef HAVE_CONFIG_H
-# include "config.h"
+# include <config.h>
#endif
#include <stdio.h>
* Released under the GPL
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <limits.h>
#include "../beilpsched.h"
#include "../bespillslots.h"
#include "../bemodule.h"
+#include "../begnuas.h"
#include "bearch_ia32_t.h"
#include "ia32_new_nodes.h" /* ia32 nodes interface */
#include "gen_ia32_regalloc_if.h" /* the generated interface (register type and class defenitions) */
#include "gen_ia32_machine.h"
-#include "ia32_gen_decls.h" /* interface declaration emitter */
#include "ia32_transform.h"
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
#include "ia32_finish.h"
#include "ia32_util.h"
-#define DEBUG_MODULE "firm.be.ia32.isa"
-
/* TODO: ugly */
static set *cur_reg_set = NULL;
* Returns gp_noreg or fp_noreg, depending in input requirements.
*/
ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos) {
- arch_register_req_t req;
- const arch_register_req_t *p_req;
+ const arch_register_req_t *req;
- p_req = arch_get_register_req(cg->arch_env, &req, irn, pos);
- assert(p_req && "Missing register requirements");
- if (p_req->cls == &ia32_reg_classes[CLASS_ia32_gp])
+ req = arch_get_register_req(cg->arch_env, irn, pos);
+ assert(req != NULL && "Missing register requirements");
+ if (req->cls == &ia32_reg_classes[CLASS_ia32_gp])
return ia32_new_NoReg_gp(cg);
- else
- return ia32_new_NoReg_fp(cg);
+
+ return ia32_new_NoReg_fp(cg);
}
/**************************************************
* If the node returns a tuple (mode_T) then the proj's
* will be asked for this information.
*/
-static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
- const ia32_irn_ops_t *ops = self;
- const ia32_register_req_t *irn_req;
- long node_pos = pos == -1 ? 0 : pos;
- ir_mode *mode = is_Block(irn) ? NULL : get_irn_mode(irn);
- FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
-
- if (is_Block(irn) || mode == mode_X) {
- DBG((mod, LEVEL_1, "ignoring Block, mode_M, mode_X node %+F\n", irn));
- return NULL;
+static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
+ const ir_node *node,
+ int pos) {
+ long node_pos = pos == -1 ? 0 : pos;
+ ir_mode *mode = is_Block(node) ? NULL : get_irn_mode(node);
+
+ if (is_Block(node) || mode == mode_X) {
+ return arch_no_register_req;
}
if (mode == mode_T && pos < 0) {
- DBG((mod, LEVEL_1, "ignoring request OUT requirements for node %+F\n", irn));
- return NULL;
+ return arch_no_register_req;
}
- DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
-
- if (is_Proj(irn)) {
+ if (is_Proj(node)) {
if(mode == mode_M)
- return NULL;
+ return arch_no_register_req;
if(pos >= 0) {
- DBG((mod, LEVEL_1, "ignoring request IN requirements for node %+F\n", irn));
- return NULL;
+ return arch_no_register_req;
}
- node_pos = (pos == -1) ? get_Proj_proj(irn) : pos;
- irn = skip_Proj_const(irn);
-
- DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+ node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
+ node = skip_Proj_const(node);
}
- if (is_ia32_irn(irn)) {
- irn_req = (pos >= 0) ? get_ia32_in_req(irn, pos) : get_ia32_out_req(irn, node_pos);
- if (irn_req == NULL) {
- /* no requirements */
- return NULL;
- }
-
- DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
-
- memcpy(req, &(irn_req->req), sizeof(*req));
+ if (is_ia32_irn(node)) {
+ const arch_register_req_t *req;
+ if(pos >= 0)
+ req = get_ia32_in_req(node, pos);
+ else
+ req = get_ia32_out_req(node, node_pos);
- if (arch_register_req_is(&(irn_req->req), should_be_same)) {
- assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
- req->other_same = get_irn_n(irn, irn_req->same_pos);
- }
+ assert(req != NULL);
- if (arch_register_req_is(&(irn_req->req), should_be_different)) {
- assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
- req->other_different = get_irn_n(irn, irn_req->different_pos);
- }
- }
- else {
- /* treat Unknowns like Const with default requirements */
- if (is_Unknown(irn)) {
- DB((mod, LEVEL_1, "returning UKNWN reqs for %+F\n", irn));
- if (mode_is_float(mode)) {
- if (USE_SSE2(ops->cg))
- memcpy(req, &(ia32_default_req_ia32_xmm_xmm_UKNWN), sizeof(*req));
- else
- memcpy(req, &(ia32_default_req_ia32_vfp_vfp_UKNWN), sizeof(*req));
- }
- else if (mode_is_int(mode) || mode_is_reference(mode))
- memcpy(req, &(ia32_default_req_ia32_gp_gp_UKNWN), sizeof(*req));
- else if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring Unknown node %+F\n", irn));
- return NULL;
- }
- else
- assert(0 && "unsupported Unknown-Mode");
- }
- else {
- DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
- req = NULL;
- }
+ return req;
}
- return req;
+ /* unknowns should be transformed already */
+ assert(!is_Unknown(node));
+
+ return arch_no_register_req;
}
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
int pos = 0;
- const ia32_irn_ops_t *ops = self;
if (get_irn_mode(irn) == mode_X) {
return;
}
- DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
-
if (is_Proj(irn)) {
pos = get_Proj_proj(irn);
irn = skip_Proj(irn);
slots = get_ia32_slots(irn);
slots[pos] = reg;
- }
- else {
+ } else {
ia32_set_firm_reg(irn, reg, cur_reg_set);
}
}
const arch_register_t **slots;
slots = get_ia32_slots(irn);
reg = slots[pos];
- }
- else {
+ } else {
reg = ia32_get_firm_reg(irn, cur_reg_set);
}
}
}
- DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias));
-
am_flav = get_ia32_am_flavour(irn);
am_flav |= ia32_O;
set_ia32_am_flavour(irn, am_flav);
ia32_code_gen_t *cg = self;
ir_graph *irg = cg->irg;
- ia32_gen_routine(cg, cg->isa->out, irg);
+ ia32_gen_routine(cg, irg);
cur_reg_set = NULL;
-1, /* stack direction */
NULL, /* main environment */
},
+ {}, /* emitter environment */
NULL, /* 16bit register names */
NULL, /* 8bit register names */
NULL, /* types */
arch_pentium_4, /* optimize for architecture */
fp_sse2, /* use sse2 unit */
NULL, /* current code generator */
- NULL, /* output file */
#ifndef NDEBUG
NULL, /* name obstack */
0 /* name obst size */
isa->opt &= ~IA32_OPT_INCDEC;
}
+ be_emit_init_env(&isa->emit, file_handle);
isa->regs_16bit = pmap_create();
isa->regs_8bit = pmap_create();
isa->types = pmap_create();
isa->tv_ent = pmap_create();
- isa->out = file_handle;
isa->cpu = ia32_init_machine_description();
ia32_build_16bit_reg_map(isa->regs_16bit);
#endif /* NDEBUG */
ia32_handle_intrinsics();
- ia32_switch_section(isa->out, NO_SECTION);
/* needed for the debug support */
- ia32_switch_section(isa->out, SECTION_TEXT);
- fprintf(isa->out, ".Ltext0:\n");
+ be_gas_emit_switch_section(&isa->emit, GAS_SECTION_TEXT);
+ be_emit_cstring(&isa->emit, ".Ltext0:\n");
+ be_emit_write_line(&isa->emit);
inited = 1;
ia32_isa_t *isa = self;
/* emit now all global declarations */
- ia32_gen_decls(isa->out, isa->arch_isa.main_env);
+ be_gas_emit_decls(&isa->emit, isa->arch_isa.main_env);
pmap_destroy(isa->regs_16bit);
pmap_destroy(isa->regs_8bit);
obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */
+ be_emit_destroy_env(&isa->emit);
+
free(self);
}
};
static const lc_opt_enum_int_items_t gas_items[] = {
- { "linux", ASM_LINUX_GAS },
- { "mingw", ASM_MINGW_GAS },
+ { "normal", GAS_FLAVOUR_NORMAL },
+ { "mingw", GAS_FLAVOUR_MINGW },
{ NULL, 0 }
};
static lc_opt_enum_int_var_t gas_var = {
- (int *)&asm_flavour, gas_items
+ (int*) &be_gas_flavour, gas_items
};
static const lc_opt_table_entry_t ia32_options[] = {
#include "../be.h"
#include "../bemachine.h"
+#include "../beemitter.h"
#ifdef NDEBUG
#define SET_IA32_ORIG_NODE(n, o)
*/
struct _ia32_isa_t {
arch_isa_t arch_isa; /**< must be derived from arch_isa_t */
+ be_emit_env_t emit;
pmap *regs_16bit; /**< Contains the 16bits names of the gp registers */
pmap *regs_8bit; /**< Contains the 8bits names of the gp registers */
pmap *types; /**< A map of modes to primitive types */
int opt_arch; /**< optimize for architecture */
int fp_kind; /**< floating point kind */
ia32_code_gen_t *cg; /**< the current code generator */
- FILE *out; /**< output file */
const be_machine_t *cpu; /**< the abstract machine */
#ifndef NDEBUG
struct obstack *name_obst; /**< holds the original node names (for debugging) */
#include "iredges_t.h"
#include "execfreq.h"
#include "error.h"
+#include "raw_bitset.h"
#include "../besched_t.h"
#include "../benode_t.h"
#include "../beabi.h"
#include "../be_dbgout.h"
+#include "../beemitter.h"
+#include "../begnuas.h"
#include "ia32_emitter.h"
#include "gen_ia32_emitter.h"
/* global arch_env for lc_printf functions */
static const arch_env_t *arch_env = NULL;
-/** by default, we generate assembler code for the Linux gas */
-asm_flavour_t asm_flavour = ASM_LINUX_GAS;
-
-/**
- * Switch to a new section
- */
-void ia32_switch_section(FILE *F, section_t sec) {
- static section_t curr_sec = NO_SECTION;
- static const char *text[ASM_MAX][SECTION_MAX] = {
- {
- ".section\t.text",
- ".section\t.data",
- ".section\t.rodata",
- ".section\t.bss",
- ".section\t.tbss,\"awT\",@nobits",
- ".section\t.ctors,\"aw\",@progbits"
- },
- {
- ".section\t.text",
- ".section\t.data",
- ".section .rdata,\"dr\"",
- ".section\t.bss",
- ".section\t.tbss,\"awT\",@nobits",
- ".section\t.ctors,\"aw\",@progbits"
- }
- };
-
- if (curr_sec == sec)
- return;
-
- curr_sec = sec;
- switch (sec) {
-
- case NO_SECTION:
- break;
-
- case SECTION_TEXT:
- case SECTION_DATA:
- case SECTION_RODATA:
- case SECTION_COMMON:
- case SECTION_TLS:
- case SECTION_CTOR:
- fprintf(F, "\t%s\n", text[asm_flavour][sec]);
- break;
-
- default:
- break;
- }
-}
-
-static void ia32_dump_function_object(FILE *F, const char *name)
-{
- switch (asm_flavour) {
- case ASM_LINUX_GAS:
- fprintf(F, "\t.type\t%s, @function\n", name);
- break;
- case ASM_MINGW_GAS:
- fprintf(F, "\t.def\t%s;\t.scl\t2;\t.type\t32;\t.endef\n", name);
- break;
- default:
- break;
- }
-}
-
-static void ia32_dump_function_size(FILE *F, const char *name)
-{
- switch (asm_flavour) {
- case ASM_LINUX_GAS:
- fprintf(F, "\t.size\t%s, .-%s\n", name, name);
- break;
- default:
- break;
- }
-}
-
/**
* Returns the register at in position pos.
*/
/* in case of a joker register: just return a valid register */
if (arch_register_type_is(reg, joker)) {
- arch_register_req_t req;
- const arch_register_req_t *p_req;
+ const arch_register_req_t *req;
/* ask for the requirements */
- p_req = arch_get_register_req(arch_env, &req, irn, pos);
+ req = arch_get_register_req(arch_env, irn, pos);
- if (arch_register_req_is(p_req, limited)) {
+ if (arch_register_req_is(req, limited)) {
/* in case of limited requirements: get the first allowed register */
-
- bitset_t *bs = bitset_alloca(arch_register_class_n_regs(p_req->cls));
- int idx;
-
- p_req->limited(p_req->limited_env, bs);
- idx = bitset_next_set(bs, 0);
- reg = arch_register_for_index(p_req->cls, idx);
+ unsigned idx = rbitset_next(req->limited, 0, 1);
+ reg = arch_register_for_index(req->cls, idx);
} else {
/* otherwise get first register in class */
- reg = arch_register_for_index(p_req->cls, 0);
+ reg = arch_register_for_index(req->cls, 0);
}
}
}
}
-#if 0
-/**
- * Determines the SSE suffix depending on the mode.
- */
-static int ia32_print_mode_suffix(lc_appendable_t *app,
- const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
-{
- ir_node *irn = arg->v_ptr;
- ir_mode *mode = get_ia32_ls_mode(irn);
-
- if (mode_is_float(mode)) {
- return lc_appendable_chadd(app, get_mode_size_bits(mode) == 32 ? 's' : 'd');
- } else {
- if(get_mode_size_bits(mode) == 32)
- return 0;
-
- if(mode_is_signed(mode))
- lc_appendable_chadd(app, 's');
- else
- lc_appendable_chadd(app, 'z');
-
- lc_appendable_chadd(app, get_mode_suffix(mode));
- return 2;
- }
-}
-#endif
-
/**
* Add a number to a prefix. This number will not be used a second time.
*/
* |_| |_|
*************************************************************/
-void ia32_emit_ident(ia32_emit_env_t *env, ident *id)
-{
- size_t len = get_id_strlen(id);
- const char* str = get_id_str(id);
-
- ia32_emit_string_len(env, str, len);
-}
-
-void ia32_emit_irprintf(ia32_emit_env_t *env, const char *fmt, ...)
-{
- char buf[128];
- va_list ap;
-
- va_start(ap, fmt);
- ir_vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
-
- ia32_emit_string(env, buf);
-}
+// we have no C++ and can't define an implicit ia32_emit_env_t* cast to
+// be_emit_env_t* so we cheat a bit...
+#define be_emit_char(env,c) be_emit_char(env->emit,c)
+#define be_emit_string(env,s) be_emit_string(env->emit,s)
+#undef be_emit_cstring
+#define be_emit_cstring(env,x) { be_emit_string_len(env->emit, x, sizeof(x)-1); }
+#define be_emit_ident(env,i) be_emit_ident(env->emit,i)
+#define be_emit_write_line(env) be_emit_write_line(env->emit)
+#define be_emit_finish_line_gas(env,n) be_emit_finish_line_gas(env->emit,n)
+#define be_emit_pad_comment(env) be_emit_pad_comment(env->emit)
void ia32_emit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
{
assert(pos < get_irn_arity(node));
- ia32_emit_char(env, '%');
- ia32_emit_string(env, reg_name);
+ be_emit_char(env, '%');
+ be_emit_string(env, reg_name);
}
void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos) {
const arch_register_t *reg = get_out_reg(node, pos);
const char *reg_name = arch_register_get_name(reg);
- ia32_emit_char(env, '%');
- ia32_emit_string(env, reg_name);
+ be_emit_char(env, '%');
+ be_emit_string(env, reg_name);
}
void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
ia32_attr_t *attr = get_ia32_attr(node);
assert(pos < 3);
- ia32_emit_char(env, '%');
- ia32_emit_string(env, attr->x87[pos]->name);
+ be_emit_char(env, '%');
+ be_emit_string(env, attr->x87[pos]->name);
}
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
break;
default:
assert(0);
- ia32_emit_string(env, "BAD");
+ be_emit_string(env, "BAD");
return;
}
- ia32_emit_ident(env, id);
+ be_emit_ident(env, id);
}
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_mode *mode)
{
- ia32_emit_char(env, get_mode_suffix(mode));
+ be_emit_char(env, get_mode_suffix(mode));
}
void ia32_emit_x87_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
ir_mode *mode = get_ia32_ls_mode(node);
assert(mode != NULL);
- ia32_emit_char(env, 's');
- ia32_emit_char(env, get_xmm_mode_suffix(mode));
+ be_emit_char(env, 's');
+ be_emit_char(env, get_xmm_mode_suffix(mode));
}
void ia32_emit_xmm_mode_suffix_s(ia32_emit_env_t *env, const ir_node *node)
{
ir_mode *mode = get_ia32_ls_mode(node);
assert(mode != NULL);
- ia32_emit_char(env, get_xmm_mode_suffix(mode));
+ be_emit_char(env, get_xmm_mode_suffix(mode));
}
void ia32_emit_extend_suffix(ia32_emit_env_t *env, const ir_mode *mode)
if(get_mode_size_bits(mode) == 32)
return;
if(mode_is_signed(mode)) {
- ia32_emit_char(env, 's');
+ be_emit_char(env, 's');
} else {
- ia32_emit_char(env, 'z');
+ be_emit_char(env, 'z');
+ }
+}
+
+static void ia32_emit_function_object(ia32_emit_env_t *env, const char *name)
+{
+ switch (be_gas_flavour) {
+ case GAS_FLAVOUR_NORMAL:
+ be_emit_cstring(env, "\t.type\t");
+ be_emit_string(env, name);
+ be_emit_cstring(env, ", @function\n");
+ be_emit_write_line(env);
+ break;
+ case GAS_FLAVOUR_MINGW:
+ be_emit_cstring(env, "\t.def\t");
+ be_emit_string(env, name);
+ be_emit_cstring(env, ";\t.scl\t2;\t.type\t32;\t.endef\n");
+ be_emit_write_line(env);
+ break;
+ default:
+ break;
+ }
+}
+
+static void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
+{
+ switch (be_gas_flavour) {
+ case GAS_FLAVOUR_NORMAL:
+ be_emit_cstring(env, "\t.size\t");
+ be_emit_string(env, name);
+ be_emit_cstring(env, ", .-");
+ be_emit_string(env, name);
+ be_emit_char(env, '\n');
+ be_emit_write_line(env);
+ break;
+ default:
+ break;
}
}
+
+
/**
* Emits registers and/or address mode of a binary operation.
*/
switch(get_ia32_op_type(node)) {
case ia32_Normal:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
- ia32_emit_char(env, '$');
+ be_emit_char(env, '$');
ia32_emit_immediate(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
} else {
const arch_register_t *in1 = get_in_reg(node, 2);
in_name = "cl";
}
- ia32_emit_char(env, '%');
- ia32_emit_string(env, in_name);
- ia32_emit_cstring(env, ", %");
- ia32_emit_string(env, arch_register_get_name(out));
+ be_emit_char(env, '%');
+ be_emit_string(env, in_name);
+ be_emit_cstring(env, ", %");
+ be_emit_string(env, arch_register_get_name(out));
}
break;
case ia32_AddrModeS:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
assert(!produces_result(node) && "Source AM with Const must not produce result");
ia32_emit_am(env, node);
- ia32_emit_cstring(env, ", $");
+ be_emit_cstring(env, ", $");
ia32_emit_immediate(env, node);
} else if (produces_result(node)) {
ia32_emit_am(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
ia32_emit_am(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
}
break;
case ia32_AddrModeD:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
- ia32_emit_char(env, '$');
+ be_emit_char(env, '$');
ia32_emit_immediate(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
} else {
const arch_register_t *in1 = get_in_reg(node, get_irn_arity(node) == 5 ? 3 : 2);
in_name = "cl";
}
- ia32_emit_char(env, '%');
- ia32_emit_string(env, in_name);
- ia32_emit_cstring(env, ", ");
+ be_emit_char(env, '%');
+ be_emit_string(env, in_name);
+ be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
}
break;
in = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
out = out ? out : in1;
- ia32_emit_char(env, '%');
- ia32_emit_string(env, arch_register_get_name(in));
- ia32_emit_cstring(env, ", %");
- ia32_emit_string(env, arch_register_get_name(out));
+ be_emit_char(env, '%');
+ be_emit_string(env, arch_register_get_name(in));
+ be_emit_cstring(env, ", %");
+ be_emit_string(env, arch_register_get_name(out));
}
break;
case ia32_AddrModeS:
switch(get_ia32_op_type(node)) {
case ia32_Normal:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
- ia32_emit_char(env, '$');
+ be_emit_char(env, '$');
ia32_emit_immediate(env, node);
} else {
if (is_ia32_Mul(node) || is_ia32_IMul1OP(node)) {
/* emit offset */
if (id != NULL) {
if (is_ia32_am_sc_sign(node))
- ia32_emit_char(env, '-');
- ia32_emit_ident(env, id);
+ be_emit_char(env, '-');
+ be_emit_ident(env, id);
}
if(offs != 0) {
if(id != NULL) {
- ia32_emit_irprintf(env, "%+d", offs);
+ be_emit_irprintf(env->emit, "%+d", offs);
} else {
- ia32_emit_irprintf(env, "%d", offs);
+ be_emit_irprintf(env->emit, "%d", offs);
}
}
if (am_flav & (ia32_B | ia32_I)) {
- ia32_emit_char(env, '(');
+ be_emit_char(env, '(');
/* emit base */
if (am_flav & ia32_B) {
/* emit index + scale */
if (am_flav & ia32_I) {
- ia32_emit_char(env, ',');
+ be_emit_char(env, ',');
ia32_emit_source_register(env, node, 1);
if (am_flav & ia32_S) {
- ia32_emit_irprintf(env, ",%d", 1 << get_ia32_am_scale(node));
+ be_emit_irprintf(env->emit, ",%d", 1 << get_ia32_am_scale(node));
}
}
- ia32_emit_char(env, ')');
+ be_emit_char(env, ')');
}
}
-#if 0
-/**
- * Formated print of commands and comments.
- */
-static void ia32_fprintf_format(FILE *F, const ir_node *irn, char *cmd_buf, char *cmnt_buf) {
- unsigned lineno;
- const char *name = irn ? be_retrieve_dbg_info(get_irn_dbg_info((ir_node *)irn), &lineno) : NULL;
-
- if (name)
- fprintf(F, "\t%-35s %-60s /* %s:%u */\n", cmd_buf, cmnt_buf, name, lineno);
- else
- fprintf(F, "\t%-35s %-60s\n", cmd_buf, cmnt_buf);
-}
-#endif
-
-void ia32_write_line(ia32_emit_env_t *env)
-{
- char *finished_line = obstack_finish(env->obst);
-
- fwrite(finished_line, env->linelength, 1, env->out);
- env->linelength = 0;
- obstack_free(env->obst, finished_line);
-}
-
-void ia32_pad_comment(ia32_emit_env_t *env)
-{
- while(env->linelength <= 30) {
- ia32_emit_char(env, ' ');
- }
- ia32_emit_cstring(env, " ");
-}
-
-void ia32_emit_finish_line(ia32_emit_env_t *env, const ir_node *node)
-{
- dbg_info *dbg;
- const char *sourcefile;
- unsigned lineno;
-
- if(node == NULL) {
- ia32_emit_char(env, '\n');
- ia32_write_line(env);
- return;
- }
-
- ia32_pad_comment(env);
- ia32_emit_cstring(env, "/* ");
- ia32_emit_irprintf(env, "%+F ", node);
-
- dbg = get_irn_dbg_info(node);
- sourcefile = be_retrieve_dbg_info(dbg, &lineno);
- if(sourcefile != NULL) {
- ia32_emit_string(env, sourcefile);
- ia32_emit_irprintf(env, ":%u", lineno);
- }
- ia32_emit_cstring(env, " */\n");
- ia32_write_line(env);
-}
-
-
/*************************************************
* _ _ _
* (_) | | |
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
- ia32_emit_string(env, get_cmp_suffix(pnc));
+ be_emit_string(env, get_cmp_suffix(pnc));
}
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
ir_node *block = get_cfop_target_block(node);
- ia32_emit_cstring(env, BLOCK_PREFIX);
- ia32_emit_irprintf(env, "%d", get_irn_node_nr(block));
+ be_emit_cstring(env, BLOCK_PREFIX);
+ be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
}
/** Return the next block in Block schedule */
/* in case of unordered compare, check for parity */
if (pnc & pn_Cmp_Uo) {
- ia32_emit_cstring(env, "\tjp ");
+ be_emit_cstring(env, "\tjp ");
ia32_emit_cfop_target(env, proj_true);
- ia32_emit_finish_line(env, proj_true);
+ be_emit_finish_line_gas(env, proj_true);
}
- ia32_emit_cstring(env, "\tj");
+ be_emit_cstring(env, "\tj");
ia32_emit_cmp_suffix(env, pnc);
- ia32_emit_char(env, ' ');
+ be_emit_char(env, ' ');
ia32_emit_cfop_target(env, proj_true);
- ia32_emit_finish_line(env, proj_true);
+ be_emit_finish_line_gas(env, proj_true);
/* the second Proj might be a fallthrough */
if (get_cfop_target_block(proj_false) != next_block) {
- ia32_emit_cstring(env, "\tjmp ");
+ be_emit_cstring(env, "\tjmp ");
ia32_emit_cfop_target(env, proj_false);
- ia32_emit_finish_line(env, proj_false);
+ be_emit_finish_line_gas(env, proj_false);
} else {
- ia32_emit_cstring(env, "\t/* fallthrough to");
+ be_emit_cstring(env, "\t/* fallthrough to");
ia32_emit_cfop_target(env, proj_false);
- ia32_emit_cstring(env, " */");
- ia32_emit_finish_line(env, proj_false);
+ be_emit_cstring(env, " */");
+ be_emit_finish_line_gas(env, proj_false);
}
}
* Emits code for conditional jump.
*/
static void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "\tcmp ");
+ be_emit_cstring(env, "\tcmp ");
ia32_emit_binop(env, node);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
}
*/
static void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
- ia32_emit_cstring(env, "\ttest $");
+ be_emit_cstring(env, "\ttest $");
ia32_emit_immediate(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
} else {
- ia32_emit_cstring(env, "\ttest ");
+ be_emit_cstring(env, "\ttest ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
}
}
static void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "/* omitted redundant test */");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "/* omitted redundant test */");
+ be_emit_finish_line_gas(env, node);
finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
}
static void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "/* omitted redundant test/cmp */");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "/* omitted redundant test/cmp */");
+ be_emit_finish_line_gas(env, node);
finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
}
* Emits code for conditional SSE floating point jump with two variables.
*/
static void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "\tucomi");
+ be_emit_cstring(env, "\tucomi");
ia32_emit_xmm_mode_suffix(env, node);
- ia32_emit_char(env, ' ');
+ be_emit_char(env, ' ');
ia32_emit_binop(env, node);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
}
reg = attr->x87[0]->name;
case iro_ia32_fcomJmp:
default:
- ia32_emit_cstring(env, "\tfucom ");
+ be_emit_cstring(env, "\tfucom ");
break;
case iro_ia32_fcomrpJmp:
pnc = get_inversed_pnc(pnc);
reg = attr->x87[0]->name;
case iro_ia32_fcompJmp:
- ia32_emit_cstring(env, "\tfucomp ");
+ be_emit_cstring(env, "\tfucomp ");
break;
case iro_ia32_fcomrppJmp:
pnc = get_inversed_pnc(pnc);
case iro_ia32_fcomppJmp:
- ia32_emit_cstring(env, "\tfucompp ");
+ be_emit_cstring(env, "\tfucompp ");
reg = "";
break;
}
if(reg[0] != '\0') {
- ia32_emit_char(env, '%');
- ia32_emit_string(env, reg);
+ be_emit_char(env, '%');
+ be_emit_string(env, reg);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\tfnstsw %ax");
- ia32_emit_finish_line(env, node);
- ia32_emit_cstring(env, "\tsahf");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\tfnstsw %ax");
+ be_emit_finish_line_gas(env, node);
+ be_emit_cstring(env, "\tsahf");
+ be_emit_finish_line_gas(env, node);
finish_CondJmp(env, node, mode_E, pnc);
}
/* we have to emit the cmp first, because the destination register */
/* could be one of the compare registers */
if (is_ia32_CmpCMov(node)) {
- ia32_emit_cstring(env, "\tcmp ");
+ be_emit_cstring(env, "\tcmp ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else if (is_ia32_xCmpCMov(node)) {
- ia32_emit_cstring(env, "\tucomis");
+ be_emit_cstring(env, "\tucomis");
ia32_emit_mode_suffix(env, get_irn_mode(node));
- ia32_emit_char(env, ' ');
+ be_emit_char(env, ' ');
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else if (is_PsiCondCMov) {
/* omit compare because flags are already set by And/Or */
- ia32_emit_cstring(env, "\ttest ");
+ be_emit_cstring(env, "\ttest ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
} else {
assert(0 && "unsupported CMov");
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
if (REGS_ARE_EQUAL(out, in2)) {
/* best case: default in == out -> do nothing */
} else {
/* out is different from in: need copy default -> out */
if (is_PsiCondCMov) {
- ia32_emit_cstring(env, "\tmovl ");
+ be_emit_cstring(env, "\tmovl ");
ia32_emit_dest_register(env, node, 2);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
- ia32_emit_cstring(env, "\tmovl ");
+ be_emit_cstring(env, "\tmovl ");
ia32_emit_source_register(env, node, 3);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
if (is_PsiCondCMov) {
- ia32_emit_cstring(env, "\tcmov");
+ be_emit_cstring(env, "\tcmov");
ia32_emit_cmp_suffix(env, pnc);
- ia32_emit_cstring(env, "l ");
+ be_emit_cstring(env, "l ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
- ia32_emit_cstring(env, "\tcmov");
+ be_emit_cstring(env, "\tcmov");
ia32_emit_cmp_suffix(env, pnc);
- ia32_emit_cstring(env, "l ");
+ be_emit_cstring(env, "l ");
ia32_emit_source_register(env, node, 2);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
static void emit_ia32_CmpCMov(ia32_emit_env_t *env, const ir_node *node) {
reg8bit = ia32_get_mapped_reg_name(env->isa->regs_8bit, out);
if (is_ia32_CmpSet(node)) {
- ia32_emit_cstring(env, "\tcmp ");
+ be_emit_cstring(env, "\tcmp ");
ia32_emit_binop(env, node);
} else if (is_ia32_xCmpSet(node)) {
- ia32_emit_cstring(env, "\tucomis");
+ be_emit_cstring(env, "\tucomis");
ia32_emit_mode_suffix(env, get_irn_mode(get_irn_n(node, 2)));
- ia32_emit_char(env, ' ');
+ be_emit_char(env, ' ');
ia32_emit_binop(env, node);
} else if (is_ia32_PsiCondSet(node)) {
- ia32_emit_cstring(env, "\tcmp $0, ");
+ be_emit_cstring(env, "\tcmp $0, ");
ia32_emit_source_register(env, node, 0);
} else {
assert(0 && "unsupported Set");
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
/* use mov to clear target because it doesn't affect the eflags */
- ia32_emit_cstring(env, "\tmovl $0, %");
- ia32_emit_string(env, arch_register_get_name(out));
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\tmovl $0, %");
+ be_emit_string(env, arch_register_get_name(out));
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\tset");
+ be_emit_cstring(env, "\tset");
ia32_emit_cmp_suffix(env, pnc);
- ia32_emit_cstring(env, " %");
- ia32_emit_string(env, reg8bit);
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, " %");
+ be_emit_string(env, reg8bit);
+ be_emit_finish_line_gas(env, node);
}
static void emit_ia32_CmpSet(ia32_emit_env_t *env, const ir_node *node) {
- and result and stored result
- cleanup stack
*/
- ia32_emit_cstring(env, "\tsubl $8, %esp");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\tsubl $8, %esp");
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\tcmpsd $3, ");
+ be_emit_cstring(env, "\tcmpsd $3, ");
ia32_emit_binop(env, node);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\tmovsd ");
+ be_emit_cstring(env, "\tmovsd ");
ia32_emit_dest_register(env, node, 0);
- ia32_emit_cstring(env, ", (%esp)");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, ", (%esp)");
+ be_emit_finish_line_gas(env, node);
}
- ia32_emit_cstring(env, "\tcmpsd ");
- ia32_emit_irprintf(env, "%d, ", sse_pnc);
+ be_emit_cstring(env, "\tcmpsd ");
+ be_emit_irprintf(env->emit, "%d, ", sse_pnc);
ia32_emit_binop(env, node);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
if (unord && sse_pnc != 3) {
- ia32_emit_cstring(env, "\tandpd (%esp), ");
+ be_emit_cstring(env, "\tandpd (%esp), ");
ia32_emit_dest_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\taddl $8, %esp");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\taddl $8, %esp");
+ be_emit_finish_line_gas(env, node);
}
}
interval = tbl.max_value - tbl.min_value;
/* emit the table */
- ia32_emit_cstring(env, "\tcmpl $");
- ia32_emit_irprintf(env, "%u, ", interval);
+ be_emit_cstring(env, "\tcmpl $");
+ be_emit_irprintf(env->emit, "%u, ", interval);
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
- ia32_emit_cstring(env, "\tja ");
+ be_emit_cstring(env, "\tja ");
ia32_emit_cfop_target(env, tbl.defProj);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
if (tbl.num_branches > 1) {
/* create table */
- ia32_emit_cstring(env, "\tjmp *");
- ia32_emit_string(env, tbl.label);
- ia32_emit_cstring(env, "(,");
+ be_emit_cstring(env, "\tjmp *");
+ be_emit_string(env, tbl.label);
+ be_emit_cstring(env, "(,");
ia32_emit_source_register(env, node, 0);
- ia32_emit_cstring(env, ",4)");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, ",4)");
+ be_emit_finish_line_gas(env, node);
- ia32_switch_section(env->out, SECTION_RODATA);
- ia32_emit_cstring(env, "\t.align 4\n");
- ia32_write_line(env);
+ be_gas_emit_switch_section(env->emit, GAS_SECTION_RODATA);
+ be_emit_cstring(env, "\t.align 4\n");
+ be_emit_write_line(env);
- ia32_emit_string(env, tbl.label);
- ia32_emit_cstring(env, ":\n");
- ia32_write_line(env);
+ be_emit_string(env, tbl.label);
+ be_emit_cstring(env, ":\n");
+ be_emit_write_line(env);
- ia32_emit_cstring(env, ".long ");
+ be_emit_cstring(env, ".long ");
ia32_emit_cfop_target(env, tbl.branches[0].target);
- ia32_emit_finish_line(env, NULL);
+ be_emit_finish_line_gas(env, NULL);
last_value = tbl.branches[0].value;
for (i = 1; i < tbl.num_branches; ++i) {
while (++last_value < tbl.branches[i].value) {
- ia32_emit_cstring(env, ".long ");
+ be_emit_cstring(env, ".long ");
ia32_emit_cfop_target(env, tbl.defProj);
- ia32_emit_finish_line(env, NULL);
+ be_emit_finish_line_gas(env, NULL);
}
- ia32_emit_cstring(env, ".long ");
+ be_emit_cstring(env, ".long ");
ia32_emit_cfop_target(env, tbl.branches[i].target);
- ia32_emit_finish_line(env, NULL);
+ be_emit_finish_line_gas(env, NULL);
}
- ia32_switch_section(env->out, SECTION_TEXT);
+ be_gas_emit_switch_section(env->emit, GAS_SECTION_TEXT);
} else {
/* one jump is enough */
- ia32_emit_cstring(env, "\tjmp ");
+ be_emit_cstring(env, "\tjmp ");
ia32_emit_cfop_target(env, tbl.branches[0].target);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
if (tbl.label)
/* we have a block schedule */
next_block = next_blk_sched(block);
if (get_cfop_target_block(node) != next_block) {
- ia32_emit_cstring(env, "\tjmp ");
+ be_emit_cstring(env, "\tjmp ");
ia32_emit_cfop_target(env, node);
} else {
- ia32_emit_cstring(env, "\t/* fallthrough to ");
+ be_emit_cstring(env, "\t/* fallthrough to ");
ia32_emit_cfop_target(env, node);
- ia32_emit_cstring(env, " */");
+ be_emit_cstring(env, " */");
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**********************************
* Emit movsb/w instructions to make mov count divideable by 4
*/
static void emit_CopyB_prolog(ia32_emit_env_t *env, int rem) {
- ia32_emit_cstring(env, "\tcld");
- ia32_emit_finish_line(env, NULL);
+ be_emit_cstring(env, "\tcld");
+ be_emit_finish_line_gas(env, NULL);
switch(rem) {
case 1:
- ia32_emit_cstring(env, "\tmovsb");
- ia32_emit_finish_line(env, NULL);
+ be_emit_cstring(env, "\tmovsb");
+ be_emit_finish_line_gas(env, NULL);
break;
case 2:
- ia32_emit_cstring(env, "\tmovsw");
- ia32_emit_finish_line(env, NULL);
+ be_emit_cstring(env, "\tmovsw");
+ be_emit_finish_line_gas(env, NULL);
break;
case 3:
- ia32_emit_cstring(env, "\tmovsb");
- ia32_emit_finish_line(env, NULL);
- ia32_emit_cstring(env, "\tmovsw");
- ia32_emit_finish_line(env, NULL);
+ be_emit_cstring(env, "\tmovsb");
+ be_emit_finish_line_gas(env, NULL);
+ be_emit_cstring(env, "\tmovsw");
+ be_emit_finish_line_gas(env, NULL);
break;
}
}
emit_CopyB_prolog(env, rem);
- ia32_emit_cstring(env, "\trep movsd");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\trep movsd");
+ be_emit_finish_line_gas(env, node);
}
/**
size >>= 2;
while (size--) {
- ia32_emit_cstring(env, "\tmovsd");
- ia32_emit_finish_line(env, NULL);
+ be_emit_cstring(env, "\tmovsd");
+ be_emit_finish_line_gas(env, NULL);
}
}
ir_mode *ls_mode = get_ia32_ls_mode(node);
int ls_bits = get_mode_size_bits(ls_mode);
- ia32_emit_cstring(env, "\tcvt");
+ be_emit_cstring(env, "\tcvt");
if(is_ia32_Conv_I2FP(node)) {
if(ls_bits == 32) {
- ia32_emit_cstring(env, "si2ss");
+ be_emit_cstring(env, "si2ss");
} else {
- ia32_emit_cstring(env, "si2sd");
+ be_emit_cstring(env, "si2sd");
}
} else if(is_ia32_Conv_FP2I(node)) {
if(ls_bits == 32) {
- ia32_emit_cstring(env, "ss2si");
+ be_emit_cstring(env, "ss2si");
} else {
- ia32_emit_cstring(env, "sd2si");
+ be_emit_cstring(env, "sd2si");
}
} else {
assert(is_ia32_Conv_FP2FP(node));
if(ls_bits == 32) {
- ia32_emit_cstring(env, "sd2ss");
+ be_emit_cstring(env, "sd2ss");
} else {
- ia32_emit_cstring(env, "ss2sd");
+ be_emit_cstring(env, "ss2sd");
}
}
- ia32_emit_char(env, ' ');
+ be_emit_char(env, ' ');
switch(get_ia32_op_type(node)) {
case ia32_Normal:
ia32_emit_source_register(env, node, 2);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
break;
case ia32_AddrModeS:
ia32_emit_dest_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
break;
default:
assert(0 && "unsupported op type for Conv");
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
static void emit_ia32_Conv_I2FP(ia32_emit_env_t *env, const ir_node *node) {
/* argument and result are both in EAX and */
/* signedness is ok: -> use converts */
if (smaller_bits == 8) {
- ia32_emit_cstring(env, "\tcbtw");
+ be_emit_cstring(env, "\tcbtw");
} else if (smaller_bits == 16) {
- ia32_emit_cstring(env, "\tcwtl");
+ be_emit_cstring(env, "\tcwtl");
} else {
assert(0);
}
/* argument and result are in the same register */
/* and signedness is ok: -> use and with mask */
int mask = (1 << smaller_bits) - 1;
- ia32_emit_cstring(env, "\tandl $0x");
- ia32_emit_irprintf(env, "%x, ", mask);
+ be_emit_cstring(env, "\tandl $0x");
+ be_emit_irprintf(env->emit, "%x, ", mask);
ia32_emit_dest_register(env, node, 0);
} else {
const char *sreg = ia32_get_reg_name_for_mode(env, smaller_mode, in_reg);
- ia32_emit_cstring(env, "\tmov");
- ia32_emit_string(env, sign_suffix);
+ be_emit_cstring(env, "\tmov");
+ be_emit_string(env, sign_suffix);
ia32_emit_mode_suffix(env, smaller_mode);
- ia32_emit_cstring(env, "l %");
- ia32_emit_string(env, sreg);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, "l %");
+ be_emit_string(env, sreg);
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
break;
case ia32_AddrModeS: {
- ia32_emit_cstring(env, "\tmov");
- ia32_emit_string(env, sign_suffix);
+ be_emit_cstring(env, "\tmov");
+ be_emit_string(env, sign_suffix);
ia32_emit_mode_suffix(env, smaller_mode);
- ia32_emit_cstring(env, "l %");
+ be_emit_cstring(env, "l %");
ia32_emit_am(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
break;
}
default:
assert(0 && "unsupported op type for Conv");
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**
static void emit_be_Call(ia32_emit_env_t *env, const ir_node *node) {
ir_entity *ent = be_Call_get_entity(node);
- ia32_emit_cstring(env, "\tcall ");
+ be_emit_cstring(env, "\tcall ");
if (ent) {
- ia32_emit_string(env, get_entity_ld_name(ent));
+ be_emit_string(env, get_entity_ld_name(ent));
} else {
- ia32_emit_char(env, '*');
+ be_emit_char(env, '*');
ia32_emit_dest_register(env, get_irn_n(node, be_pos_Call_ptr), 0);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**
return;
if (offs > 0) {
- ia32_emit_cstring(env, "\tsubl $");
- ia32_emit_irprintf(env, "%u, ", offs);
+ be_emit_cstring(env, "\tsubl $");
+ be_emit_irprintf(env->emit, "%u, ", offs);
ia32_emit_source_register(env, node, 0);
} else {
- ia32_emit_cstring(env, "\taddl $");
- ia32_emit_irprintf(env, "%u, ", -offs);
+ be_emit_cstring(env, "\taddl $");
+ be_emit_irprintf(env->emit, "%u, ", -offs);
ia32_emit_source_register(env, node, 0);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**
* Emits code to set stack pointer.
*/
static void emit_be_SetSP(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "\tmovl ");
+ be_emit_cstring(env, "\tmovl ");
ia32_emit_source_register(env, node, 2);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**
return;
if (mode_is_float(get_irn_mode(node))) {
- ia32_emit_cstring(env, "\tmovsd ");
+ be_emit_cstring(env, "\tmovsd ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
- ia32_emit_cstring(env, "\tmovl ");
+ be_emit_cstring(env, "\tmovl ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
static void emit_be_Copy(ia32_emit_env_t *env, const ir_node *node) {
lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "xor %1S, %2S", irn, irn);
} else {
#endif
- ia32_emit_cstring(env, "\txchg ");
+ be_emit_cstring(env, "\txchg ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
#if 0
}
#endif
} else if (cls1 == &ia32_reg_classes[CLASS_ia32_xmm]) {
- ia32_emit_cstring(env, "\txorpd ");
+ be_emit_cstring(env, "\txorpd ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, NULL);
+ be_emit_finish_line_gas(env, NULL);
- ia32_emit_cstring(env, "\txorpd ");
+ be_emit_cstring(env, "\txorpd ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_finish_line(env, NULL);
+ be_emit_finish_line_gas(env, NULL);
- ia32_emit_cstring(env, "\txorpd ");
+ be_emit_cstring(env, "\txorpd ");
ia32_emit_source_register(env, node, 1);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
} else if (cls1 == &ia32_reg_classes[CLASS_ia32_vfp]) {
/* is a NOP */
} else if (cls1 == &ia32_reg_classes[CLASS_ia32_st]) {
ia32_immop_type_t imm_tp = get_ia32_immop_type(node);
if (imm_tp == ia32_ImmSymConst) {
- ia32_emit_cstring(env, "\tmovl $");
+ be_emit_cstring(env, "\tmovl $");
ia32_emit_immediate(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
tarval *tv = get_ia32_Immop_tarval(node);
if (tarval_is_null(tv)) {
if (env->isa->opt_arch == arch_pentium_4) {
/* P4 prefers sub r, r, others xor r, r */
- ia32_emit_cstring(env, "\tsubl ");
+ be_emit_cstring(env, "\tsubl ");
} else {
- ia32_emit_cstring(env, "\txorl ");
+ be_emit_cstring(env, "\txorl ");
}
ia32_emit_dest_register(env, node, 0);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
- ia32_emit_cstring(env, "\tmovl $");
+ be_emit_cstring(env, "\tmovl $");
ia32_emit_immediate(env, node);
- ia32_emit_cstring(env, ", ");
+ be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
}
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
/**
* Emits code to load the TLS base
*/
static void emit_ia32_LdTls(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "\tmovl %gs:0, ");
+ be_emit_cstring(env, "\tmovl %gs:0, ");
ia32_emit_dest_register(env, node, 0);
- ia32_emit_finish_line(env, node);
+ be_emit_finish_line_gas(env, node);
}
static void emit_be_Return(ia32_emit_env_t *env, const ir_node *node) {
- ia32_emit_cstring(env, "\tret");
- ia32_emit_finish_line(env, node);
+ be_emit_cstring(env, "\tret");
+ be_emit_finish_line_gas(env, node);
}
static void emit_Nothing(ia32_emit_env_t *env, const ir_node *node) {
}
if (last_line != lineno) {
char name[64];
- FILE *F = env->out;
snprintf(name, sizeof(name), ".LM%u", ++num);
last_line = lineno;
be_dbg_line(env->cg->birg->main_env->db_handle, lineno, name);
- fprintf(F, "%s:\n", name);
+ be_emit_string(env, name);
+ be_emit_cstring(env, ":\n");
+ be_emit_write_line(env);
}
}
}
* Emits gas alignment directives
*/
static void ia32_emit_alignment(ia32_emit_env_t *env, unsigned align, unsigned skip) {
- ia32_emit_cstring(env, "\t.p2align ");
- ia32_emit_irprintf(env, "%u,,%u\n", align, skip);
- ia32_write_line(env);
+ be_emit_cstring(env, "\t.p2align ");
+ be_emit_irprintf(env->emit, "%u,,%u\n", align, skip);
+ be_emit_write_line(env);
}
/**
if (align)
ia32_emit_align_label(env, env->isa->opt_arch);
- ia32_emit_cstring(env, BLOCK_PREFIX);
- ia32_emit_irprintf(env, "%d:", get_irn_node_nr(block));
- ia32_pad_comment(env);
- ia32_emit_cstring(env, " /* preds:");
+ be_emit_cstring(env, BLOCK_PREFIX);
+ be_emit_irprintf(env->emit, "%d:", get_irn_node_nr(block));
+ be_emit_pad_comment(env);
+ be_emit_cstring(env, " /* preds:");
/* emit list of pred blocks in comment */
arity = get_irn_arity(block);
for (i = 0; i < arity; ++i) {
ir_node *predblock = get_Block_cfgpred_block(block, i);
- ia32_emit_irprintf(env, " %d", get_irn_node_nr(predblock));
+ be_emit_irprintf(env->emit, " %d", get_irn_node_nr(predblock));
}
if (exec_freq != NULL) {
- ia32_emit_irprintf(env, " freq: %f", get_block_execfreq(exec_freq, block));
+ be_emit_irprintf(env->emit, " freq: %f", get_block_execfreq(exec_freq, block));
}
- ia32_emit_cstring(env, " */\n");
- ia32_write_line(env);
+ be_emit_cstring(env, " */\n");
+ be_emit_write_line(env);
}
/* emit the contents of the block */
* Emits code for function start.
*/
static void ia32_emit_func_prolog(ia32_emit_env_t *env, ir_graph *irg) {
- FILE *F = env->out;
ir_entity *irg_ent = get_irg_entity(irg);
const char *irg_name = get_entity_ld_name(irg_ent);
cpu_support cpu = env->isa->opt_arch;
const be_irg_t *birg = env->cg->birg;
- fprintf(F, "\n");
- ia32_switch_section(F, SECTION_TEXT);
+ be_emit_write_line(env);
+ be_gas_emit_switch_section(env->emit, GAS_SECTION_TEXT);
be_dbg_method_begin(birg->main_env->db_handle, irg_ent, be_abi_get_stack_layout(birg->abi));
ia32_emit_align_func(env, cpu);
if (get_entity_visibility(irg_ent) == visibility_external_visible) {
- fprintf(F, ".globl %s\n", irg_name);
+ be_emit_cstring(env, ".global ");
+ be_emit_string(env, irg_name);
+ be_emit_char(env, '\n');
+ be_emit_write_line(env);
}
- ia32_dump_function_object(F, irg_name);
- fprintf(F, "%s:\n", irg_name);
+ ia32_emit_function_object(env, irg_name);
+ be_emit_string(env, irg_name);
+ be_emit_cstring(env, ":\n");
+ be_emit_write_line(env);
}
/**
static void ia32_emit_func_epilog(ia32_emit_env_t *env, ir_graph *irg) {
const char *irg_name = get_entity_ld_name(get_irg_entity(irg));
const be_irg_t *birg = env->cg->birg;
- FILE *F = env->out;
- ia32_dump_function_size(F, irg_name);
+ ia32_emit_function_size(env, irg_name);
be_dbg_method_end(birg->main_env->db_handle);
- fprintf(F, "\n");
+ be_emit_char(env, '\n');
+ be_emit_write_line(env);
}
/**
/**
* Main driver. Emits the code for one routine.
*/
-void ia32_gen_routine(ia32_code_gen_t *cg, FILE *F, ir_graph *irg) {
+void ia32_gen_routine(ia32_code_gen_t *cg, ir_graph *irg) {
ia32_emit_env_t env;
ir_node *block;
ir_node *last_block = NULL;
int i, n;
- struct obstack obst;
- obstack_init(&obst);
-
- env.out = F;
+ env.isa = (ia32_isa_t *)cg->arch_env->isa;
+ env.emit = &env.isa->emit;
env.arch_env = cg->arch_env;
env.cg = cg;
- env.isa = (ia32_isa_t *)cg->arch_env->isa;
- env.obst = &obst;
- env.linelength = 0;
FIRM_DBG_REGISTER(env.mod, "firm.be.ia32.emitter");
/* set the global arch_env (needed by print hooks) */
#include "debug.h"
#include "../bearch.h"
+#include "../beemitter.h"
#include "bearch_ia32_t.h"
-typedef struct _ia32_emit_env_t {
- FILE *out;
+typedef struct ia32_emit_env_t {
+ be_emit_env_t *emit;
const arch_env_t *arch_env;
const ia32_code_gen_t *cg;
ia32_isa_t *isa;
- struct obstack *obst;
- int linelength;
DEBUG_ONLY(firm_dbg_module_t *mod;)
} ia32_emit_env_t;
-static INLINE void ia32_emit_char(ia32_emit_env_t *env, char c)
-{
- obstack_1grow(env->obst, c);
- env->linelength++;
-}
-
-static INLINE void ia32_emit_string_len(ia32_emit_env_t *env, const char *str, size_t l)
-{
- obstack_grow(env->obst, str, l);
- env->linelength += l;
-}
-
-static INLINE void ia32_emit_string(ia32_emit_env_t *env, const char *str)
-{
- size_t len = strlen(str);
- ia32_emit_string_len(env, str, len);
-}
-
-#define ia32_emit_cstring(env,x) { ia32_emit_string_len(env, x, sizeof(x)-1); }
-
void ia32_emit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_adr(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node);
-void ia32_emit_finish_line(ia32_emit_env_t *env, const ir_node *node);
-
-void ia32_gen_routine(ia32_code_gen_t *cg, FILE *F, ir_graph *irg);
-
-/**
- * Sections.
- */
-typedef enum section_t {
- NO_SECTION = -1, /**< no section selected yet. */
- SECTION_TEXT = 0, /**< text section */
- SECTION_DATA = 1, /**< data section */
- SECTION_RODATA = 2, /**< rodata section */
- SECTION_COMMON = 3, /**< common section */
- SECTION_TLS = 4, /**< thread local storage section */
- SECTION_CTOR = 5, /**< ctor section for instrumentation code init */
- SECTION_MAX = 6
-} section_t;
-
-/**
- * Switch to a new section.
- */
-void ia32_switch_section(FILE *f, section_t sec);
-
-typedef enum asm_flavour_t {
- ASM_LINUX_GAS = 0, /**< Linux gas */
- ASM_MINGW_GAS = 1, /**< MinGW gas */
- ASM_MAX = 2
-} asm_flavour_t;
-extern asm_flavour_t asm_flavour;
+void ia32_gen_routine(ia32_code_gen_t *cg, ir_graph *irg);
#endif /* _IA32_EMITTER_H_ */
*/
static void ia32_finish_node(ir_node *irn, void *env) {
ia32_code_gen_t *cg = env;
- const ia32_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t *out_reg, *in_reg, *in2_reg;
int n_res, i;
ir_node *copy, *in_node, *block, *in2_node;
if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) && need_constraint_copy(irn))
{
for (i = 0; i < n_res; i++) {
- if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
+ if (arch_register_req_is(reqs[i], should_be_same)) {
+ int same_pos = reqs[i]->other_same;
+
/* get in and out register */
out_reg = get_ia32_out_reg(irn, i);
- in_node = get_irn_n(irn, reqs[i]->same_pos);
+ in_node = get_irn_n(irn, same_pos);
in_reg = arch_get_irn_register(cg->arch_env, in_node);
/* don't copy ignore nodes */
/* beware: the current op could be everything, so test for ia32 */
/* commutativity first before getting the second in */
if (is_ia32_commutative(irn)) {
- in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
+ in2_node = get_irn_n(irn, same_pos ^ 1);
in2_reg = arch_get_irn_register(cg->arch_env, in2_node);
if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
- set_irn_n(irn, reqs[i]->same_pos, in2_node);
- set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
+ set_irn_n(irn, same_pos, in2_node);
+ set_irn_n(irn, same_pos ^ 1, in_node);
}
else
goto insert_copy;
}
else {
insert_copy:
- DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
+ DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, same_pos));
/* create copy from in register */
copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);
sched_add_before(irn, copy);
/* set copy as in */
- set_irn_n(irn, reqs[i]->same_pos, copy);
+ set_irn_n(irn, same_pos, copy);
}
}
}
set_ia32_pncode(irn, get_negated_pnc(pnc, mode_E));
}
}
-
- /*
- If we have a CondJmp/CmpSet/xCmpSet with immediate,
- we need to check if it's the right operand, otherwise
- we have to change it, as CMP doesn't support immediate
- as left operands.
- */
-#if 0
- if ((is_ia32_CondJmp(irn) || is_ia32_CmpSet(irn) || is_ia32_xCmpSet(irn)) &&
- (is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn)) &&
- op_tp == ia32_AddrModeS)
- {
- set_ia32_op_type(irn, ia32_AddrModeD);
- set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
- }
-#endif
}
end: ;
}
ia32_code_gen_t *cg = env;
ir_node *base, *index, *noreg;
const arch_register_t *reg_base, *reg_index;
- const ia32_register_req_t **reqs;
+ const arch_register_req_t **reqs;
int n_res, i;
/* check only ia32 nodes with source address mode */
n_res = get_ia32_n_res(irn);
for (i = 0; i < n_res; i++) {
- if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
+ if (arch_register_req_is(reqs[i], should_be_same)) {
/* get in and out register */
const arch_register_t *out_reg = get_ia32_out_reg(irn, i);
+ int same_pos = reqs[i]->other_same;
/*
there is a constraint for the remaining operand
and the result register is equal to base or index register
*/
- if (reqs[i]->same_pos == 2 &&
+ if (same_pos == 2 &&
(REGS_ARE_EQUAL(out_reg, reg_base) || REGS_ARE_EQUAL(out_reg, reg_index)))
{
/* turn back address mode */
+++ /dev/null
-/**
- * Dumps global variables and constants as ia32 assembler.
- * @author Christian Wuerdig
- * @date 04.11.2005
- * @version $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "obst.h"
-#include "tv.h"
-#include "irnode.h"
-#include "entity.h"
-#include "irprog.h"
-#include "error.h"
-
-#include "../be.h"
-
-#include "ia32_emitter.h"
-#include "ia32_gen_decls.h"
-
-typedef struct obstack obstack_t;
-
-typedef struct _ia32_decl_env {
- obstack_t *rodata_obst;
- obstack_t *data_obst;
- obstack_t *bss_obst;
- obstack_t *ctor_obst;
- const be_main_env_t *main_env;
-} ia32_decl_env_t;
-
-/************************************************************************/
-
-/**
- * output a tarval
- */
-static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
-{
- switch (bytes) {
-
- case 1:
- obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
- break;
-
- case 2:
- obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 4:
- obstack_printf(obst, "0x%02x%02x%02x%02x",
- get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 8:
- obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
- get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
- get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
- case 10:
- case 12:
- break;
-
- case 16:
- obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x"
- "%02x%02x%02x%02x%02x%02x%02x%02x",
- get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 16),
- get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12),
- get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10),
- get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8),
- get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6),
- get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
- get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2),
- get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
- break;
-
-
- default:
- fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
- assert(0);
- }
-}
-
-/**
- * Return the tarval of an atomic initializer.
- */
-static tarval *get_atomic_init_tv(ir_node *init)
-{
- for (;;) {
- ir_mode *mode = get_irn_mode(init);
-
- switch (get_irn_opcode(init)) {
-
- case iro_Cast:
- init = get_Cast_op(init);
- continue;
-
- case iro_Conv:
- init = get_Conv_op(init);
- continue;
-
- case iro_Const:
- return get_Const_tarval(init);
-
- case iro_SymConst:
- switch (get_SymConst_kind(init)) {
- case symconst_ofs_ent:
- return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
-
- case symconst_type_size:
- return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
-
- case symconst_type_align:
- return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
-
- case symconst_enum_const:
- return get_enumeration_value(get_SymConst_enum(init));
-
- default:
- return NULL;
- }
-
- default:
- return NULL;
- }
- }
-}
-
-/**
- * dump an atomic value
- */
-static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
-{
- ir_mode *mode = get_irn_mode(init);
- int bytes = get_mode_size_bytes(mode);
- tarval *tv;
-
- switch (get_irn_opcode(init)) {
-
- case iro_Cast:
- do_dump_atomic_init(obst, get_Cast_op(init));
- return;
-
- case iro_Conv:
- do_dump_atomic_init(obst, get_Conv_op(init));
- return;
-
- case iro_Const:
- tv = get_Const_tarval(init);
-
- /* it's a arithmetic value */
- dump_arith_tarval(obst, tv, bytes);
- return;
-
- case iro_SymConst:
- switch (get_SymConst_kind(init)) {
- case symconst_addr_name:
- obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
- break;
-
- case symconst_addr_ent:
- obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
- break;
-
- case symconst_ofs_ent:
- obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
- break;
-
- case symconst_type_size:
- obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
- break;
-
- case symconst_type_align:
- obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
- break;
-
- case symconst_enum_const:
- tv = get_enumeration_value(get_SymConst_enum(init));
- dump_arith_tarval(obst, tv, bytes);
- break;
-
- default:
- assert(!"dump_atomic_init(): don't know how to init from this SymConst");
- }
- return;
-
- case iro_Add:
- do_dump_atomic_init(obst, get_Add_left(init));
- obstack_printf(obst, " + ");
- do_dump_atomic_init(obst, get_Add_right(init));
- return;
-
- case iro_Sub:
- do_dump_atomic_init(obst, get_Sub_left(init));
- obstack_printf(obst, " - ");
- do_dump_atomic_init(obst, get_Sub_right(init));
- return;
-
- case iro_Mul:
- do_dump_atomic_init(obst, get_Mul_left(init));
- obstack_printf(obst, " * ");
- do_dump_atomic_init(obst, get_Mul_right(init));
- return;
-
- default:
- assert(0 && "dump_atomic_init(): unknown IR-node");
- }
-}
-
-/**
- * dumps the type for given size (.byte, .long, ...)
- */
-static void dump_size_type(obstack_t *obst, int size) {
- switch (size) {
-
- case 1:
- obstack_printf(obst, "\t.byte\t");
- break;
-
- case 2:
- obstack_printf(obst, "\t.value\t");
- break;
-
- case 4:
- obstack_printf(obst, "\t.long\t");
- break;
-
- case 8:
- obstack_printf(obst, "\t.quad\t");
- break;
-
- case 10:
- case 12:
- /* handled in arith */
- break;
-
- case 16:
- obstack_printf(obst, "\t.octa\t");
- break;
-
- default:
- fprintf(stderr, "Try to dump a type with %d bytes\n", size);
- assert(0);
- }
-}
-
-/**
- * dump an atomic value to an obstack
- */
-static void dump_atomic_init(obstack_t *obst, ir_node *init)
-{
- ir_mode *mode = get_irn_mode(init);
- int bytes = get_mode_size_bytes(mode);
-
- dump_size_type(obst, bytes);
- do_dump_atomic_init(obst, init);
- obstack_printf(obst, "\n");
-}
-
-/************************************************************************/
-/* Routines to dump global variables */
-/************************************************************************/
-
-/**
- * Determine if an entity is a string constant
- * @param ent The entity
- * @return 1 if it is a string constant, 0 otherwise
- */
-static int ent_is_string_const(ir_entity *ent)
-{
- ir_type *type, *element_type;
- ir_mode *mode;
- int i, c, n;
-
- type = get_entity_type(ent);
-
- /* if it's an array */
- if (!is_Array_type(type))
- return 0;
-
- element_type = get_array_element_type(type);
-
- /* and the array's element type is primitive */
- if (!is_Primitive_type(element_type))
- return 0;
-
- /* and the mode of the element type is an int of
- * the same size as the byte mode */
- mode = get_type_mode(element_type);
- if (!mode_is_int(mode)
- || get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
- return 0;
-
- /* if it contains only printable chars and a 0 at the end */
- n = get_compound_ent_n_values(ent);
- for (i = 0; i < n; ++i) {
- ir_node *irn = get_compound_ent_value(ent, i);
- if(get_irn_opcode(irn) != iro_Const)
- return 0;
-
- c = (int) get_tarval_long(get_Const_tarval(irn));
-
- if((i < n - 1 && !(isgraph(c) || isspace(c)))
- || (i == n - 1 && c != '\0'))
- return 0;
- }
-
- /* then we can emit it as a string constant */
- return 1;
-}
-
-/**
- * Dump a string constant.
- * No checks are made!!
- * @param obst The obst to dump on.
- * @param ent The entity to dump.
- */
-static void dump_string_cst(obstack_t *obst, ir_entity *ent)
-{
- int i, n;
-
- obstack_printf(obst, "\t.string \"");
- n = get_compound_ent_n_values(ent);
-
- for (i = 0; i < n-1; ++i) {
- ir_node *irn;
- int c;
-
- irn = get_compound_ent_value(ent, i);
- c = (int) get_tarval_long(get_Const_tarval(irn));
-
- switch (c) {
- case '"' : obstack_printf(obst, "\\\""); break;
- case '\n': obstack_printf(obst, "\\n"); break;
- case '\r': obstack_printf(obst, "\\r"); break;
- case '\t': obstack_printf(obst, "\\t"); break;
- case '\\': obstack_printf(obst, "\\\\"); break;
- default :
- if (isprint(c))
- obstack_printf(obst, "%c", c);
- else
- obstack_printf(obst, "\\%o", c);
- break;
- }
- }
- obstack_printf(obst, "\"\n");
-}
-
-static void dump_array_init(obstack_t *obst, ir_entity *ent)
-{
- const ir_type *ty = get_entity_type(ent);
- int i;
- int filler;
- int size = 0;
-
- /* potential spare values should be already included! */
- for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
- ir_entity *step = get_compound_ent_value_member(ent, i);
- ir_type *stype = get_entity_type(step);
-
- if (get_type_mode(stype)) {
- int align = (get_type_alignment_bits(stype) + 7) >> 3;
- int n = size % align;
-
- if (n > 0) {
- obstack_printf(obst, "\t.zero\t%d\n", align - n);
- size += align - n;
- }
- }
- dump_atomic_init(obst, get_compound_ent_value(ent, i));
- size += get_type_size_bytes(stype);
- }
- filler = get_type_size_bytes(ty) - size;
-
- if (filler > 0)
- obstack_printf(obst, "\t.skip\t%d\n", filler);
-}
-
-enum normal_or_bitfield_kind {
- NORMAL = 0,
- BITFIELD
-};
-
-typedef struct {
- enum normal_or_bitfield_kind kind;
- union {
- ir_node *value;
- unsigned char bf_val;
- } v;
-} normal_or_bitfield;
-
-/**
- * Dump an initializer for a compound entity.
- */
-static void dump_compound_init(obstack_t *obst, ir_entity *ent)
-{
- normal_or_bitfield *vals;
- int i, j, n = get_compound_ent_n_values(ent);
- int last_ofs;
-
- /* Find the initializer size. Sorrily gcc support a nasty feature:
- The last field of a compound may be a flexible array. This allows
- initializers bigger than the type size. */
- last_ofs = 0;
- for (i = 0; i < n; ++i) {
- int offset = get_compound_ent_value_offset_bytes(ent, i);
- int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
- const compound_graph_path *path = get_compound_ent_value_path(ent, i);
- int path_len = get_compound_graph_path_length(path);
- ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
- int value_len = get_type_size_bits(get_entity_type(last_ent));
-
- offset += (value_len + bits_remainder + 7) >> 3;
-
- if (offset > last_ofs) {
- last_ofs = offset;
- }
- }
-
- /*
- * In the worst case, every initializer allocates one byte.
- * Moreover, initializer might be big, do not allocate an stack.
- */
- vals = xcalloc(last_ofs, sizeof(vals[0]));
-
- /* collect the values and store them at the offsets */
- for (i = 0; i < n; ++i) {
- const compound_graph_path *path = get_compound_ent_value_path(ent, i);
- int path_len = get_compound_graph_path_length(path);
- int offset = get_compound_ent_value_offset_bytes(ent, i);
- int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
- ir_node *value = get_compound_ent_value(ent, i);
- ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
- int value_len = get_type_size_bits(get_entity_type(last_ent));
- assert(offset >= 0);
- assert(offset_bits >= 0);
-
- if (offset_bits != 0 ||
- (value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
- tarval *shift, *shifted;
- tarval *tv = get_atomic_init_tv(value);
- if (tv == NULL) {
- panic("Couldn't get numeric value for bitfield initializer '%s'\n",
- get_entity_ld_name(ent));
- }
- tv = tarval_convert_to(tv, mode_Lu);
- shift = new_tarval_from_long(offset_bits, mode_Is);
- shifted = tarval_shl(tv, shift);
- if (shifted == tarval_bad || shifted == tarval_undefined) {
- panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
- get_entity_ld_name(ent));
- }
-
- for (j = 0; value_len > 0; ++j) {
- assert(offset + j < last_ofs);
- assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
- vals[offset + j].kind = BITFIELD;
- vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
- value_len -= 8 - offset_bits;
- offset_bits = 0;
- }
- } else {
- assert(offset < last_ofs);
- assert(vals[offset].kind == NORMAL);
- assert(vals[offset].v.value == NULL);
- vals[offset].v.value = value;
- }
- }
-
- /* now write them sorted */
- for (i = 0; i < last_ofs; ) {
- int space = 0, skip = 0;
- if (vals[i].kind == NORMAL) {
- if(vals[i].v.value != NULL) {
- dump_atomic_init(obst, vals[i].v.value);
- skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
- } else {
- space = 1;
- }
- } else {
- assert(vals[i].kind == BITFIELD);
- obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
- }
-
- ++i;
- space = 0;
- while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
- ++space;
- ++i;
- }
- space -= skip;
- assert(space >= 0);
-
- /* a gap */
- if (space > 0)
- obstack_printf(obst, "\t.skip\t%d\n", space);
- }
- xfree(vals);
-}
-
-/**
- * Dump a global entity.
- */
-static void dump_global(ia32_decl_env_t *env, ir_entity *ent, int emit_commons)
-{
- obstack_t *obst;
- ir_type *type = get_entity_type(ent);
- const char *ld_name = get_entity_ld_name(ent);
- ir_variability variability = get_entity_variability(ent);
- ir_visibility visibility = get_entity_visibility(ent);
- int align = get_type_alignment_bytes(type);
- int emit_as_common = 0;
-
- obst = env->data_obst;
- if (is_Method_type(type)) {
- if (get_method_img_section(ent) == section_constructors) {
- obst = env->ctor_obst;
- obstack_printf(obst, ".balign\t%d\n", align);
- dump_size_type(obst, align);
- obstack_printf(obst, "%s\n", ld_name);
- }
- return;
- } else if (variability == variability_constant) {
- /* a constant entity, put it on the rdata */
- obst = env->rodata_obst;
- } else if (variability == variability_uninitialized) {
- /* uninitialized entity put it in bss segment */
- obst = env->bss_obst;
- if(emit_commons && visibility != visibility_local)
- emit_as_common = 1;
- }
-
- be_dbg_variable(env->main_env->db_handle, obst, ent);
-
- /* global or not global */
- if (visibility == visibility_external_visible && !emit_as_common) {
- obstack_printf(obst, ".global\t%s\n", ld_name);
- } else if(visibility == visibility_external_allocated) {
- obstack_printf(obst, ".global\t%s\n", ld_name);
- /* we can return now... */
- return;
- }
- /* alignment */
- if (align > 1 && !emit_as_common) {
- obstack_printf(obst, ".balign\t%d\n", align);
- }
-
- if (!emit_as_common) {
- obstack_printf(obst, "%s:\n", ld_name);
- }
-
- if (variability == variability_uninitialized) {
- if(emit_as_common) {
- obstack_printf(obst, "\t.comm %s,%d,%d\n",
- ld_name, get_type_size_bytes(type), align);
- } else {
- obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
- }
- } else if (is_atomic_type(type)) {
- dump_atomic_init(obst, get_atomic_ent_value(ent));
- } else if (ent_is_string_const(ent)) {
- dump_string_cst(obst, ent);
- } else if (is_Array_type(type)) {
- dump_array_init(obst, ent);
- } else if (is_compound_type(type)) {
- dump_compound_init(obst, ent);
- } else {
- assert(0 && "unsupported type");
- }
-}
-
-/**
- * Dumps declarations of global variables and the initialization code.
- */
-static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env, int emit_commons)
-{
- int i, n = get_compound_n_members(gt);
-
- for (i = 0; i < n; i++) {
- ir_entity *ent = get_compound_member(gt, i);
- dump_global(env, ent, emit_commons);
- }
-}
-
-/************************************************************************/
-
-void ia32_gen_decls(FILE *out, const be_main_env_t *main_env) {
- ia32_decl_env_t env;
- obstack_t rodata, data, bss, ctor;
- int size;
- char *cp;
-
- /* dump the global type */
- obstack_init(&rodata);
- obstack_init(&data);
- obstack_init(&bss);
-
- if (main_env->options->opt_profile)
- obstack_init(&ctor);
-
- env.rodata_obst = &rodata;
- env.data_obst = &data;
- env.bss_obst = &bss;
- env.ctor_obst = main_env->options->opt_profile ? &ctor : NULL;
- env.main_env = main_env;
-
- ia32_dump_globals(get_glob_type(), &env, 1);
-
- size = obstack_object_size(&data);
- cp = obstack_finish(&data);
- if (size > 0) {
- ia32_switch_section(out, SECTION_DATA);
- fwrite(cp, 1, size, out);
- }
-
- size = obstack_object_size(&rodata);
- cp = obstack_finish(&rodata);
- if (size > 0) {
- ia32_switch_section(out, SECTION_RODATA);
- fwrite(cp, 1, size, out);
- }
-
- size = obstack_object_size(&bss);
- cp = obstack_finish(&bss);
- if (size > 0) {
- ia32_switch_section(out, SECTION_COMMON);
- fwrite(cp, 1, size, out);
- }
-
- if (main_env->options->opt_profile) {
- size = obstack_object_size(&ctor);
- cp = obstack_finish(&ctor);
- if (size > 0) {
- ia32_switch_section(out, SECTION_CTOR);
- fwrite(cp, 1, size, out);
- }
- obstack_free(&ctor, NULL);
- }
-
- obstack_free(&rodata, NULL);
- obstack_free(&data, NULL);
- obstack_free(&bss, NULL);
-
- /* dump the Thread Local Storage */
- obstack_init(&data);
-
- env.rodata_obst = &data;
- env.data_obst = &data;
- env.bss_obst = &data;
- env.ctor_obst = NULL;
-
- ia32_dump_globals(get_tls_type(), &env, 0);
-
- size = obstack_object_size(&data);
- cp = obstack_finish(&data);
- if (size > 0) {
- ia32_switch_section(out, SECTION_TLS);
- fprintf(out, ".balign\t%d\n", 32);
- fwrite(cp, 1, size, out);
- }
-
- obstack_free(&data, NULL);
-}
+++ /dev/null
-/**
- * Header for ia32 assembler declarations dumper.
- * @author Christian Wuerdig
- * $Id$
- */
-
-#ifndef _IA32_GEN_DECLS_H_
-#define _IA32_GEN_DECLS_H_
-
-#include "../be.h"
-
-/**
- * Generate all entities.
- */
-void ia32_gen_decls(FILE *out, const be_main_env_t *main_env);
-
-#endif /* _IA32_GEN_DECLS_H_ */
* @author Christian Wuerdig
* $Id$
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef HAVE_MALLOC_H
#include "irprintf.h"
#include "iredges.h"
#include "error.h"
+#include "raw_bitset.h"
#include "../bearch.h"
* |_|
***********************************************************************************/
-/**
- * Returns a string containing the names of all registers within the limited bitset
- */
-static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- char *p = buf;
- int size = 0;
- int i, cnt;
-
- req->limited(NULL, bs);
-
- for (i = 0; i < req->cls->n_regs; i++) {
- if (bitset_is_set(bs, i)) {
- cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
- if (cnt < 0) {
- fprintf(stderr, "dumper problem, exiting\n");
- exit(1);
- }
-
- p += cnt;
- size += cnt;
-
- if (size >= max)
- break;
- }
- }
-
- return buf;
-}
-
/**
* Dumps the register requirements for either in or out.
*/
-static void dump_reg_req(FILE *F, ir_node *n, const ia32_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
+ int inout) {
char *dir = inout ? "out" : "in";
int max = inout ? get_ia32_n_res(n) : get_irn_arity(n);
- char *buf = alloca(1024);
+ char buf[1024];
int i;
- memset(buf, 0, 1024);
+ memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
- if (reqs[i]->req.type == arch_register_req_type_none) {
+ if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
- if (reqs[i]->req.type & arch_register_req_type_normal) {
- fprintf(F, " %s", reqs[i]->req.cls->name);
+ if (reqs[i]->type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->cls->name);
}
- if (reqs[i]->req.type & arch_register_req_type_limited) {
- fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ if (reqs[i]->type & arch_register_req_type_limited) {
+ fprintf(F, " %s",
+ arch_register_req_format(buf, sizeof(buf), reqs[i], n));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
- ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
- ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->other_different));
}
fprintf(F, "\n");
ir_mode *mode = NULL;
int bad = 0;
int i, n_res, am_flav, flags;
- const ia32_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t **slots;
switch (reason) {
/**
* Returns the argument register requirements of an ia32 node.
*/
-const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_ia32_in_req_all(const ir_node *node) {
ia32_attr_t *attr = get_ia32_attr(node);
return attr->in_req;
}
/**
* Sets the argument register requirements of an ia32 node.
*/
-void set_ia32_in_req_all(ir_node *node, const ia32_register_req_t **reqs) {
+void set_ia32_in_req_all(ir_node *node, const arch_register_req_t **reqs) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->in_req = reqs;
}
/**
* Returns the result register requirements of an ia32 node.
*/
-const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_ia32_out_req_all(const ir_node *node) {
ia32_attr_t *attr = get_ia32_attr(node);
return attr->out_req;
}
/**
* Sets the result register requirements of an ia32 node.
*/
-void set_ia32_out_req_all(ir_node *node, const ia32_register_req_t **reqs) {
+void set_ia32_out_req_all(ir_node *node, const arch_register_req_t **reqs) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->out_req = reqs;
}
/**
* Returns the argument register requirement at position pos of an ia32 node.
*/
-const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
- return attr->in_req != NULL ? attr->in_req[pos] : NULL;
+ if(attr->in_req == NULL)
+ return arch_no_register_req;
+
+ return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an ia32 node.
*/
-const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
- return attr->out_req != NULL ? attr->out_req[pos] : NULL;
+ if(attr->out_req == NULL)
+ return arch_no_register_req;
+
+ return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
-void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) {
+void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->out_req[pos] = req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) {
+void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->in_req[pos] = req;
}
/**
* Initializes the nodes attributes.
*/
-void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_register_req_t **in_reqs,
- const ia32_register_req_t **out_reqs, const be_execution_unit_t ***execution_units,
- int n_res, unsigned latency)
+void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
+ const arch_register_req_t **in_reqs,
+ const arch_register_req_t **out_reqs,
+ const be_execution_unit_t ***execution_units,
+ int n_res, unsigned latency)
{
ia32_attr_t *attr = get_ia32_attr(node);
/**
* Returns the argument register requirements of an ia32 node.
*/
-const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node);
+const arch_register_req_t **get_ia32_in_req_all(const ir_node *node);
/**
* Sets the argument register requirements of an ia32 node.
*/
-void set_ia32_in_req_all(ir_node *node, const ia32_register_req_t **reqs);
+void set_ia32_in_req_all(ir_node *node, const arch_register_req_t **reqs);
/**
* Returns the result register requirements of an ia32 node.
*/
-const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node);
+const arch_register_req_t **get_ia32_out_req_all(const ir_node *node);
/**
* Sets the result register requirements of an ia32 node.
*/
-void set_ia32_out_req_all(ir_node *node, const ia32_register_req_t **reqs);
+void set_ia32_out_req_all(ir_node *node, const arch_register_req_t **reqs);
/**
* Returns the argument register requirements of an ia32 node.
*/
-const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos);
+const arch_register_req_t *get_ia32_in_req(const ir_node *node, int pos);
/**
* Returns the result register requirements of an ia32 node.
*/
-const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos);
+const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
-void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos);
+void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the IN register requirements at position pos.
*/
-void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos);
+void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the register flag of an ia32 node.
/**
* Initializes the nodes attributes.
*/
-void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_register_req_t **in_reqs, \
- const ia32_register_req_t **out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
+void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
+ const arch_register_req_t **in_reqs,
+ const arch_register_req_t **out_reqs,
+ const be_execution_unit_t ***execution_units,
+ int n_res, unsigned latency);
/**
* Registers the ia32_copy_attr function for all ia32 opcodes.
ia32_am_OBIS = ia32_O | ia32_B | ia32_I | ia32_S
} ia32_am_flavour_t;
-typedef struct _ia32_register_req_t {
- const arch_register_req_t req;
- int same_pos; /**< in case of "should be same" we need to remember the pos to get the irn */
- int different_pos; /**< in case of "should be different" we need to remember the pos to get the irn */
-} ia32_register_req_t;
-
enum {
ia32_pn_Cmp_Unsigned = 0x100 /**< set this flag in a pnc to indicate an unsigned compare operation */
};
const be_execution_unit_t ***exec_units; /**< list of units this operation can be executed on */
- const ia32_register_req_t **in_req; /**< register requirements for arguments */
- const ia32_register_req_t **out_req; /**< register requirements for results */
+ const arch_register_req_t **in_req; /**< register requirements for arguments */
+ const arch_register_req_t **out_req; /**< register requirements for results */
const arch_register_t *x87[3]; /**< register slots for x87 register */
{ "name" => "xmm7", "type" => 1 },
{ "name" => "xmm_NOREG", "type" => 4 | 16 }, # we need a dummy register for NoReg nodes
{ "name" => "xmm_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
- { "mode" => "mode_LLu" }
+ { "mode" => "mode_E" }
],
"vfp" => [
{ "name" => "vf0", "type" => 1 | 16 },
"C" => "${arch}_emit_immediate(env, node);",
"SE" => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));",
"ME" => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
- ${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
+ ia32_emit_mode_suffix(env, get_ia32_ls_mode(node));",
"M" => "${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
"XM" => "${arch}_emit_x87_mode_suffix(env, node);",
"XXM" => "${arch}_emit_xmm_mode_suffix(env, node);",
"op_flags" => "L|F",
"state" => "exc_pinned",
"comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
"emit" => '. mov%M %binop',
"latency" => 3,
"units" => [ "GP" ],
"op_flags" => "L|F",
"state" => "exc_pinned",
"comment" => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ], "out" => ["none" ] },
"emit" => '. mov%M %binop',
"latency" => 3,
"units" => [ "GP" ],
); # end of %nodes
# Include the generated SIMD node specification written by the SIMD optimization
-
-do "../ir/be/ia32/ia32_simd_spec.pl";
+#do "../ir/be/ia32/ia32_simd_spec.pl";
* |___/
**************************************************/
-static ir_node *my_skip_proj(const ir_node *n) {
- while (is_Proj(n))
- n = get_Proj_pred(n);
- return (ir_node *)n;
-}
-
/**
* Return register requirements for a mips node.
* If the node returns a tuple (mode_T) then the proj's
* will be asked for this information.
*/
-static const arch_register_req_t *mips_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
- const mips_register_req_t *irn_req;
+static const
+arch_register_req_t *mips_get_irn_reg_req(const void *self,
+ const ir_node *node, int pos) {
long node_pos = pos == -1 ? 0 : pos;
- ir_mode *mode = get_irn_mode(irn);
- FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
+ ir_mode *mode = get_irn_mode(node);
- if (is_Block(irn) || mode == mode_X || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
- return NULL;
+ if (is_Block(node) || mode == mode_X || mode == mode_M) {
+ return arch_no_register_req;
}
if (mode == mode_T && pos < 0) {
- DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", irn));
- return NULL;
+ return arch_no_register_req;
}
- DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
-
- if (is_Proj(irn)) {
+ if (is_Proj(node)) {
/* in case of a proj, we need to get the correct OUT slot */
/* of the node corresponding to the proj number */
if (pos == -1) {
- node_pos = mips_translate_proj_pos(irn);
+ node_pos = mips_translate_proj_pos(node);
}
else {
node_pos = pos;
}
- irn = my_skip_proj(irn);
-
- DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+ node = skip_Proj_const(node);
}
/* get requirements for our own nodes */
- if (is_mips_irn(irn)) {
+ if (is_mips_irn(node)) {
+ const arch_register_req_t *req;
if (pos >= 0) {
- irn_req = get_mips_in_req(irn, pos);
- }
- else {
- irn_req = get_mips_out_req(irn, node_pos);
- }
-
- DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
-
- memcpy(req, &(irn_req->req), sizeof(*req));
-
- if (arch_register_req_is(&(irn_req->req), should_be_same)) {
- assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
- req->other_same = get_irn_n(irn, irn_req->same_pos);
+ req = get_mips_in_req(node, pos);
+ } else {
+ req = get_mips_out_req(node, node_pos);
}
- if (arch_register_req_is(&(irn_req->req), should_be_different)) {
- assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
- req->other_different = get_irn_n(irn, irn_req->different_pos);
- }
+ return req;
}
- /* get requirements for FIRM nodes */
- else {
- /* treat Phi like Const with default requirements */
- if (is_Phi(irn)) {
- DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
- if (mode_is_float(mode)) {
- //memcpy(req, &(mips_default_req_mips_floating_point.req), sizeof(*req));
- assert(0 && "floating point not supported (yet)");
- }
- else if (mode_is_int(mode) || mode_is_reference(mode)) {
- memcpy(req, &(mips_default_req_mips_gp.req), sizeof(*req));
- }
- else if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
- return NULL;
- }
- else {
- assert(0 && "unsupported Phi-Mode");
- }
- }
- else {
- DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
- req = NULL;
- }
- }
+ /* unknown should be translated by now */
+ assert(!is_Unknown(node));
- return req;
+ return arch_no_register_req;
}
static void mips_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
}
pos = mips_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj(irn);
}
if (is_mips_irn(irn)) {
}
pos = mips_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
}
if (is_mips_irn(irn)) {
}
static arch_irn_class_t mips_classify(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_cfop(irn)) {
return arch_irn_class_branch;
}
static arch_irn_flags_t mips_get_flags(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_mips_irn(irn)) {
return get_mips_flags(irn);
* |_|
***********************************************************************************/
-/**
- * Returns a string containing the names of all registers within the limited bitset
- */
-static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- char *p = buf;
- int size = 0;
- int i, cnt;
-
- req->limited(NULL, bs);
-
- for (i = 0; i < req->cls->n_regs; i++) {
- if (bitset_is_set(bs, i)) {
- cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
- if (cnt < 0) {
- fprintf(stderr, "dumper problem, exiting\n");
- exit(1);
- }
-
- p += cnt;
- size += cnt;
-
- if (size >= max)
- break;
- }
- }
-
- return buf;
-}
-
/**
* Dumps the register requirements for either in or out.
*/
-static void dump_reg_req(FILE *F, ir_node *n, const mips_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) {
char *dir = inout ? "out" : "in";
int max = inout ? get_mips_n_res(n) : get_irn_arity(n);
- char *buf = alloca(1024);
+ char buf[1024];
int i;
- memset(buf, 0, 1024);
+ memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
- if (reqs[i]->req.type == arch_register_req_type_none) {
+ if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
- if (reqs[i]->req.type & arch_register_req_type_normal) {
- fprintf(F, " %s", reqs[i]->req.cls->name);
+ if (reqs[i]->type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->cls->name);
}
- if (reqs[i]->req.type & arch_register_req_type_limited) {
- fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ if (reqs[i]->type & arch_register_req_type_limited) {
+ fprintf(F, " %s",
+ arch_register_req_format(buf, sizeof(buf), reqs[i], n));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
- ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
- ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->other_different));
}
fprintf(F, "\n");
}
fprintf(F, "\n");
- }
- else {
+ } else {
fprintf(F, "%sreq = N/A\n", dir);
}
}
int i;
mips_attr_t *attr;
char buf[64];
- const mips_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t **slots;
switch (reason) {
/**
* Returns the argument register requirements of a mips node.
*/
-const mips_register_req_t **get_mips_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_mips_in_req_all(const ir_node *node) {
mips_attr_t *attr = get_mips_attr(node);
return attr->in_req;
}
/**
* Returns the result register requirements of an mips node.
*/
-const mips_register_req_t **get_mips_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_mips_out_req_all(const ir_node *node) {
mips_attr_t *attr = get_mips_attr(node);
return attr->out_req;
}
/**
* Returns the argument register requirement at position pos of an mips node.
*/
-const mips_register_req_t *get_mips_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) {
mips_attr_t *attr = get_mips_attr(node);
return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an mips node.
*/
-const mips_register_req_t *get_mips_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) {
mips_attr_t *attr = get_mips_attr(node);
return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
-void set_mips_req_out(ir_node *node, const mips_register_req_t *req, int pos) {
+void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
mips_attr_t *attr = get_mips_attr(node);
attr->out_req[pos] = req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_mips_req_in(ir_node *node, const mips_register_req_t *req, int pos) {
+void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
mips_attr_t *attr = get_mips_attr(node);
attr->in_req[pos] = req;
}
/**
* Initializes the nodes attributes.
*/
-void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const mips_register_req_t **in_reqs,
- const mips_register_req_t **out_reqs,
+void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_register_req_t **in_reqs,
+ const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res, unsigned latency)
{
/**
* Returns the argument register requirements of an mips node.
*/
-const mips_register_req_t **get_mips_in_req_all(const ir_node *node);
+const arch_register_req_t **get_mips_in_req_all(const ir_node *node);
/**
* Returns the result register requirements of an mips node.
*/
-const mips_register_req_t **get_mips_out_req_all(const ir_node *node);
+const arch_register_req_t **get_mips_out_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an mips node.
*/
-const mips_register_req_t *get_mips_in_req(const ir_node *node, int pos);
+const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos);
/**
* Returns the result register requirements of an mips node.
*/
-const mips_register_req_t *get_mips_out_req(const ir_node *node, int pos);
+const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
-void set_mips_req_out(ir_node *node, const mips_register_req_t *req, int pos);
+void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the IN register requirements at position pos.
*/
-void set_mips_req_in(ir_node *node, const mips_register_req_t *req, int pos);
+void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the register flag of an mips node.
/**
* Initializes the nodes attributes.
*/
-void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const mips_register_req_t **in_reqs,
- const mips_register_req_t **out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
+void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_register_req_t **in_reqs,
+ const arch_register_req_t **out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
/**
* Initialize transform ops for the mips opcodes
#include "../bearch.h"
#include "irmode_t.h"
-typedef struct _mips_register_req_t {
- const arch_register_req_t req;
- int same_pos; /**<< in case of "should be same" we need to remember the pos to get the irn */
- int different_pos; /**<< in case of "should be different" we need to remember the pos to get the irn */
-} mips_register_req_t;
-
-
typedef struct _mips_attr_t {
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
int n_res; /**< number of results for this node */
int stack_entity_offset; /**< contains the real stack offset for the entity */
int switch_default_pn; /**< proj number of default case in switch */
- const mips_register_req_t **in_req; /**< register requirements for arguments */
- const mips_register_req_t **out_req; /**< register requirements for results */
+ const arch_register_req_t **in_req; /**< register requirements for arguments */
+ const arch_register_req_t **out_req; /**< register requirements for results */
/* must be last, dynamically allocated */
const arch_register_t *slots[1]; /**< register slots for assigned registers */
# 4 - ignore (do not assign this register)
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
%reg_classes = (
- "gp" => [
- { name => "zero", type => 4+2 }, # always zero
- { name => "at", type => 4 }, # reserved for assembler
- { name => "v0", type => 1 }, # first return value
- { name => "v1", type => 1 }, # second return value
- { name => "a0", type => 1 }, # first argument
- { name => "a1", type => 1 }, # second argument
- { name => "a2", type => 1 }, # third argument
- { name => "a3", type => 1 }, # fourth argument
- { name => "t0", type => 1 },
- { name => "t1", type => 1 },
- { name => "t2", type => 1 },
- { name => "t3", type => 1 },
- { name => "t4", type => 1 },
- { name => "t5", type => 1 },
- { name => "t6", type => 1 },
- { name => "t7", type => 1 },
- { name => "s0", type => 2 },
- { name => "s1", type => 2 },
- { name => "s2", type => 2 },
- { name => "s3", type => 2 },
- { name => "s4", type => 2 },
- { name => "s5", type => 2 },
- { name => "s6", type => 2 },
- { name => "s7", type => 2 },
- { name => "t8", type => 1 },
- { name => "t9", type => 1 },
- { name => "k0", type => 4 }, # reserved for OS
- { name => "k1", type => 4 }, # reserved for OS
- { name => "gp", type => 4 }, # general purpose
- { name => "sp", type => 4+2 }, # stack pointer
- { name => "fp", type => 4+2 }, # frame pointer
- { name => "ra", type => 2+1 }, # return address. This is also caller save, because
- # the jla instruction that is used for calls modifies
- # the ra register. It is callee save too, because at the last
- # command of a function (the ja $ra) it needs to have it's
- # old value.
- { mode => "mode_P" }
- ],
+ "gp" => [
+ { name => "zero", type => 4+2 }, # always zero
+ { name => "at", type => 4 }, # reserved for assembler
+ { name => "v0", type => 1 }, # first return value
+ { name => "v1", type => 1 }, # second return value
+ { name => "a0", type => 1 }, # first argument
+ { name => "a1", type => 1 }, # second argument
+ { name => "a2", type => 1 }, # third argument
+ { name => "a3", type => 1 }, # fourth argument
+ { name => "t0", type => 1 },
+ { name => "t1", type => 1 },
+ { name => "t2", type => 1 },
+ { name => "t3", type => 1 },
+ { name => "t4", type => 1 },
+ { name => "t5", type => 1 },
+ { name => "t6", type => 1 },
+ { name => "t7", type => 1 },
+ { name => "s0", type => 2 },
+ { name => "s1", type => 2 },
+ { name => "s2", type => 2 },
+ { name => "s3", type => 2 },
+ { name => "s4", type => 2 },
+ { name => "s5", type => 2 },
+ { name => "s6", type => 2 },
+ { name => "s7", type => 2 },
+ { name => "t8", type => 1 },
+ { name => "t9", type => 1 },
+ { name => "k0", type => 4 }, # reserved for OS
+ { name => "k1", type => 4 }, # reserved for OS
+ { name => "gp", type => 4 }, # general purpose
+ { name => "sp", type => 4+2 }, # stack pointer
+ { name => "fp", type => 4+2 }, # frame pointer
+ { name => "ra", type => 2+1 }, # return address. This is also caller
+ # save, because the jla instruction that
+ # is used for calls modifies the ra
+ # register. It is callee save too,
+ # because at the last command of a
+ # function (the ja $ra) it needs to have
+ # it's old value.
+ { mode => "mode_P" }
+ ],
); # %reg_classes
#--------------------------------------------------#
/* The main ppc backend driver file. */
/* $Id$ */
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "pseudo_irg.h"
* |___/
**************************************************/
-static ir_node *my_skip_proj(const ir_node *n) {
- while (is_Proj(n))
- n = get_Proj_pred(n);
- return (ir_node *)n;
-}
-
/**
* Return register requirements for a ppc node.
* If the node returns a tuple (mode_T) then the proj's
* will be asked for this information.
*/
-static const arch_register_req_t *ppc32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
- const ppc32_register_req_t *irn_req;
+static const
+arch_register_req_t *ppc32_get_irn_reg_req(const void *self,
+ const ir_node *irn, int pos) {
long node_pos = pos == -1 ? 0 : pos;
ir_mode *mode = get_irn_mode(irn);
FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
if (is_Block(irn) || mode == mode_X || mode == mode_M) {
DBG((mod, LEVEL_1, "ignoring block, mode_X or mode_M node %+F\n", irn));
- return NULL;
+ return arch_no_register_req;
}
if (mode == mode_T && pos < 0) {
DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F", irn));
- return NULL;
+ return arch_no_register_req;
}
DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
/* of the node corresponding to the proj number */
if (pos == -1) {
node_pos = ppc32_translate_proj_pos(irn);
- }
- else {
+ } else {
node_pos = pos;
}
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
}
/* get requirements for our own nodes */
if (is_ppc32_irn(irn)) {
+ const arch_register_req_t *req;
if (pos >= 0) {
- irn_req = get_ppc32_in_req(irn, pos);
- }
- else {
- irn_req = get_ppc32_out_req(irn, node_pos);
+ req = get_ppc32_in_req(irn, pos);
+ } else {
+ req = get_ppc32_out_req(irn, node_pos);
}
DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
-
- memcpy(req, &(irn_req->req), sizeof(*req));
-
- if (arch_register_req_is(&(irn_req->req), should_be_same)) {
- assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
- req->other_same = get_irn_n(irn, irn_req->same_pos);
- }
-
- if (arch_register_req_is(&(irn_req->req), should_be_different)) {
- assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
- req->other_different = get_irn_n(irn, irn_req->different_pos);
- }
+ return req;
}
- /* get requirements for FIRM nodes */
- else {
- /* treat Phi like Const with default requirements */
- if (is_Phi(irn)) {
- DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
- if (mode_is_float(mode)) {
- memcpy(req, &(ppc32_default_req_ppc32_fp.req), sizeof(*req));
- }
- else if (mode_is_int(mode) || mode_is_reference(mode)) {
- memcpy(req, &(ppc32_default_req_ppc32_gp.req), sizeof(*req));
- }
- else if (mode == mode_T || mode == mode_M) {
- DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
- return NULL;
- }
- else {
- assert(0 && "unsupported Phi-Mode");
- }
- }
- else {
- DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
- req = NULL;
- }
- }
+ /* unknowns should be transformed by now */
+ assert(!is_Unknown(irn));
- return req;
+ DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
+ return arch_no_register_req;
}
static void ppc32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
}
pos = ppc32_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj(irn);
}
if (is_ppc32_irn(irn)) {
}
pos = ppc32_translate_proj_pos(irn);
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
}
if (is_ppc32_irn(irn)) {
}
static arch_irn_class_t ppc32_classify(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_cfop(irn)) {
return arch_irn_class_branch;
}
static arch_irn_flags_t ppc32_get_flags(const void *self, const ir_node *irn) {
- irn = my_skip_proj(irn);
+ irn = skip_Proj_const(irn);
if (is_ppc32_irn(irn)) {
return get_ppc32_flags(irn);
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#ifdef _WIN32
* |_|
***********************************************************************************/
-/**
- * Returns a string containing the names of all registers within the limited bitset
- */
-static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
- bitset_t *bs = bitset_alloca(req->cls->n_regs);
- char *p = buf;
- int size = 0;
- int i, cnt;
-
- req->limited(NULL, bs);
-
- for (i = 0; i < req->cls->n_regs; i++) {
- if (bitset_is_set(bs, i)) {
- cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
- if (cnt < 0) {
- fprintf(stderr, "dumper problem, exiting\n");
- exit(1);
- }
-
- p += cnt;
- size += cnt;
-
- if (size >= max)
- break;
- }
- }
-
- return buf;
-}
-
/**
* Dumps the register requirements for either in or out.
*/
-static void dump_reg_req(FILE *F, ir_node *n, const ppc32_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) {
char *dir = inout ? "out" : "in";
int max = inout ? get_ppc32_n_res(n) : get_irn_arity(n);
- char *buf = alloca(1024);
+ char buf[1024];
int i;
- memset(buf, 0, 1024);
+ memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
- if (reqs[i]->req.type == arch_register_req_type_none) {
+ if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
- if (reqs[i]->req.type & arch_register_req_type_normal) {
- fprintf(F, " %s", reqs[i]->req.cls->name);
+ if (reqs[i]->type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->cls->name);
}
- if (reqs[i]->req.type & arch_register_req_type_limited) {
- fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ if (reqs[i]->type & arch_register_req_type_limited) {
+ fprintf(F, " %s",
+ arch_register_req_format(buf, sizeof(buf), reqs[i], n));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
- ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
}
- if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
- ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
+ if (reqs[i]->type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->other_different));
}
fprintf(F, "\n");
}
fprintf(F, "\n");
- }
- else {
+ } else {
fprintf(F, "%sreq = N/A\n", dir);
}
}
int bad = 0;
int i;
ppc32_attr_t *attr;
- const ppc32_register_req_t **reqs;
+ const arch_register_req_t **reqs;
const arch_register_t **slots;
switch (reason) {
/**
* Returns the argument register requirements of a ppc node.
*/
-const ppc32_register_req_t **get_ppc32_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_ppc32_in_req_all(const ir_node *node) {
ppc32_attr_t *attr = get_ppc32_attr(node);
return attr->in_req;
}
/**
* Returns the result register requirements of an ppc node.
*/
-const ppc32_register_req_t **get_ppc32_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_ppc32_out_req_all(const ir_node *node) {
ppc32_attr_t *attr = get_ppc32_attr(node);
return attr->out_req;
}
/**
* Returns the argument register requirement at position pos of an ppc node.
*/
-const ppc32_register_req_t *get_ppc32_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_ppc32_in_req(const ir_node *node, int pos) {
ppc32_attr_t *attr = get_ppc32_attr(node);
return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an ppc node.
*/
-const ppc32_register_req_t *get_ppc32_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos) {
ppc32_attr_t *attr = get_ppc32_attr(node);
return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
-void set_ppc32_req_out(ir_node *node, const ppc32_register_req_t *req, int pos) {
+void set_ppc32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
ppc32_attr_t *attr = get_ppc32_attr(node);
attr->out_req[pos] = req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_ppc32_req_in(ir_node *node, const ppc32_register_req_t *req, int pos) {
+void set_ppc32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
ppc32_attr_t *attr = get_ppc32_attr(node);
attr->in_req[pos] = req;
}
* Initializes ppc specific node attributes
*/
void init_ppc32_attributes(ir_node *node, int flags,
- const ppc32_register_req_t **in_reqs, const ppc32_register_req_t **out_reqs,
+ const arch_register_req_t **in_reqs, const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res, unsigned latency) {
ppc32_attr_t *attr = get_ppc32_attr(node);
/**
* Returns the argument register requirements of an ppc node.
*/
-const ppc32_register_req_t **get_ppc32_in_req_all(const ir_node *node);
+const arch_register_req_t **get_ppc32_in_req_all(const ir_node *node);
/**
* Returns the result register requirements of an ppc node.
*/
-const ppc32_register_req_t **get_ppc32_out_req_all(const ir_node *node);
+const arch_register_req_t **get_ppc32_out_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an ppc node.
*/
-const ppc32_register_req_t *get_ppc32_in_req(const ir_node *node, int pos);
+const arch_register_req_t *get_ppc32_in_req(const ir_node *node, int pos);
/**
* Returns the result register requirements of an ppc node.
*/
-const ppc32_register_req_t *get_ppc32_out_req(const ir_node *node, int pos);
+const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
-void set_ppc32_req_out(ir_node *node, const ppc32_register_req_t *req, int pos);
+void set_ppc32_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the IN register requirements at position pos.
*/
-void set_ppc32_req_in(ir_node *node, const ppc32_register_req_t *req, int pos);
+void set_ppc32_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the register flag of an ppc node.
ppc32_attr_offset_mode get_ppc32_offset_mode(const ir_node *node);
void init_ppc32_attributes(ir_node *node, int flags,
- const ppc32_register_req_t **in_reqs, const ppc32_register_req_t **out_reqs,
+ const arch_register_req_t **in_reqs, const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res, unsigned latency);
#include "../bearch.h"
-typedef struct _ppc32_register_req_t {
- const arch_register_req_t req;
- int same_pos; /**< in case of "should be same" we need to remember the pos to get the irn */
- int different_pos; /**< in case of "should be different" we need to remember the pos to get the irn */
-} ppc32_register_req_t;
-
typedef struct
{
unsigned shift:5;
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
int n_res; /**< number of results for this node */
- const ppc32_register_req_t **in_req; /**< register requirements for arguments */
- const ppc32_register_req_t **out_req; /**< register requirements for results */
+ const arch_register_req_t **in_req; /**< register requirements for arguments */
+ const arch_register_req_t **out_req; /**< register requirements for results */
ppc32_attr_content_type content_type;
ppc32_attr_offset_mode offset_mode;
int size = get_type_size_bytes(type);
int offset = 0;
- ir_node *load, *store;
+ ir_node *load, *store = NULL;
- if(size/4>=1)
+ if(size/4 >= 1)
{
ir_node *res;
tarval *offset0 = new_tarval_from_long(0, mode_Is);
struct tv_ent *entry;
ir_node *cnst,*symcnst;
ir_graph *rem;
- ir_entity *ent;
+ ir_entity *ent = NULL;
if(!const_set)
const_set = new_set(cmp_tv_ent, 10);
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <stdio.h>
our $arch;
our %nodes;
our %emit_templates;
+our $finish_line_template = "be_emit_finish_line_gas(emit, node);";
my $target_c = $target_dir."/gen_".$arch."_emitter.c";
my $target_h = $target_dir."/gen_".$arch."_emitter.h";
our $arch;
my @tokens = ($template =~ m/[^\%]+|\%[a-zA-Z_][a-zA-Z0-9_]*|\%./g);
- push(@{$result}, "${indent}${arch}_emit_char(env, '\t');\n");
+ push(@{$result}, "${indent}be_emit_char(emit, '\t');\n");
for (@tokens) {
SWITCH: {
if (/%\./) { last SWITCH; }
- if (/%%/) { push(@{$result}, "${indent}${arch}_emit_char(env, '%');\n"); last SWITCH; }
+ if (/%%/) { push(@{$result}, "${indent}be_emit_char(emit, '%');\n"); last SWITCH; }
if (/%(.+)/) {
if(defined($emit_templates{$1})) {
push(@{$result}, "${indent}$emit_templates{$1}\n");
} else {
print "Warning: No emit_template defined for '$1'\n";
- push(@{$result}, "${indent}$1(env, node);\n");
+ push(@{$result}, "${indent}$1(emit, node);\n");
}
last SWITCH;
}
- push(@{$result}, "${indent}${arch}_emit_cstring(env, \"$_\");\n");
+ push(@{$result}, "${indent}be_emit_cstring(emit, \"$_\");\n");
}
}
- push(@{$result}, "${indent}${arch}_emit_finish_line(env, node);\n");
+ push(@{$result}, "${indent}${finish_line_template}\n");
}
# skip this node description if no emit information is available
next if (!defined($n{"emit"}));
- $line = "static void emit_".$arch."_".$op."(${arch}_emit_env_t *env, const ir_node *node)";
+ $line = "static void emit_${arch}_${op}(${arch}_emit_env_t *env, const ir_node *node)";
push(@obst_register, " BE_EMIT($op);\n");
}
push(@obst_func, $line." {\n");
+ push(@obst_func, "\tbe_emit_env_t *emit = env->emit;\n");
+
my @emit = split(/\n/, $n{"emit"});
foreach my $template (@emit) {
*/
#include "irnode.h"
-#include "$arch\_emitter.h"
+#include "${arch}_emitter.h"
-void $arch\_register_spec_emitters(void);
+void ${arch}_register_spec_emitters(void);
#endif /* _GEN_$tmp\_EMITTER_H_ */
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "gen_$arch\_machine.h"
push(@obst_header, "void ".$arch."_create_opcodes(void);\n");
+# create default compare function
+if(defined($default_cmp_attr)) {
+ my $cmpcode = $default_cmp_attr;
+ push(@obst_cmp_attr, "static int default_cmp_attr(ir_node *a, ir_node *b) {\n");
+ if($cmpcode =~ m/attr_a/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
+ }
+ if($cmpcode =~ m/attr_b/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
+ }
+ push(@obst_cmp_attr, "\t${cmpcode}\n");
+ push(@obst_cmp_attr, "}\n\n");
+}
+
push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n");
foreach my $op (keys(%nodes)) {
my %n = %{ $nodes{"$op"} };
push(@obst_header, "ir_op *get_op_$op(void);\n");
push(@obst_header, "int is_$op(const ir_node *n);\n");
- $cmp_attr_func = 0;
+ my $cmp_attr_func;
+ if(defined($default_cmp_attr)) {
+ $cmp_attr_func = "default_cmp_attr";
+ }
# create compare attribute function if needed
- if (exists($n{"cmp_attr"}) || defined($default_cmp_attr)) {
+ if (exists($n{"cmp_attr"})) {
+ my $cmpcode = $n{"cmp_attr"};
+
push(@obst_cmp_attr, "static int cmp_attr_$op(ir_node *a, ir_node *b) {\n");
- push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
- push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
- push(@obst_cmp_attr, "\t(void) attr_a;\n");
- push(@obst_cmp_attr, "\t(void) attr_b;\n");
- if(exists($n{"cmp_attr"})) {
- push(@obst_cmp_attr, "\t".$n{"cmp_attr"}."\n");
- } else {
- push(@obst_cmp_attr, "\t$default_cmp_attr\n");
+ if($cmpcode =~ m/attr_a/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
+ }
+ if($cmpcode =~ m/attr_b/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
}
+ push(@obst_cmp_attr, "\t${cmpcode}\n");
push(@obst_cmp_attr, "}\n\n");
- $cmp_attr_func = 1;
+ $cmp_attr_func = "cmp_attr_${op}";
}
if (exists($n{"rd_constructor"}) && $n{"rd_constructor"} =~ /^NONE$/i) {
if (@in) {
$in_req_var = "_in_req_$op";
- $temp .= "\tstatic const $arch\_register_req_t *".$in_req_var."[] =\n";
+ $temp .= "\tstatic const arch_register_req_t *".$in_req_var."[] =\n";
$temp .= "\t{\n";
for ($idx = 0; $idx <= $#in; $idx++) {
- $temp .= "\t\t".$op."_reg_req_in_".$idx.",\n";
+ $temp .= "\t\t&".$op."_reg_req_in_".$idx.",\n";
}
$temp .= "\t};\n";
}
if (@out) {
$out_req_var = "_out_req_$op";
- $temp .= "\tstatic const $arch\_register_req_t *".$out_req_var."[] =\n";
+ $temp .= "\tstatic const arch_register_req_t *".$out_req_var."[] =\n";
$temp .= "\t{\n";
for ($idx = 0; $idx <= $#out; $idx++) {
- $temp .= "\t\t".$op."_reg_req_out_".$idx.",\n";
+ $temp .= "\t\t&".$op."_reg_req_out_".$idx.",\n";
}
$temp .= "\t};\n";
}
}
$temp .= "\n";
- $temp .= "\tif (!op_$op) {\n";
- $temp .= "\t\tassert(0);\n";
- $temp .= "\t\treturn NULL;\n";
- $temp .= "\t}\n\n";
+ $temp .= "\tassert(op_$op != NULL);\n\n";
+
for (my $i = 1; $i <= $arity; $i++) {
$temp .= "\tin[".($i - 1)."] = op".$i.";\n";
}
push(@obst_new_irop, "\n\tmemset(&ops, 0, sizeof(ops));\n");
push(@obst_new_irop, "\tops.dump_node = $arch\_dump_node;\n");
- if ($cmp_attr_func) {
- push(@obst_new_irop, "\tops.node_cmp_attr = cmp_attr_$op;\n");
+ if (defined($cmp_attr_func)) {
+ push(@obst_new_irop, "\tops.node_cmp_attr = ${cmp_attr_func};\n");
}
$n_opcodes++;
use strict;
use Data::Dumper;
+use integer;
my $specfile = $ARGV[0];
my $target_dir = $ARGV[1];
my $return;
-no strict "subs";
+use strict "subs";
unless ($return = do $specfile) {
warn "couldn't parse $specfile: $@" if $@;
warn "couldn't do $specfile: $!" unless defined $return;
my @obst_reginit; # stack for the register type inits
my @obst_req; # stack for the register requirements
my @obst_limit_func; # stack for functions to return a subset of a register class
-my @obst_defreq_head; # stack for prototypes of default requirement function
my @obst_header_all; # stack for some extern struct defs needed for bearch_$arch include
-my @obst_requirement_def; # stack for requirement name defines
+my @obst_header_t;
my $numregs;
my $class_ptr;
my $tmp;
my %reg2class;
-
-# there is a default NONE requirement
-$tmp = "/* Default NONE register requirements */\n";
-$tmp .= "const $arch\_register_req_t $arch\_default_req_none = {\n";
-$tmp .= " {\n";
-$tmp .= " arch_register_req_type_none, /* register type */\n";
-$tmp .= " NULL, /* register class */\n";
-$tmp .= " NULL, /* limit function */\n";
-$tmp .= " NULL, /* limit environment */\n";
-$tmp .= " NULL, /* node for same */\n";
-$tmp .= " NULL /* node for different */\n";
-$tmp .= " },\n";
-$tmp .= " 0, /* same pos */\n";
-$tmp .= " 0 /* different pos */\n";
-$tmp .= "};\n\n";
-push(@obst_req, $tmp);
-push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_none;\n");
+my %regclass2len;
push(@obst_classdef, "enum reg_classes {\n");
my $class_mode;
# assure, the initialization is done only once
-push(@obst_reginit, " static int run_once = 0;\n");
+push(@obst_reginit, "\tstatic int run_once = 0;\n");
push(@obst_reginit, "\n");
-push(@obst_reginit, " if (run_once)\n return;\n");
-push(@obst_reginit, " run_once = 1;\n");
+push(@obst_reginit, "\tif (run_once)\n");
+push(@obst_reginit, "\t\treturn;\n");
+push(@obst_reginit, "\trun_once = 1;\n");
# generate register type and class variable, init function and default requirements
foreach my $class_name (keys(%reg_classes)) {
push(@obst_regtypes_decl, "extern arch_register_t ".$class_name."_regs[$numregs];\n");
push(@obst_regtypes_def, "arch_register_t ".$class_name."_regs[$numregs];\n");
- push(@obst_classdef, " CLASS_$class_name = $class_idx,\n");
+ push(@obst_classdef, "\tCLASS_$class_name = $class_idx,\n");
push(@obst_regclasses, "{ \"$class_name\", $numregs, NULL, ".$class_name."_regs }");
- # there is a default NORMAL requirement for each class
- $tmp = "/* Default NORMAL register requirements for class $class_name */\n";
- $tmp .= "const $arch\_register_req_t $arch\_default_req_$class_name = {\n";
- $tmp .= " {\n";
- $tmp .= " arch_register_req_type_normal,\n";
- $tmp .= " $class_ptr,\n";
- $tmp .= " NULL, /* limit function */ \n";
- $tmp .= " NULL, /* limit environment */\n";
- $tmp .= " NULL, /* node for same */\n";
- $tmp .= " NULL /* node for different */\n";
- $tmp .= " },\n";
- $tmp .= " 0, /* same pos */\n";
- $tmp .= " 0 /* different pos */\n";
- $tmp .= "};\n\n";
- push(@obst_req, $tmp);
- push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_$class_name;\n");
-
my $idx = 0;
- push(@obst_reginit, " /* Init of all registers in class '$class_name' */\n\n");
- push(@obst_reginit, " /* set largest possible mode for '$class_name' */\n");
- push(@obst_reginit, " $arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n\n");
+ push(@obst_reginit, "\t/* Init of all registers in class '$class_name' */\n\n");
+ push(@obst_reginit, "\t/* set largest possible mode for '$class_name' */\n");
+ push(@obst_reginit, "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n\n");
push(@obst_regdef, "enum reg_".$class_name."_values {\n");
foreach (@class) {
- # For each class we build for each of it's member registers a limit function
- # which limits the class to this particular register. We also build the
- # corresponding requirement structs.
- # We need those functions to set register requirements on demand in transformation
- # esp. for Call and RegParams where we can mix int and float parameters.
-
- my $limit_func_name = $arch."_limit_".$class_name."_".$_->{"name"};
-
- # push the function prototype
- $tmp = "void $limit_func_name(void *_unused, bitset_t *bs)";
- push(@obst_defreq_head, $tmp.";\n");
-
- # push the function definition
- $tmp .= " {\n";
- $tmp .= " bs = bitset_clear_all(bs);\n";
- $tmp .= " bitset_set(bs, REG_".uc($_->{"name"}).");\n"; # REGISTER to index assignment is done some lines down
- $tmp .= "}\n\n";
- push(@obst_limit_func, $tmp);
-
- # push the default requirement struct
- $tmp = "const $arch\_register_req_t $arch\_default_req_$class_name\_".$_->{"name"}." = {\n";
- $tmp .= " {\n";
- $tmp .= " arch_register_req_type_limited,\n";
- $tmp .= " $class_ptr,\n";
- $tmp .= " $limit_func_name,\n";
- $tmp .= " NULL, /* limit environment */\n";
- $tmp .= " NULL, /* node for same */\n";
- $tmp .= " NULL /* node for different */\n";
- $tmp .= " },\n";
- $tmp .= " 0, /* same pos */\n";
- $tmp .= " 0 /* different pos */\n";
- $tmp .= "};\n\n";
- push(@obst_req, $tmp);
- push(@obst_header_all,"extern const $arch\_register_req_t $arch\_default_req_$class_name\_".$_->{"name"}.";\n");
-
# realname is name if not set by user
$_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
$reg2class{$_->{"name"}} = { "class" => $old_classname, "index" => $idx }; # remember reg to class for later use
- push(@obst_regdef, " REG_".uc($_->{"name"})." = $idx,\n");
- push(@obst_reginit, " ".$class_name."_regs[$idx].name = \"".$_->{"realname"}."\";\n");
- push(@obst_reginit, " ".$class_name."_regs[$idx].reg_class = $class_ptr;\n");
- push(@obst_reginit, " ".$class_name."_regs[$idx].index = $idx;\n");
- push(@obst_reginit, " ".$class_name."_regs[$idx].type = ".translate_reg_type($_->{"type"}).";\n");
- push(@obst_reginit, " ".$class_name."_regs[$idx].data = ".get_execunit_variable_name($_->{"unit"}).";\n");
+ push(@obst_regdef, "\tREG_".uc($_->{"name"})." = $idx,\n");
+ push(@obst_reginit, "\t${class_name}_regs[$idx].name = \"".$_->{"realname"}."\";\n");
+ push(@obst_reginit, "\t${class_name}_regs[$idx].reg_class = $class_ptr;\n");
+ push(@obst_reginit, "\t${class_name}_regs[$idx].index = $idx;\n");
+ push(@obst_reginit, "\t${class_name}_regs[$idx].type = ".translate_reg_type($_->{"type"}).";\n");
+ push(@obst_reginit, "\t${class_name}_regs[$idx].data = ".get_execunit_variable_name($_->{"unit"}).";\n");
push(@obst_reginit, "\n");
$idx++;
}
- push(@obst_regdef, " $numregs = $idx\n");
+ $regclass2len{$old_classname} = $idx;
+ push(@obst_regdef, "\t$numregs = $idx\n");
push(@obst_regdef, "};\n\n");
$class_idx++;
}
-push(@obst_classdef, " N_CLASSES = ".scalar(keys(%reg_classes))."\n");
+push(@obst_classdef, "\tN_CLASSES = ".scalar(keys(%reg_classes))."\n");
push(@obst_classdef, "};\n\n");
# generate node-register constraints
$tmp = uc($arch);
print OUT<<EOF;
-#ifndef _GEN_$tmp\_REGALLOC_IF_T_H_
-#define _GEN_$tmp\_REGALLOC_IF_T_H_
-
/**
* Generated register classes from spec.
*
* created by: $0 $specfile $target_dir
* date: $creation_time
*/
+#ifndef _GEN_${tmp}_REGALLOC_IF_T_H_
+#define _GEN_${tmp}_REGALLOC_IF_T_H_
+
+#include "gen_${arch}_regalloc_if.h"
EOF
-print OUT @obst_requirement_def;
+print OUT @obst_header_t;
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_T_H_ */\n";
$creation_time = localtime(time());
print OUT<<EOF;
-#ifndef _GEN_$tmp\_REGALLOC_IF_H_
-#define _GEN_$tmp\_REGALLOC_IF_H_
-
/**
* Contains additional external requirements defs for external includes.
*
* created by: $0 $specfile $target_dir
* date: $creation_time
*/
+#ifndef _GEN_${tmp}_REGALLOC_IF_H_
+#define _GEN_${tmp}_REGALLOC_IF_H_
#include "../bearch.h"
-#include "$arch\_nodes_attr.h"
+#include "${arch}_nodes_attr.h"
EOF
print OUT @obst_header_all, "\n";
-print OUT @obst_defreq_head, "\n";
-
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_H_ */\n";
close(OUT);
* created by: $0 $specfile $target_dir
* date: $creation_time
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
-#include "gen_$arch\_regalloc_if.h"
-#include "gen_$arch\_machine.h" /* we need this, as there can be units assigned to registers */
-#include "bearch_$arch\_t.h" /* we need this to put the caller saved registers into the isa set */
-#include "$arch\_map_regs.h"
+#include "gen_${arch}_regalloc_if.h"
+#include "gen_${arch}_machine.h"
+#include "bearch_${arch}_t.h"
+#include "${arch}_map_regs.h"
#include "irmode.h"
+#ifdef BIT
+#undef BIT
+#endif
+#define BIT(x) (1 << (x % 32))
+
EOF
-print OUT "arch_register_class_t $arch\_reg_classes[] = {\n ".join(",\n ", @obst_regclasses)."\n};\n\n";
+print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @obst_regclasses)."\n};\n\n";
print OUT @obst_regtypes_def, "\n";
-print OUT "void ".$arch."_register_init(void *isa_ptr) {\n";
+print OUT "void ${arch}_register_init(void *isa_ptr) {\n";
print OUT @obst_reginit;
print OUT "}\n\n";
if ($reqs[$idx] eq "none") {
$class = "none";
- }
- elsif (is_reg_class($reqs[$idx])) {
+ } elsif (is_reg_class($reqs[$idx])) {
$class = $reqs[$idx];
- }
- else {
+ } else {
my @regs = split(/ /, $reqs[$idx]);
GET_CLASS: foreach my $reg (@regs) {
if ($reg =~ /!?(in|out)\_r\d+/ || $reg =~ /!in/) {
for (my $idx = 0; $idx <= $#reqs; $idx++) {
my $class = undef;
- my $tmp2 = "const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx = ";
- my $tmp = "#define ".$op."_reg_req_$inout\_$idx ";
+ my $tmp2 = "const arch_register_req_t ${op}_reg_req_${inout}_${idx} = ";
if ($reqs[$idx] eq "none") {
- $tmp .= "&$arch\_default_req_none\n";
- }
- elsif ($reqs[$idx] =~ /^new_reg_(.*)$/) {
+ $tmp2 .= "{\n";
+ $tmp2 .= "\tarch_register_req_type_none,\n";
+ $tmp2 .= "\tNULL, /* regclass */\n";
+ $tmp2 .= "\tNULL, /* limit bitset */\n";
+ $tmp2 .= "\t-1, /* same pos */\n";
+ $tmp2 .= "\t-1 /* different pos */\n";
+ $tmp2 .= "};\n";
+
+ push(@obst_req, $tmp2."\n");
+ push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
+ } elsif ($reqs[$idx] =~ /^new_reg_(.*)$/) {
if (is_reg_class($1)) {
- $tmp .= "&_".$op."_reg_req_$inout\_$idx\n";
$tmp2 .= "{\n";
- $tmp2 .= " {\n";
- $tmp2 .= " arch_register_req_type_should_be_different_from_all,\n";
- $tmp2 .= " &$arch\_reg_classes[CLASS_$arch\_".$1."],\n";
- $tmp2 .= " NULL, /* limit function */\n";
- $tmp2 .= " NULL, /* limit environment */\n";
- $tmp2 .= " NULL, /* same node */\n";
- $tmp2 .= " NULL /* different node */\n";
- $tmp2 .= " },\n";
- $tmp2 .= " 0,\n";
- $tmp2 .= " 0\n";
+ $tmp2 .= "\tarch_register_req_type_should_be_different_from_all,\n";
+ $tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_$1],\n";
+ $tmp2 .= "\tNULL, /* limit bitset */\n";
+ $tmp2 .= "\t-1, /* same pos */\n";
+ $tmp2 .= "\t-1 /* different pos */\n";
$tmp2 .= "};\n";
push(@obst_req, $tmp2."\n");
- push(@obst_header_all, "extern const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx;\n");
- }
- else {
+ push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
+ } else {
print STDERR "Invalid register class '$1' given in OUT requirement $idx for '$op'.\n";
}
- }
- elsif (is_reg_class($reqs[$idx])) {
- $tmp .= "&$arch\_default_req_".$arch."_".$reqs[$idx]."\n";
- }
- else {
+ } elsif (is_reg_class($reqs[$idx])) {
+ my $class = $reqs[$idx];
+ $tmp2 .= "{\n";
+ $tmp2 .= "\tarch_register_req_type_normal,\n";
+ $tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_${class}],\n";
+ $tmp2 .= "\tNULL, /* limit bitset */\n";
+ $tmp2 .= "\t-1, /* same pos */\n";
+ $tmp2 .= "\t-1 /* different pos */\n";
+ $tmp2 .= "};\n";
+
+ push(@obst_req, $tmp2."\n");
+ push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
+ } else {
my @req_type_mask;
my ($class, $has_limit, $same_pos, $different_pos) = build_subset_class_func($n, $op, $idx, (($inout eq "in") ? 1 : 0), $reqs[$idx]);
if ($different_pos == 666) {
push(@req_type_mask, "arch_register_req_type_should_be_different_from_all");
undef $different_pos;
- }
- else {
+ } else {
push(@req_type_mask, "arch_register_req_type_should_be_different");
}
}
- $tmp .= "&_".$op."_reg_req_$inout\_$idx\n";
$tmp2 .= "{\n";
- $tmp2 .= " {\n";
- $tmp2 .= " ".join(" | ", @req_type_mask).",\n";
- $tmp2 .= " &$arch\_reg_classes[CLASS_$arch\_".$class."],\n";
- $tmp2 .= " ".($has_limit ? "limit_reg_".$op."_$inout\_".$idx : "NULL").",\n";
- $tmp2 .= " NULL, /* limit environment */\n";
- $tmp2 .= " NULL, /* same node */\n";
- $tmp2 .= " NULL /* different node */\n";
- $tmp2 .= " },\n";
- $tmp2 .= " ".(defined($same_pos) ? $same_pos : "0").",\n";
- $tmp2 .= " ".(defined($different_pos) ? $different_pos : "0")."\n";
+ $tmp2 .= "\t".join(" | ", @req_type_mask).",\n";
+ $tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_${class}],\n";
+ $tmp2 .= "\t".($has_limit ? "limit_reg_${op}_${inout}_${idx}" : "NULL").",\n";
+ $tmp2 .= "\t".(defined($same_pos) ? $same_pos : "-1").",\n";
+ $tmp2 .= "\t".(defined($different_pos) ? $different_pos : "-1")."\n";
$tmp2 .= "};\n";
push(@obst_req, $tmp2."\n");
- push(@obst_header_all, "extern const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx;\n");
+ push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
}
-
- push(@obst_requirement_def, $tmp);
}
}
my @obst_init;
my @obst_limits;
my @obst_ignore;
-
+ my @limit_array;
# build function header
my $n = shift;
if (!defined($neg)) {
$has_limit = 1;
- push(@obst_init, " bs = bitset_set_all(bs); /* allow all register (negative constraints given) */\n");
}
$_ = substr($_, 1); # skip '!'
$neg = 1;
- }
- else {
+ } else {
if (defined($neg) && $neg == 1) {
# we have seen a negative constraint as first one but this one is positive
# this doesn't make sense
return (undef, undef, undef, undef);
}
- if (!defined($neg)) {
- $has_limit = 1;
- push(@obst_init, " bs = bitset_clear_all(bs); /* disallow all register (positive constraints given) */\n");
- }
+ $has_limit = 1;
$neg = 0;
}
# set class
if (!defined($class)) {
$class = $temp;
- }
- elsif ($class ne $temp) {
+ } elsif ($class ne $temp) {
# all registers must belong to the same class
print STDERR "Registerclass mismatch. '$_' is not member of class '$class'.\n";
return (undef, undef, undef, undef);
}
- if ($neg == 1) {
- $has_limit = 1;
- push(@obst_limits, " bitset_clear(bs, ".get_reg_index($_)."); /* disallow $_ */\n");
- }
- else {
- $has_limit = 1;
- push(@obst_limits, " bitset_set(bs, ".get_reg_index($_)."); /* allow $_ */\n");
- }
+ # calculate position inside the initializer bitfield (only 32 bits per
+ # element)
+ my $regidx = get_reg_index($_);
+ my $arrayp = $regidx / 32;
+ push(@{$limit_array[$arrayp]}, $_);
}
- my @cur_class = @{ $reg_classes{"$class"} };
- for (my $idx = 0; $idx <= $#cur_class; $idx++) {
- if (defined($cur_class[$idx]{"type"}) && ($cur_class[$idx]{"type"} & 4)) {
- push(@obst_ignore, " bitset_clear(bs, ".get_reg_index($cur_class[$idx]{"name"}).");");
- push(@obst_ignore, " /* disallow ignore reg ".$cur_class[$idx]{"name"}." */\n");
+ # don't allow ignore regs in negative constraints
+ if($neg) {
+ my @cur_class = @{ $reg_classes{"$class"} };
+ for (my $idx = 0; $idx <= $#cur_class; $idx++) {
+ if (defined($cur_class[$idx]{"type"}) && ($cur_class[$idx]{"type"} & 4)) {
+ my $reg = $cur_class[$idx]{"name"};
+ my $regix = get_reg_index($reg);
+ my $arrayp = $regix / 32;
+ push(@{$limit_array[$arrayp]}, $reg);
+ }
}
}
if ($has_limit == 1) {
- push(@obst_header_all, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs);\n");
-
- push(@obst_limit_func, "/* limit the possible registers for ".($in ? "IN" : "OUT")." $idx at op $op */\n");
- push(@obst_limit_func, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs) {\n");
- push(@obst_limit_func, @obst_init);
- push(@obst_limit_func, @obst_ignore);
- push(@obst_limit_func, @obst_limits);
- push(@obst_limit_func, "}\n\n");
+ push(@obst_limit_func, "static const unsigned limit_reg_${op}_".($in ? "in" : "out")."_${idx}[] = { ");
+ my $first = 1;
+ my $limitbitsetlen = $regclass2len{$class};
+ my $limitarraylen = $limitbitsetlen / 32 + ($limitbitsetlen % 32 > 0 ? 1 : 0);
+ for(my $i = 0; $i < $limitarraylen; $i++) {
+ my $limitarraypart = $limit_array[$i];
+ if($first) {
+ $first = 0;
+ } else {
+ push(@obst_limit_func, ", ");
+ }
+ my $temp;
+ if($neg) {
+ $temp = "0xFFFFFFFF";
+ }
+ foreach my $reg (@{$limitarraypart}) {
+ if($neg) {
+ $temp .= " & ~";
+ } elsif(defined($temp)) {
+ $temp .= " | ";
+ }
+ $temp .= "BIT(REG_".uc(${reg}).")";
+ }
+ if(defined($temp)) {
+ push(@obst_limit_func, "${temp}");
+ } else {
+ push(@obst_limit_func, "0");
+ }
+ }
+ push(@obst_limit_func, " };\n");
}
return ($class, $has_limit, $same_pos, $different_pos);