+ int n_params = get_method_n_params(mtp);
+ int i;
+
+ /* 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->high_signed ||
+ mode == env->high_unsigned)
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Determine which modes need to be lowered */
+static void setup_modes(lower_env_t *env)
+{
+ unsigned size_bits = env->params->doubleword_size;
+ ir_mode *doubleword_signed = NULL;
+ ir_mode *doubleword_unsigned = NULL;
+ int n_modes = get_irp_n_modes();
+ ir_mode_arithmetic arithmetic;
+ unsigned modulo_shift;
+ int i;
+
+ /* search for doubleword modes... */
+ for (i = 0; i < n_modes; ++i) {
+ ir_mode *mode = get_irp_mode(i);
+ if (!mode_is_int(mode))
+ continue;
+ if (get_mode_size_bits(mode) != size_bits)
+ continue;
+ if (mode_is_signed(mode)) {
+ if (doubleword_signed != NULL) {
+ /* sigh - the lowerer should really just lower all mode with
+ * size_bits it finds. Unfortunately this required a bigger
+ * rewrite. */
+ panic("multiple double word signed modes found");
+ }
+ doubleword_signed = mode;
+ } else {
+ if (doubleword_unsigned != NULL) {
+ /* sigh - the lowerer should really just lower all mode with
+ * size_bits it finds. Unfortunately this required a bigger
+ * rewrite. */
+ panic("multiple double word unsigned modes found");
+ }
+ doubleword_unsigned = mode;
+ }
+ }
+ if (doubleword_signed == NULL || doubleword_unsigned == NULL) {
+ panic("Couldn't find doubleword modes");
+ }
+
+ arithmetic = get_mode_arithmetic(doubleword_signed);
+ modulo_shift = get_mode_modulo_shift(doubleword_signed);
+
+ assert(get_mode_size_bits(doubleword_unsigned) == size_bits);
+ assert(size_bits % 2 == 0);
+ assert(get_mode_sign(doubleword_signed) == 1);
+ assert(get_mode_sign(doubleword_unsigned) == 0);
+ assert(get_mode_sort(doubleword_signed) == irms_int_number);
+ assert(get_mode_sort(doubleword_unsigned) == irms_int_number);
+ assert(get_mode_arithmetic(doubleword_unsigned) == arithmetic);
+ assert(get_mode_modulo_shift(doubleword_unsigned) == modulo_shift);
+
+ /* try to guess a sensible modulo shift for the new mode.
+ * (This is IMO another indication that this should really be a node
+ * attribute instead of a mode thing) */
+ if (modulo_shift == size_bits) {
+ modulo_shift = modulo_shift / 2;
+ } else if (modulo_shift == 0) {
+ /* fine */
+ } else {
+ panic("Don't know what new modulo shift to use for lowered doubleword mode");
+ }
+ size_bits /= 2;
+
+ /* produce lowered modes */
+ env->high_signed = doubleword_signed;
+ env->high_unsigned = doubleword_unsigned;
+ env->low_signed = new_ir_mode("WS", irms_int_number, size_bits, 1,
+ arithmetic, modulo_shift);
+ env->low_unsigned = new_ir_mode("WU", irms_int_number, size_bits, 0,
+ arithmetic, modulo_shift);
+}
+
+static void enqueue_preds(lower_env_t *env, ir_node *node)
+{
+ int arity = get_irn_arity(node);
+ int i;
+
+ for (i = 0; i < arity; ++i) {
+ ir_node *pred = get_irn_n(node, i);
+ pdeq_putr(env->waitq, pred);
+ }
+}
+
+static void lower_node(lower_env_t *env, ir_node *node)
+{
+ int arity;
+ int i;
+ lower_func func;
+ ir_op *op;
+ ir_mode *mode;
+ unsigned idx;