#define SNPRINTF_BUF_LEN 128
-static set *cur_reg_set = NULL;
+static const arch_env_t *arch_env = NULL;
/*************************************************************
static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
ir_node *op;
const arch_register_t *reg = NULL;
- const arch_register_t **slots;
assert(get_irn_arity(irn) > pos && "Invalid IN position");
in register we need. */
op = get_irn_n(irn, pos);
- if (is_Proj(op)) {
- pos = (int)translate_proj_pos(op);
- while(is_Proj(op))
- op = get_Proj_pred(op);
- }
+ reg = arch_get_irn_register(arch_env, op);
- if (is_ia32_irn(op)) {
- /* The operator is an ia32 node: this node has only one out */
- slots = get_ia32_slots(op);
- reg = slots[0];
- }
- else {
- /* The operator is not an ia32 node: check for Phi or Proj */
- if (is_Phi(op)) {
- /* Phi's getting register assigned */
- reg = ia32_get_firm_reg(NULL, op, cur_reg_set);
- assert(reg && "No register assigned to Phi node");
- }
- else {
- assert(0 && "Unsupported node for IN register");
- }
- }
+ assert(reg && "could not get in register");
return reg;
}
static const lc_arg_handler_t ia32_mode_handler = { ia32_get_arg_type, ia32_get_mode_suffix };
if(env == NULL) {
- env = firm_get_arg_env();
+ env = lc_arg_new_env();
lc_arg_register(env, "ia32:sreg", 's', &ia32_reg_handler);
lc_arg_register(env, "ia32:dreg", 'd', &ia32_reg_handler);
return buf;
}
+
+/*************************************************
+ * _ _ _
+ * (_) | | |
+ * ___ _ __ ___ _| |_ ___ ___ _ __ __| |
+ * / _ \ '_ ` _ \| | __| / __/ _ \| '_ \ / _` |
+ * | __/ | | | | | | |_ | (_| (_) | | | | (_| |
+ * \___|_| |_| |_|_|\__| \___\___/|_| |_|\__,_|
+ *
+ *************************************************/
+
/*
* coding of conditions
*/
finish_CondJmp(F, irn);
}
+
+
+/*********************************************************
+ * _ _ _
+ * (_) | (_)
+ * ___ _ __ ___ _| |_ _ _ _ _ __ ___ _ __ ___
+ * / _ \ '_ ` _ \| | __| | | | | | '_ ` _ \| '_ \/ __|
+ * | __/ | | | | | | |_ | | |_| | | | | | | |_) \__ \
+ * \___|_| |_| |_|_|\__| | |\__,_|_| |_| |_| .__/|___/
+ * _/ | | |
+ * |__/ |_|
+ *********************************************************/
+
+/* jump table entry (target and corresponding number) */
typedef struct _branch_t {
ir_node *target;
int value;
} branch_t;
+/* jump table for switch generation */
typedef struct _jmp_tbl_t {
- ir_node *defProj;
- int min_value;
- int max_value;
- int num_branches;
- char *label;
- branch_t *branches;
+ ir_node *defProj; /**< default target */
+ int min_value; /**< smallest switch case */
+ int max_value; /**< largest switch case */
+ int num_branches; /**< number of jumps */
+ char *label; /**< label of the jump table */
+ branch_t *branches; /**< jump array */
} jmp_tbl_t;
-/* Compare two variables of type branch_t */
+/**
+ * Compare two variables of type branch_t. Used to sort all switch cases
+ */
static int ia32_cmp_branch_t(const void *a, const void *b) {
branch_t *b1 = (branch_t *)a;
branch_t *b2 = (branch_t *)b;
tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
tbl.defProj = NULL;
tbl.num_branches = get_irn_n_edges(irn);
- tbl.branches = calloc(tbl.num_branches, sizeof(*(tbl.branches)));
+ tbl.branches = calloc(tbl.num_branches, sizeof(tbl.branches[0]));
tbl.min_value = INT_MAX;
tbl.max_value = INT_MIN;
}
/* sort the branches by their number */
- qsort(tbl.branches, tbl.num_branches, sizeof(*(tbl.branches)), ia32_cmp_branch_t);
+ qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), ia32_cmp_branch_t);
/* two-complement's magic make this work without overflow */
interval = tbl.max_value - tbl.min_value;
fprintf(F, "\tjmp %s\t\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
}
+ if (tbl.label)
+ free(tbl.label);
if (tbl.branches)
free(tbl.branches);
}
ir_fprintf(F, "\tjmp %s\t\t\t/* Jmp(%+F) */\n", get_cfop_target(irn, buf), get_irn_link(irn));
}
+
+
+/****************************
+ * _
+ * (_)
+ * _ __ _ __ ___ _ ___
+ * | '_ \| '__/ _ \| |/ __|
+ * | |_) | | | (_) | |\__ \
+ * | .__/|_| \___/| ||___/
+ * | | _/ |
+ * |_| |__/
+ ****************************/
+
/**
* Emits code for a proj -> node
*/
}
}
+
+
+/***********************************************************************************
+ * _ __ _
+ * (_) / _| | |
+ * _ __ ___ __ _ _ _ __ | |_ _ __ __ _ _ __ ___ _____ _____ _ __| | __
+ * | '_ ` _ \ / _` | | '_ \ | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
+ * | | | | | | (_| | | | | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
+ * |_| |_| |_|\__,_|_|_| |_| |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\
+ *
+ ***********************************************************************************/
+
/**
- * Main emitting function
+ * Emits code for a node.
*/
void ia32_emit_node(ir_node *irn, void *env) {
emit_env_t *emit_env = env;
/**
* Main driver
*/
-void ia32_gen_routine(FILE *F, ir_graph *irg, set *reg_set) {
+void ia32_gen_routine(FILE *F, ir_graph *irg, const arch_env_t *env) {
emit_env_t emit_env;
- emit_env.mod = firm_dbg_register("be.codegen.ia32");
- emit_env.out = F;
- emit_env.reg_set = reg_set;
+ emit_env.mod = firm_dbg_register("ir.be.codegen.ia32");
+ emit_env.out = F;
+ emit_env.arch_env = env;
- cur_reg_set = reg_set;
+ arch_env = env;
ia32_emit_start(F, irg);
irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);