This patch has bootstrapped and tested on powerpc64le-unknown-linux-gnu
with no regressions. Is this ok for the trunk?
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48344 for the original
problem report. The error resulted because gcc's processing of
command-line options within gcc initialization code originally preceded
the processing of target-specific configuration hooks.
In the unpatched gcc implementation, the Pmode (pointer mode) variable
has not been initialized at the time the -fstack-limit-register
command-line option is processed. As a consequence, the stack-limiting
register is not assigned a proper mode. Thus, rtl instructions that
make use of this stack-limiting register have an unspecified mode, and
are therefore not matched by any known instructions.
The fix represented in this patch is to defer the command-line
processing related to command-line specification of a stack-limiting
register until after target-specific initialization has been completed.
Some questions and issues raised in response to version 2 of this patch
are addressed below:
1. Concerns regarding possible unintended consequences that might result
from moving all target-specific initialization to precede the invocation
of the handle_common_deferred_options () function are addressed by
preserving the original initialization order and moving the relevant
command-line processing to follow the target-specific initialization.
2. A question was raised as to whether Pmode can change with attribute
target. It cannot.
gcc/ChangeLog:
2016-01-27 Kelvin Nilsen <kel...@gcc.gnu.org>
* toplev.c (do_compile): Invoke finish_deferred_option_handling ()
upon return from process_options () and provide comment to explain
why.
* opts-global.c (handle_common_deferred_options): Introduce static
variables opt_fstack_limit_symbol_arg and
opt_fstack_limit_register_no to remember command-line options
that cannot be processed until after target-specific
initialization has been completed. Modify the handling of the
OPT_fstack_limit_register_ and OPT_fstack_limit_symbol_
command-line options to defer processing.
(finish_deferred_option_handling): New function to
complete the command-line processing associated with the
OPT_fstack_limit_register_ and OPT_fstack_limit_symbol_
command-line options.
* opts.h: New declaration of finish_deferred_option_handling.
gcc/testsuite/ChangeLog:
2016-01-27 Kelvin Nilsen <kel...@gcc.gnu.org>
* gcc.target/powerpc/pr48344-1.c: New test.
Index: gcc/testsuite/gcc.target/powerpc/pr48344-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr48344-1.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr48344-1.c (revision 232633)
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fstack-limit-register=r2" } */
+void foo ()
+{
+ int N = 2;
+ int slots[N];
+
+}
+
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c (revision 232135)
+++ gcc/toplev.c (working copy)
@@ -1938,7 +1938,10 @@ standard_type_bitsize (int bitsize)
static void
do_compile ()
{
+ /* process_options () performs target-specific initialization. Upon
+ return from process_options (), Pmode has a meaningful value. */
process_options ();
+ finish_deferred_option_handling ();
/* Don't do any more if an error has already occurred. */
if (!seen_error ())
Index: gcc/opts.h
===================================================================
--- gcc/opts.h (revision 232135)
+++ gcc/opts.h (working copy)
@@ -372,6 +372,7 @@ extern void control_warning_option (unsigned int o
extern char *write_langs (unsigned int mask);
extern void print_ignored_options (void);
extern void handle_common_deferred_options (void);
+extern void finish_deferred_option_handling (void);
extern bool common_handle_option (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
Index: gcc/opts-global.c
===================================================================
--- gcc/opts-global.c (revision 232135)
+++ gcc/opts-global.c (working copy)
@@ -310,6 +310,31 @@ decode_options (struct gcc_options *opts, struct g
finish_options (opts, opts_set, loc);
}
+/* During execution of handle_common_deferred_options (), the Pmode
+ variable cannot be used because it has not yet been initialized.
+ For this reason, handling of the OPT_fstack_limit_register_ and
+ OPT_fstack_limit_symbol_ options is deferred until execution
+ of finish_deferred_option_handling (), which is invoked following
+ target-specific initialization.
+
+ The variable opt_fstack_limit_symbol_arg represents the name
+ of the register specified in an OPT_fstack_limit_symbol_ command
+ line option, or NULL to represent that no OPT_fstack_limit_symbol_
+ option is active.
+
+ The variable opt_fstack_limit_register_no represents the number of
+ the register specified in an OPT_fstack_limit_register_
+ command-line option, or -1 to indicate that no
+ OPT_fstack_limit_register_ option is active. (Legal register
+ numbers are all >= 0.)
+
+ Note that these two command-line options are mutually exclusive.
+ If both are specified, subsequent option processing overwrites
+ earlier option processing. */
+
+static const char *opt_fstack_limit_symbol_arg = NULL;
+static int opt_fstack_limit_register_no = -1;
+
/* Process common options that have been deferred until after the
handlers have been called for all options. */
@@ -417,12 +442,18 @@ handle_common_deferred_options (void)
if (reg < 0)
error ("unrecognized register name %qs", opt->arg);
else
- stack_limit_rtx = gen_rtx_REG (Pmode, reg);
+ {
+ /* Deactivate previous OPT_fstack_limit_symbol_ options */
+ opt_fstack_limit_symbol_arg = NULL;
+ opt_fstack_limit_register_no = reg;
+ }
}
break;
case OPT_fstack_limit_symbol_:
- stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt->arg));
+ /* Deactivate previous OPT_fstack_limit_register_ options */
+ opt_fstack_limit_register_no = -1;
+ opt_fstack_limit_symbol_arg = opt->arg;
break;
case OPT_fasan_shadow_offset_:
@@ -442,3 +473,17 @@ handle_common_deferred_options (void)
}
}
}
+
+/* Finish handling options that handle_common_deferred_options () left
+ unhandled because target-specific initialization had not yet been
+ completed. */
+void
+finish_deferred_option_handling (void)
+{
+ if (opt_fstack_limit_symbol_arg != NULL)
+ stack_limit_rtx
+ = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt_fstack_limit_symbol_arg));
+
+ if (opt_fstack_limit_register_no >= 0)
+ stack_limit_rtx = gen_rtx_REG (Pmode, opt_fstack_limit_register_no);
+}