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);
+}

Reply via email to