/* Target machine subroutines for Altera Nios II.
- Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ Copyright (C) 2012-2020 Free Software Foundation, Inc.
Contributed by Jonah Graham (jgraham@altera.com),
Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
Contributed by Mentor Graphics, Inc.
{
gcc_assert (GP_REG_P (regno));
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
+ if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
return true;
if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
warning (0, "switch %<-mcustom-%s%> has no effect unless "
- "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
+ "%<-funsafe-math-optimizations%> is specified",
+ N2FPU_NAME (i));
/* Warn if the user is trying to use -mcustom-fmins et. al, that won't
get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
warning (0, "switch %<-mcustom-%s%> has no effect unless "
- "-ffinite-math-only is specified", N2FPU_NAME (i));
+ "%<-ffinite-math-only%> is specified", N2FPU_NAME (i));
/* Warn if the user is trying to use a custom rounding instruction
that won't get used without -fno-math-errno. See
for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
if (N2FPU_ENABLED_P (i) && N2FPU_NO_ERRNO_P (i))
warning (0, "switch %<-mcustom-%s%> has no effect unless "
- "-fno-math-errno is specified", N2FPU_NAME (i));
+ "%<-fno-math-errno%> is specified", N2FPU_NAME (i));
if (errors || custom_code_conflict)
fatal_error (input_location,
- "conflicting use of -mcustom switches, target attributes, "
- "and/or __builtin_custom_ functions");
+ "conflicting use of %<-mcustom%> switches, target attributes, "
+ "and/or %<__builtin_custom_%> functions");
}
static void
sorry ("position-independent code requires the Linux ABI");
if (flag_pic && stack_limit_rtx
&& GET_CODE (stack_limit_rtx) == SYMBOL_REF)
- sorry ("PIC support for -fstack-limit-symbol");
+ sorry ("PIC support for %<-fstack-limit-symbol%>");
/* Function to allocate machine-dependent function status. */
init_machine_status = &nios2_init_machine_status;
if (flag_pic)
{
if (nios2_gpopt_option != gpopt_none)
- error ("-mgpopt not supported with PIC.");
+ error ("%<-mgpopt%> not supported with PIC.");
if (nios2_gprel_sec)
- error ("-mgprel-sec= not supported with PIC.");
+ error ("%<-mgprel-sec=%> not supported with PIC.");
if (nios2_r0rel_sec)
- error ("-mr0rel-sec= not supported with PIC.");
+ error ("%<-mr0rel-sec=%> not supported with PIC.");
}
/* Process -mgprel-sec= and -m0rel-sec=. */
{
if (regcomp (&nios2_gprel_sec_regex, nios2_gprel_sec,
REG_EXTENDED | REG_NOSUB))
- error ("-mgprel-sec= argument is not a valid regular expression.");
+ error ("%<-mgprel-sec=%> argument is not a valid regular expression.");
}
if (nios2_r0rel_sec)
{
if (regcomp (&nios2_r0rel_sec_regex, nios2_r0rel_sec,
REG_EXTENDED | REG_NOSUB))
- error ("-mr0rel-sec= argument is not a valid regular expression.");
+ error ("%<-mr0rel-sec=%> argument is not a valid regular expression.");
}
/* If we don't have mul, we don't have mulx either! */
*total = COSTS_N_INSNS (2); /* Latency adjustment. */
else
*total = COSTS_N_INSNS (1);
+ if (TARGET_HAS_MULX && GET_MODE (x) == DImode)
+ {
+ enum rtx_code c0 = GET_CODE (XEXP (x, 0));
+ enum rtx_code c1 = GET_CODE (XEXP (x, 1));
+ if ((c0 == SIGN_EXTEND && c1 == SIGN_EXTEND)
+ || (c0 == ZERO_EXTEND && c1 == ZERO_EXTEND))
+ /* This is the <mul>sidi3 pattern, which expands into 4 insns,
+ 2 multiplies and 2 moves. */
+ {
+ *total = *total * 2 + COSTS_N_INSNS (2);
+ return true;
+ }
+ }
return false;
}
if (nios2_small_section_name_p (section))
return true;
}
+ else if (flexible_array_type_p (TREE_TYPE (exp))
+ && (!TREE_PUBLIC (exp) || DECL_EXTERNAL (exp)))
+ {
+ /* We really should not consider any objects of any flexibly-sized
+ type to be small data, but pre-GCC 10 did not test
+ for this and just fell through to the next case. Thus older
+ code compiled with -mgpopt=global could contain GP-relative
+ accesses to objects defined in this compilation unit with
+ external linkage. We retain the possible small-data treatment
+ of such definitions for backward ABI compatibility, but
+ no longer generate GP-relative accesses for external
+ references (so that the ABI could be changed in the future
+ with less potential impact), or objects with internal
+ linkage. */
+ return false;
+ }
else
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
push the argument on the stack, or a hard register in which to
store the argument.
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
CUM is a variable of type CUMULATIVE_ARGS which gives info about
the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
+ ARG is a description of the argument. */
static rtx
-nios2_function_arg (cumulative_args_t cum_v, machine_mode mode,
- const_tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+nios2_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
rtx return_rtx = NULL_RTX;
if (cum->regs_used < NUM_ARG_REGS)
- return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
+ return_rtx = gen_rtx_REG (arg.mode, FIRST_ARG_REGNO + cum->regs_used);
return return_rtx;
}
in memory. */
static int
-nios2_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode, tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+nios2_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- HOST_WIDE_INT param_size;
-
- if (mode == BLKmode)
- {
- param_size = int_size_in_bytes (type);
- gcc_assert (param_size >= 0);
- }
- else
- param_size = GET_MODE_SIZE (mode);
+ HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
+ gcc_assert (param_size >= 0);
/* Convert to words (round up). */
param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
return 0;
}
-/* Update the data in CUM to advance over an argument of mode MODE
- and data type TYPE; TYPE is null for libcalls where that information
- may not be available. */
+/* Update the data in CUM to advance over argument ARG. */
static void
-nios2_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
- const_tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+nios2_function_arg_advance (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- HOST_WIDE_INT param_size;
-
- if (mode == BLKmode)
- {
- param_size = int_size_in_bytes (type);
- gcc_assert (param_size >= 0);
- }
- else
- param_size = GET_MODE_SIZE (mode);
+ HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
+ gcc_assert (param_size >= 0);
/* Convert to words (round up). */
param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
own va_arg type. */
static void
nios2_setup_incoming_varargs (cumulative_args_t cum_v,
- machine_mode mode, tree type,
- int *pretend_size, int second_time)
+ const function_arg_info &arg,
+ int *pretend_size, int second_time)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
CUMULATIVE_ARGS local_cum;
cfun->machine->uses_anonymous_args = 1;
local_cum = *cum;
- nios2_function_arg_advance (local_cum_v, mode, type, true);
+ nios2_function_arg_advance (local_cum_v, arg);
regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
{
if (!custom_insn_opcode (value, VOIDmode))
error ("custom instruction opcode must be compile time "
- "constant in the range 0-255 for __builtin_custom_%s",
+ "constant in the range 0-255 for %<__builtin_custom_%s%>",
custom_builtin_name[index]);
}
else
int ignore ATTRIBUTE_UNUSED)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
- unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
if (fcode < nios2_fpu_builtin_base)
{
continue;
if (!ISDIGIT (*t))
{
- error ("`custom-%s=' argument requires "
- "numeric digits", N2FPU_NAME (code));
+ error ("%<custom-%s=%> argument should be "
+ "a non-negative integer", N2FPU_NAME (code));
return false;
}
}
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Stop pretending to be a post-reload pass. */
reload_completed = 0;