typedef struct _lower_env_t {
node_entry_t **entries; /**< entries per node */
struct obstack obst; /**< an obstack holding the temporary data */
+ ir_type *l_mtp; /**< lowered method type of the current method */
tarval *tv_mode_bytes; /**< a tarval containing the number of bytes in the lowered modes */
tarval *tv_mode_bits; /**< a tarval containing the number of bits in the lowered modes */
pdeq *waitq; /**< a wait queue of all nodes that must be handled later */
pmap *proj_2_block; /**< a map from ProjX to its destination blocks */
+ ident *first_id; /**< .l for little and .h for big endian */
+ ident *next_id; /**< .h for little and .l for big endian */
const lwrdw_param_t *params; /**< transformation parameter */
unsigned flags; /**< some flags */
int n_entries; /**< number of entries */
+#ifndef NDEBUG
+ ir_type *value_param_tp; /**< the old value param type */
+#endif
} lower_env_t;
/**
/**
* Lower the method type.
+ *
+ * @param mtp the method type to lower
+ * @param ent the lower environment
+ *
+ * @return the lowered type
*/
static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) {
pmap_entry *entry;
- ident *id;
- ir_type *res;
+ ident *id, *lid;
+ ir_type *res, *value_type;
if (is_lowered_type(mtp))
return mtp;
} /* if */
} /* for */
- id = id_mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
+ id = id_mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
res = new_type_method(id, n_param, n_res);
/* set param types and result types */
} /* for */
set_lowered_type(mtp, res);
pmap_insert(lowered_type, mtp, res);
+
+ value_type = get_method_value_param_type(mtp);
+ if (value_type != NULL) {
+ /* this creates a new value parameter type */
+ (void)get_method_value_param_ent(res, 0);
+
+ /* set new param positions */
+ for (i = n_param = 0; i < n; ++i) {
+ ir_type *tp = get_method_param_type(mtp, i);
+ ident *id = get_method_param_ident(mtp, i);
+ ir_entity *ent = get_method_value_param_ent(mtp, i);
+
+ set_entity_link(ent, INT_TO_PTR(n_param));
+ if (is_Primitive_type(tp)) {
+ ir_mode *mode = get_type_mode(tp);
+
+ if (mode == env->params->high_signed || mode == env->params->high_unsigned) {
+ if (id != NULL) {
+ lid = id_mangle(id, env->first_id);
+ set_method_param_ident(res, n_param, lid);
+ set_entity_ident(get_method_value_param_ent(res, n_param), lid);
+ lid = id_mangle(id, env->next_id);
+ set_method_param_ident(res, n_param + 1, lid);
+ set_entity_ident(get_method_value_param_ent(res, n_param + 1), lid);
+ } /* if */
+ n_param += 2;
+ continue;
+ } /* if */
+ } /* if */
+ if (id != NULL) {
+ set_method_param_ident(res, n_param, id);
+ set_entity_ident(get_method_value_param_ent(res, n_param), id);
+ } /* if */
+ ++n_param;
+ } /* for */
+
+ set_lowered_type(value_type, get_method_value_param_type(res));
+ } /* if */
} else {
res = entry->value;
} /* if */
env->entries[idx]->high_word = new_rd_Mux(dbg, irg, block, sel, false_h, true_h, mode);
} /* lower_Mux */
-static void lower_ASM(ir_node *asmn, ir_mode *mode, lower_env_t *env)
-{
+/**
+ * Translate an ASM node.
+ */
+static void lower_ASM(ir_node *asmn, ir_mode *mode, lower_env_t *env) {
ir_mode *his = env->params->high_signed;
ir_mode *hiu = env->params->high_unsigned;
int i;
ir_mode *op_mode = get_irn_mode(get_irn_n(asmn, i));
if (op_mode == his || op_mode == hiu) {
panic("lowering ASM unimplemented");
- }
- }
+ } /* if */
+ } /* for */
for (n = asmn;;) {
ir_mode *proj_mode;
proj_mode = get_irn_mode(n);
if (proj_mode == his || proj_mode == hiu) {
panic("lowering ASM unimplemented");
- }
- }
-}
+ } /* if */
+ } /* for */
+} /* lower_ASM */
+
+/**
+ * Translate a Sel node.
+ */
+static void lower_Sel(ir_node *sel, ir_mode *mode, lower_env_t *env) {
+ ir_node *ptr = get_Sel_ptr(sel);
+
+ if (ptr == get_irg_value_param_base(current_ir_graph)) {
+ ir_entity *ent = get_Sel_entity(sel);
+ int pos = PTR_TO_INT(get_entity_link(ent));
+
+ assert(get_entity_owner(ent) == env->value_param_tp);
+
+ ent = get_method_value_param_ent(env->l_mtp, pos);
+ set_Sel_entity(sel, ent);
+ } /* if */
+} /* lower_Sel */
/**
* check for opcodes that must always be lowered.
case iro_Return:
case iro_Cond:
case iro_Conv:
+ case iro_Sel:
return 1;
default:
return 0;
(void) size;
return (e1->imode - e2->imode) | (e1->omode - e2->omode);
-} /* static int cmp_conv_tp */
+} /* cmp_conv_tp */
/**
* Enter a lowering function into an ir_op.
*/
static void enter_lower_func(ir_op *op, lower_func func) {
op->ops.generic = (op_func)func;
-}
+} /* enter_lower_func */
+
+/**
+ * Returns non-zero if a method type must be lowered.
+ *
+ * @param mtp the method type
+ */
+static int mtp_must_to_lowered(ir_type *mtp, lower_env_t *env) {
+ int i, n_params;
+
+ n_params = get_method_n_params(mtp);
+ if (n_params <= 0)
+ return 0;
+
+ /* first check if we have parameters that must be fixed */
+ for (i = 0; i < n_params; ++i) {
+ ir_type *tp = get_method_param_type(mtp, i);
+
+ if (is_Primitive_type(tp)) {
+ ir_mode *mode = get_type_mode(tp);
+
+ if (mode == env->params->high_signed ||
+ mode == env->params->high_unsigned)
+ return 1;
+ } /* if */
+ } /* for */
+ return 0;
+} /* mtp_must_to_lowered */
/*
* Do the lowering.
void lower_dw_ops(const lwrdw_param_t *param)
{
lower_env_t lenv;
- int i;
- ir_graph *rem;
+ int i;
+ ir_graph *rem;
if (! param)
return;
lenv.tv_mode_bits = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), param->low_unsigned);
lenv.waitq = new_pdeq();
lenv.params = param;
+ lenv.first_id = new_id_from_chars(param->little_endian ? ".l" : ".h", 2);
+ lenv.next_id = new_id_from_chars(param->little_endian ? ".h" : ".l", 2);
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
LOWER(DivMod);
LOWER(Div);
LOWER(Mod);
+ LOWER(Sel);
LOWER_UN(Abs);
LOWER_UN(Minus);
/* transform all graphs */
rem = current_ir_graph;
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- ir_graph *irg = get_irp_irg(i);
+ ir_graph *irg = get_irp_irg(i);
+ ir_entity *ent;
+ ir_type *mtp;
int n_idx;
obstack_init(&lenv.obst);
lenv.entries = NEW_ARR_F(node_entry_t *, n_idx);
memset(lenv.entries, 0, n_idx * sizeof(lenv.entries[0]));
- /* first step: link all nodes and allocate data */
- lenv.flags = 0;
+ lenv.l_mtp = NULL;
+ lenv.flags = 0;
lenv.proj_2_block = pmap_create();
-
+#ifndef NDEBUG
+ lenv.value_param_tp = NULL;
+#endif
ir_reserve_resources(irg, IR_RESOURCE_PHI_LIST | IR_RESOURCE_IRN_LINK);
+ ent = get_irg_entity(irg);
+ mtp = get_entity_type(ent);
+
+ if (mtp_must_to_lowered(mtp, &lenv)) {
+ ir_type *ltp = lower_mtp(mtp, &lenv);
+ lenv.flags |= MUST_BE_LOWERED;
+ set_entity_type(ent, ltp);
+ lenv.l_mtp = ltp;
+#ifndef NDEBUG
+ lenv.value_param_tp = get_method_value_param_type(mtp);
+#endif
+ } /* if */
+
+ /* first step: link all nodes and allocate data */
irg_walk_graph(irg, firm_clear_node_and_phi_links, prepare_links_and_handle_rotl, &lenv);
if (lenv.flags & MUST_BE_LOWERED) {