if (current_function_contains_functions)
return "function with nested functions cannot be inline";
- /* This restriction may be eliminated sometime soon. But for now, don't
- worry about remapping the static chain. */
- if (current_function_needs_context)
- return "nested function cannot be inline";
-
/* If its not even close, don't even look. */
if (!DECL_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
return "function too large to be inline";
struct inline_remap *map;
rtx cc0_insn = 0;
rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
+ rtx static_chain_value = 0;
/* Allow for equivalences of the pseudos we make for virtual fp and ap. */
max_regno = MAX_REGNUM (header) + 3;
&& (GET_CODE (arg_vals[i]) == REG
|| GET_CODE (arg_vals[i]) == SUBREG
|| GET_CODE (arg_vals[i]) == MEM)
- && reg_overlap_mentioned_p (arg_vals[i], target))))
+ && reg_overlap_mentioned_p (arg_vals[i], target))
+ /* ??? We must always copy a SUBREG into a REG, because it might
+ get substituted into an address, and not all ports correctly
+ handle SUBREGs in addresses. */
+ || (GET_CODE (arg_vals[i]) == SUBREG)))
arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);
}
map->min_insnno = 0;
map->max_insnno = INSN_UID (header);
+ map->integrating = 1;
+
/* const_equiv_map maps pseudos in our routine to constants, so it needs to
be large enough for all our pseudos. This is the number we are currently
using plus the number in the called routine, plus 15 for each arg,
if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
current_function_uses_pic_offset_table = 1;
+ /* If this function needs a context, set it up. */
+ if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_NEEDS_CONTEXT)
+ static_chain_value = lookup_static_chain (fndecl);
+
/* Process each argument. For each, set up things so that the function's
reference to the argument will refer to the argument being passed.
We only replace REG with REG here. Any simplifications are done
else
break;
}
+ /* If this is setting the static chain pseudo, set it from
+ the value we want to give it instead. */
+ else if (static_chain_value != 0
+ && GET_CODE (pattern) == SET
+ && rtx_equal_p (SET_SRC (pattern),
+ static_chain_incoming_rtx))
+ {
+ rtx newdest = copy_rtx_and_substitute (SET_DEST (pattern), map);
+
+ copy = emit_insn (gen_rtx (SET, VOIDmode, newdest,
+ static_chain_value));
+
+ static_chain_value = 0;
+ }
else
copy = emit_insn (copy_rtx_and_substitute (pattern, map));
/* REG_NOTES will be copied later. */
map->insn_map[INSN_UID (insn)] = copy;
}
- /* Now copy the REG_NOTES. */
+ /* Now copy the REG_NOTES. Increment const_age, so that only constants
+ from parameters can be substituted in. These are the only ones that
+ are valid across the entire function. */
+ map->const_age++;
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && map->insn_map[INSN_UID (insn)])
- REG_NOTES (map->insn_map[INSN_UID (insn)])
- = copy_rtx_and_substitute (REG_NOTES (insn), map);
+ && map->insn_map[INSN_UID (insn)]
+ && REG_NOTES (insn))
+ {
+ rtx tem = copy_rtx_and_substitute (REG_NOTES (insn), map);
+ /* We must also do subst_constants, in case one of our parameters
+ has const type and constant value. */
+ subst_constants (&tem, NULL_RTX, map);
+ apply_change_group ();
+ REG_NOTES (map->insn_map[INSN_UID (insn)]) = tem;
+ }
if (local_return_label)
emit_label (local_return_label);
emit_line_note (input_filename, lineno);
if (structure_value_addr)
- return gen_rtx (MEM, TYPE_MODE (type),
- memory_address (TYPE_MODE (type), structure_value_addr));
+ {
+ target = gen_rtx (MEM, TYPE_MODE (type),
+ memory_address (TYPE_MODE (type), structure_value_addr));
+ MEM_IN_STRUCT_P (target) = 1;
+ }
return target;
}
\f
XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
- RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
+
+ /* If doing function inlining, this MEM might not be const in the
+ function that it is being inlined into, and thus may not be
+ unchanging after function inlining. Constant pool references are
+ handled elsewhere, so this doesn't lose RTX_UNCHANGING_P bits
+ for them. */
+ if (! map->integrating)
+ RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
+
return copy;
}
rtx head = DECL_SAVED_INSNS (fndecl);
rtx last;
- temporary_allocation ();
-
current_function_decl = fndecl;
/* This call is only used to initialize global variables. */
rest_of_compilation (fndecl);
current_function_decl = 0;
-
- permanent_allocation ();
}