+static ir_node *gen_Cond(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
+ ir_node *sel = get_Cond_selector(node);
+ ir_mode *sel_mode = get_irn_mode(sel);
+ ir_node *res = NULL;
+ ir_node *pred = NULL;
+ ir_node *cmp_a, *cmp_b, *cnst, *expr;
+
+ if (is_Proj(sel) && sel_mode == mode_b) {
+ pred = get_Proj_pred(sel);
+
+ /* get both compare operators */
+ cmp_a = get_Cmp_left(pred);
+ cmp_b = get_Cmp_right(pred);
+
+ /* check if we can use a CondJmp with immediate */
+ cnst = get_immediate_op(cmp_a, cmp_b);
+ expr = get_expr_op(cmp_a, cmp_b);
+
+ if (cnst && expr) {
+ res = new_rd_ia32_CondJmp_i(get_irn_dbg_info(node), current_ir_graph, block, expr, mode_T);
+ set_ia32_Immop_attr(res, cnst);
+ }
+ else {
+ res = new_rd_ia32_CondJmp(get_irn_dbg_info(node), current_ir_graph, block, cmp_a, cmp_b, mode_T);
+ }
+
+ set_ia32_pncode(res, get_Proj_proj(sel));
+ }
+ else {
+ res = new_rd_ia32_SwitchJmp(get_irn_dbg_info(node), current_ir_graph, block, sel, mode_T);
+ set_ia32_pncode(res, get_Cond_defaultProj(node));
+ }
+
+ return res;
+}
+
+
+
+/**
+ * Transform the argument projs from a start node corresponding to the
+ * calling convention.
+ * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
+ * "RegParam x -> ProjT -> Start" OR
+ * "StackParam x -> ProjM -> Start"
+ * whether parameter is passed in register or on stack.
+ *
+ * @param mod the debug module
+ * @param block the block the nodes should belong to
+ * @param proj the ProjT node which points to Start
+ * @param start the Start node
+ * @return Should be always NULL
+ */
+static ir_node *gen_Proj_Start(firm_dbg_module_t *mod, ir_node *block, ir_node *proj, ir_node *start) {
+ const ir_edge_t *edge;
+ ir_node *succ, *irn;
+ ir_node **projargs;
+ ir_mode *mode;
+ int n, i, j;
+ unsigned cc;
+ ir_node *proj_M = get_irg_initial_mem(current_ir_graph);
+ entity *irg_ent = get_irg_entity(current_ir_graph);
+ type *tp = get_entity_type(irg_ent);
+ int cur_gp_idx = 0;
+ int cur_fp_idx = 0;
+ int stack_idx = 0;
+ int done = 0;
+
+ assert(is_Method_type(tp) && "irg type is not a method");
+
+ switch(get_Proj_proj(proj)) {
+ case pn_Start_T_args:
+ /* We cannot use get_method_n_params here as the function might
+ be variadic or one argument is not used. */
+ n = get_irn_n_edges(proj);
+
+ /* we are done here when there are no parameters */
+ if (n < 1)
+ break;
+
+ /* temporary remember all proj arg x */
+ projargs = calloc(n, sizeof(ir_node *));
+
+ foreach_out_edge((const ir_node *)proj, edge) {
+ succ = get_edge_src_irn(edge);
+ assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
+ projargs[get_Proj_proj(succ)] = succ;
+ }
+
+ cc = get_method_calling_convention(tp);
+
+ /* get the correct order in case of 'this' call */
+ current_gpreg_param_req = gpreg_param_req_std;
+ current_fpreg_param_req = fpreg_param_req_std;
+ if (cc & cc_this_call) {
+ current_gpreg_param_req = gpreg_param_req_this;
+ current_fpreg_param_req = fpreg_param_req_this;
+ }
+
+ /* loop over all parameters and check whether its a int or float */
+ for (i = 0; i < n && !done && (cc & cc_reg_param); i++) {
+ mode = get_irn_mode(projargs[i]);
+
+ if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) {
+ /* parameter got passed in general purpose register */
+ irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
+ set_ia32_pncode(irn, i);
+ set_ia32_regreq_out(irn, current_gpreg_param_req[cur_gp_idx], 0);
+ cur_gp_idx++;
+ }
+ else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) {
+ /* parameter got passed in floating point register*/
+ irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
+ set_ia32_pncode(irn, i);
+ set_ia32_regreq_out(irn, current_fpreg_param_req[cur_fp_idx], 0);
+ cur_fp_idx++;
+ }
+
+ /* kill the old "Proj Arg" and replace with the new Arg */
+ exchange(projargs[i], irn);
+
+ if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) {
+ stack_idx = i;
+ done = 1;
+ }
+ }
+
+ /* create all remaining stack parameters */
+ if (cc & cc_last_on_top) {
+ for (i = stack_idx; i < n; i++) {
+ mode = get_irn_mode(projargs[i]);
+
+ if (mode_is_float(mode))
+ irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+ else
+ irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+
+ set_ia32_pncode(irn, i);
+
+ /* kill the old "Proj Arg" and replace with the new stack param */
+ exchange(projargs[i], irn);
+ }
+ }
+ else {
+ for (i = n - 1, j = stack_idx; i >= stack_idx; i--, j++) {
+ mode = get_irn_mode(projargs[i]);
+
+ if (mode_is_float(mode))
+ irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+ else
+ irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+
+ set_ia32_pncode(irn, j);
+
+ /* kill the old "Proj Arg" and replace with the new stack param */
+ exchange(projargs[i], irn);
+ }
+ }
+
+ free(projargs);
+
+ break;
+ case pn_Start_X_initial_exec:
+ case pn_Start_M:
+ case pn_Start_P_frame_base:
+ case pn_Start_P_globals:
+ case pn_Start_P_value_arg_base:
+ break;
+ default:
+ assert(0 && "unsupported Proj(Start)");
+ }
+
+ return NULL;
+}
+
+/**
+ * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
+ * All others are ignored.
+ *
+ * @param mod the debug module
+ * @param block the block the new node should belong to
+ * @param node the ir Proj node
+ * @param mode mode of the Proj
+ * @return The transformed node.
+ */
+static ir_node *gen_Proj(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
+ ir_node *new_node = NULL;
+ ir_node *pred = get_Proj_pred(node);
+
+ if (mode == mode_M)
+ return NULL;
+
+ if (get_irn_op(pred) == op_Start) {
+ new_node = gen_Proj_Start(mod, block, node, pred);
+ }
+
+ return new_node;