Patchwork rs6000_handle_option global state avoidance, part 1

login
register
mail settings
Submitter Joseph S. Myers
Date May 4, 2011, 11:54 a.m.
Message ID <Pine.LNX.4.64.1105041152530.25186@digraph.polyomino.org.uk>
Download mbox | patch
Permalink /patch/94010/
State New
Headers show

Comments

Joseph S. Myers - May 4, 2011, 11:54 a.m.
This patch implements the simpler parts of stopping
rs6000_handle_option from using global state.  Many options are
converted to use .opt features such as Var and Enum, replacing
explicit code, while other code is changed to use the opts and
opts_set pointers.  -mabi=, -mcpu= and -mtune= will be dealt with in
separate patches (this patch only does the more mechanical parts of
stopping them from using global state).  rs6000_explicit_options is
replaced by use of global_options_set and the opts_set pointer.

Two options, -mcmodel= and -mfpu=, had cases that fell through to the
next case without comments to indicate if this was intended.  I added
comments to make the semantics explicit.  Given the documentation, it
may well be intentional for -mcmodel= but is more doubtful for -mfpu=.

The "On 64-bit Darwin, power alignment is ABI-incompatible" check was
moved to rs6000_option_override_internal because macros such as
DEFAULT_ABI and TARGET_64BIT can implicitly use global state, and it's
better to make such checks on the state after all options have been
parsed (so they don't depend on the ordering of options on the command
line) anyway.  The commented-out RS6000_DEFAULT_LONG_DOUBLE_SIZE
definition in eabispe.h (referencing an obsolete ABI version) was
removed for the same reason (implicitly uses global state, which is
inconsistent with how this macro is used).  (A subsequent patch will
arrange for automatically-generated macros such as TARGET_64BIT to
have variants taking a pointer to a gcc_options structure, for use in
the option override hook when that gets a part that works on options
structures split out.)

Tested building cc1 and xgcc for crosses to: powerpc-eabi
powerpc-eabispe powerpc-linux-gnuspe powerpc-linux-gnu
powerpc64-linux-gnu powerpc-darwin powerpc-ibm-aix4.3
powerpc-ibm-aix5.2.0 powerpc-ibm-aix5.3.0 powerpc-ibm-aix6.1.  Also
bootstrapped with no regressions on x86_64-unknown-linux-gnu to test
the *.awk changes.  Will commit to trunk in the absence of target
maintainer objections.

2011-05-04  Joseph Myers  <joseph@codesourcery.com>

	* opt-functions.awk (var_type_struct): Handle Enum options.
	* optc-gen.awk: Don't check range of variables of character type.
	* config/rs6000/rs6000.c (rs6000_sched_insert_nops_str,
	rs6000_sched_costly_dep_str, rs6000_recip_name, rs6000_abi_name,
	rs6000_sdata_name, rs6000_explicit_options): Remove.
	(rs6000_option_override_internal): Check for -malign-power here.
	Use global_options_set instead of rs6000_explicit_options.
	(rs6000_parse_fpu_option): Remove.
	(rs6000_handle_option): Access variables via opts and opts_set
	pointers.  Use error_at and warning_at.  Add fall-through
	comments.  Don't handle OPT_mcmodel_, OPT_maix_struct_return,
	OPT_msvr4_struct_return, OPT_mvrsave, OPT_mspe, OPT_mcall_,
	OPT_msdata_, OPT_mtls_size_, OPT_mtraceback_, OPT_mfloat_gprs_,
	OPT_msched_costly_dep_, OPT_malign_ or OPT_mrecip_ explicitly
	here.  Don't use rs6000_parse_fpu_option.
	* config/rs6000/rs6000.h (fpu_type): Remove declaration.
	* config/rs6000/rs6000.opt (rs6000_long_double_type_size,
	rs6000_spe, rs6000_float_gprs): Remove TargetVariable entries.
	(mrecip=): Use Var.
	(mspe): Use Var and Save.
	(mtraceback=): Use Enum and Var.
	(rs6000_traceback_type): New Enum and EnumValue entries.
	(mfloat-gprs=): Use Enum, Var and Save.
	(rs6000_float_gprs): New Enum and EnumValue entries.
	(mlong-double-): use Var and Save.
	(msched-costly-dep=, minsert-sched-nops=): Use Var.
	(malign-): Use Enum and Var.
	(rs6000_alignment_flags): New Enum and EnumValue entries.
	(mfpu=): Use Enum.
	(fpu_type_t): New Enum and EnumValue entries.
	* config/rs6000/aix43.h (SUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/aix52.h (SUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/aix53.h (SUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/aix61.h (SUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/e500-double.h (SUB3TARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/eabispe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	(RS6000_DEFAULT_LONG_DOUBLE_SIZE): Remove commented-out
	definition.
	* config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/linux64.opt (mcmodel=): Use Enum and Var.
	(rs6000_cmodel): New Enum and EnumValue entries.
	* config/rs6000/linuxspe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Use
	global_options_set instead of rs6000_explicit_options.
	* config/rs6000/sysv4.opt (mcall-, msdata=): Use Var.
	(mtls-size=): Use Enum and Var.
	(rs6000_tls_size): New Enum and EnumValue entries.
David Edelsohn - May 5, 2011, 3:29 p.m.
On Wed, May 4, 2011 at 7:54 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:

> Two options, -mcmodel= and -mfpu=, had cases that fell through to the
> next case without comments to indicate if this was intended.  I added
> comments to make the semantics explicit.  Given the documentation, it
> may well be intentional for -mcmodel= but is more doubtful for -mfpu=.

I doubt that either of the fall through cases was intended.

Alan, is mcmodel suppose to set m64?

Michael, is mfpu suppose to set mrecip?

The rest of the patch looks like a faithful translation.

Thanks, David

>  #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
>     case OPT_mcmodel_:
> -      if (strcmp (arg, "small") == 0)
> -       rs6000_current_cmodel = CMODEL_SMALL;
> -      else if (strcmp (arg, "medium") == 0)
> -       rs6000_current_cmodel = CMODEL_MEDIUM;
> -      else if (strcmp (arg, "large") == 0)
> -       rs6000_current_cmodel = CMODEL_LARGE;
> -      else
> -       {
> -         error ("invalid option for -mcmodel: '%s'", arg);
> -         return false;
> -       }
> -      rs6000_explicit_options.cmodel = true;
> +      /* Fall through.  */
>  #endif
>
>  #ifdef TARGET_USES_AIX64_OPT
> @@ -4261,9 +4224,9 @@ rs6000_handle_option (struct gcc_options
>  #else
>     case OPT_m64:
>  #endif
> -      target_flags |= MASK_POWERPC64 | MASK_POWERPC;
> -      target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
> -      target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
> +      opts->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
> +      opts->x_target_flags |= ~opts_set->x_target_flags & MASK_PPC_GFXOPT;
> +      opts_set->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
>       break;

>     case OPT_mfpu_:
> -      fpu_type = rs6000_parse_fpu_option(arg);
> -      if (fpu_type != FPU_NONE)
> -      /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on HARD_FLOAT. */
> -      {
> -        target_flags &= ~MASK_SOFT_FLOAT;
> -        target_flags_explicit |= MASK_SOFT_FLOAT;
> -        rs6000_xilinx_fpu = 1;
> -        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
> -        rs6000_single_float = 1;
> -        if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
> -          rs6000_single_float = rs6000_double_float = 1;
> -        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
> -          rs6000_simple_fpu = 1;
> -      }
> +      fpu_type = (enum fpu_type_t) value;
> +      if (fpu_type != FPU_NONE)
> +       {
> +         /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on
> +            HARD_FLOAT. */
> +         opts->x_target_flags &= ~MASK_SOFT_FLOAT;
> +         opts_set->x_target_flags |= MASK_SOFT_FLOAT;
> +         opts->x_rs6000_xilinx_fpu = 1;
> +         if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
> +           opts->x_rs6000_single_float = 1;
> +         if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
> +           opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
> +         if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
> +           opts->x_rs6000_simple_fpu = 1;
> +       }
>       else
> -      {
> -        /* -mfpu=none is equivalent to -msoft-float */
> -        target_flags |= MASK_SOFT_FLOAT;
> -        target_flags_explicit |= MASK_SOFT_FLOAT;
> -        rs6000_single_float = rs6000_double_float = 0;
> -      }
> +       {
> +         /* -mfpu=none is equivalent to -msoft-float.  */
> +         opts->x_target_flags |= MASK_SOFT_FLOAT;
> +         opts_set->x_target_flags |= MASK_SOFT_FLOAT;
> +         opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
> +       }
> +      /* Fall through.  */
Michael Eager - May 5, 2011, 5:08 p.m.
David Edelsohn wrote:
> On Wed, May 4, 2011 at 7:54 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> 
>> Two options, -mcmodel= and -mfpu=, had cases that fell through to the
>> next case without comments to indicate if this was intended.  I added
>> comments to make the semantics explicit.  Given the documentation, it
>> may well be intentional for -mcmodel= but is more doubtful for -mfpu=.
> 
> I doubt that either of the fall through cases was intended.
> 
> Alan, is mcmodel suppose to set m64?
> 
> Michael, is mfpu suppose to set mrecip?

No.  There was a break statement at the end of case OPT_mfpu which
disappeared when OPT_mrecip was added.

> 
> The rest of the patch looks like a faithful translation.
> 
> Thanks, David
> 
>>  #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
>>     case OPT_mcmodel_:
>> -      if (strcmp (arg, "small") == 0)
>> -       rs6000_current_cmodel = CMODEL_SMALL;
>> -      else if (strcmp (arg, "medium") == 0)
>> -       rs6000_current_cmodel = CMODEL_MEDIUM;
>> -      else if (strcmp (arg, "large") == 0)
>> -       rs6000_current_cmodel = CMODEL_LARGE;
>> -      else
>> -       {
>> -         error ("invalid option for -mcmodel: '%s'", arg);
>> -         return false;
>> -       }
>> -      rs6000_explicit_options.cmodel = true;
>> +      /* Fall through.  */
>>  #endif
>>
>>  #ifdef TARGET_USES_AIX64_OPT
>> @@ -4261,9 +4224,9 @@ rs6000_handle_option (struct gcc_options
>>  #else
>>     case OPT_m64:
>>  #endif
>> -      target_flags |= MASK_POWERPC64 | MASK_POWERPC;
>> -      target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
>> -      target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
>> +      opts->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
>> +      opts->x_target_flags |= ~opts_set->x_target_flags & MASK_PPC_GFXOPT;
>> +      opts_set->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
>>       break;
> 
>>     case OPT_mfpu_:
>> -      fpu_type = rs6000_parse_fpu_option(arg);
>> -      if (fpu_type != FPU_NONE)
>> -      /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on HARD_FLOAT. */
>> -      {
>> -        target_flags &= ~MASK_SOFT_FLOAT;
>> -        target_flags_explicit |= MASK_SOFT_FLOAT;
>> -        rs6000_xilinx_fpu = 1;
>> -        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
>> -        rs6000_single_float = 1;
>> -        if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
>> -          rs6000_single_float = rs6000_double_float = 1;
>> -        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
>> -          rs6000_simple_fpu = 1;
>> -      }
>> +      fpu_type = (enum fpu_type_t) value;
>> +      if (fpu_type != FPU_NONE)
>> +       {
>> +         /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on
>> +            HARD_FLOAT. */
>> +         opts->x_target_flags &= ~MASK_SOFT_FLOAT;
>> +         opts_set->x_target_flags |= MASK_SOFT_FLOAT;
>> +         opts->x_rs6000_xilinx_fpu = 1;
>> +         if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
>> +           opts->x_rs6000_single_float = 1;
>> +         if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
>> +           opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
>> +         if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
>> +           opts->x_rs6000_simple_fpu = 1;
>> +       }
>>       else
>> -      {
>> -        /* -mfpu=none is equivalent to -msoft-float */
>> -        target_flags |= MASK_SOFT_FLOAT;
>> -        target_flags_explicit |= MASK_SOFT_FLOAT;
>> -        rs6000_single_float = rs6000_double_float = 0;
>> -      }
>> +       {
>> +         /* -mfpu=none is equivalent to -msoft-float.  */
>> +         opts->x_target_flags |= MASK_SOFT_FLOAT;
>> +         opts_set->x_target_flags |= MASK_SOFT_FLOAT;
>> +         opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
>> +       }
>> +      /* Fall through.  */
>
Michael Meissner - May 5, 2011, 7:08 p.m.
On Thu, May 05, 2011 at 10:08:24AM -0700, Michael Eager wrote:
> David Edelsohn wrote:
> >On Wed, May 4, 2011 at 7:54 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> >
> >>Two options, -mcmodel= and -mfpu=, had cases that fell through to the
> >>next case without comments to indicate if this was intended.  I added
> >>comments to make the semantics explicit.  Given the documentation, it
> >>may well be intentional for -mcmodel= but is more doubtful for -mfpu=.
> >
> >I doubt that either of the fall through cases was intended.
> >
> >Alan, is mcmodel suppose to set m64?
> >
> >Michael, is mfpu suppose to set mrecip?
> 
> No.  There was a break statement at the end of case OPT_mfpu which
> disappeared when OPT_mrecip was added.

Yes, it was an error on my part.  Sorry.  I will fix the GCC 4.6 branch.  I
will hold off fixing the on trunk, on the assumption this patch will go in.  I
can fix it if desired.
Alan Modra - May 5, 2011, 10:45 p.m.
On Thu, May 05, 2011 at 11:29:13AM -0400, David Edelsohn wrote:
> Alan, is mcmodel suppose to set m64?

No, that was an accident.

Patch

Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(revision 173345)
+++ gcc/optc-gen.awk	(working copy)
@@ -629,6 +629,8 @@  if (have_save) {
 					var_target_range[name] = "0, 255"
 				else if (otype ~ "^signed +char *$")
 					var_target_range[name] = "-128, 127"
+				if (otype == var_type(flags[i]))
+					var_target_range[name] = ""
 			}
 			else
 				var_target_other[n_target_other++] = name;
Index: gcc/opt-functions.awk
===================================================================
--- gcc/opt-functions.awk	(revision 173345)
+++ gcc/opt-functions.awk	(working copy)
@@ -192,6 +192,10 @@  function var_type_struct(flags)
 {
 	if (flag_set_p("UInteger", flags))
 		return "int "
+	else if (flag_set_p("Enum.*", flags)) {
+		en = opt_args("Enum", flags);
+		return enum_type[en] " "
+	}
 	else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) {
 		if (flag_set_p(".*Mask.*", flags))
 			return "int "
Index: gcc/config/rs6000/aix53.h
===================================================================
--- gcc/config/rs6000/aix53.h	(revision 173345)
+++ gcc/config/rs6000/aix53.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Definitions of target machine for GNU compiler,
    for IBM RS/6000 POWER running AIX V5.3.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by David Edelsohn (edelsohn@gnu.org).
 
@@ -39,7 +39,7 @@  do {									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
       rs6000_long_double_type_size = 64;				\
-      if (rs6000_explicit_options.long_double)				\
+      if (global_options_set.x_rs6000_long_double_type_size)		\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
   if (TARGET_POWERPC64 && ! TARGET_64BIT)				\
Index: gcc/config/rs6000/linuxspe.h
===================================================================
--- gcc/config/rs6000/linuxspe.h	(revision 173345)
+++ gcc/config/rs6000/linuxspe.h	(working copy)
@@ -28,11 +28,11 @@ 
 #define SUBSUBTARGET_OVERRIDE_OPTIONS \
   if (rs6000_select[1].string == NULL) \
     rs6000_cpu = PROCESSOR_PPC8540; \
-  if (!rs6000_explicit_options.spe_abi) \
+  if (!global_options_set.x_rs6000_spe_abi) \
     rs6000_spe_abi = 1; \
-  if (!rs6000_explicit_options.float_gprs) \
+  if (!global_options_set.x_rs6000_float_gprs) \
     rs6000_float_gprs = 1; \
-  if (!rs6000_explicit_options.spe) \
+  if (!global_options_set.x_rs6000_spe) \
     rs6000_spe = 1; \
   if (target_flags & MASK_64BIT) \
     error ("-m64 not supported in this configuration")
Index: gcc/config/rs6000/linux64.opt
===================================================================
--- gcc/config/rs6000/linux64.opt	(revision 173345)
+++ gcc/config/rs6000/linux64.opt	(working copy)
@@ -1,6 +1,6 @@ 
 ; Options for 64-bit PowerPC Linux.
 ;
-; Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
+; Copyright (C) 2005, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
 ; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
 ;
 ; This file is part of GCC.
@@ -24,5 +24,19 @@  Target Report Var(profile_kernel) Save
 Call mcount for profiling before a function prologue
 
 mcmodel=
-Target RejectNegative Joined
+Target RejectNegative Joined Enum(rs6000_cmodel) Var(rs6000_current_cmodel)
 Select code model
+
+Enum
+Name(rs6000_cmodel) Type(enum rs6000_cmodel)
+Known code models (for use with the -mcmodel= option):
+
+EnumValue
+Enum(rs6000_cmodel) String(small) Value(CMODEL_SMALL)
+
+EnumValue
+Enum(rs6000_cmodel) String(medium) Value(CMODEL_MEDIUM)
+
+EnumValue
+Enum(rs6000_cmodel) String(large) Value(CMODEL_LARGE)
+
Index: gcc/config/rs6000/sysv4.opt
===================================================================
--- gcc/config/rs6000/sysv4.opt	(revision 173345)
+++ gcc/config/rs6000/sysv4.opt	(working copy)
@@ -1,6 +1,7 @@ 
 ; SYSV4 options for PPC port.
 ;
-; Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+; Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+; Free Software Foundation, Inc.
 ; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
 ;
 ; This file is part of GCC.
@@ -20,17 +21,29 @@ 
 ; <http://www.gnu.org/licenses/>.
 
 mcall-
-Target RejectNegative Joined
+Target RejectNegative Joined Var(rs6000_abi_name)
 Select ABI calling convention
 
 msdata=
-Target RejectNegative Joined
+Target RejectNegative Joined Var(rs6000_sdata_name)
 Select method for sdata handling
 
 mtls-size=
-Target RejectNegative Joined
+Target RejectNegative Joined Var(rs6000_tls_size) Enum(rs6000_tls_size)
 Specify bit size of immediate TLS offsets
 
+Enum
+Name(rs6000_tls_size) Type(int)
+
+EnumValue
+Enum(rs6000_tls_size) String(16) Value(16)
+
+EnumValue
+Enum(rs6000_tls_size) String(32) Value(32)
+
+EnumValue
+Enum(rs6000_tls_size) String(64) Value(64)
+
 mbit-align
 Target Report Var(TARGET_NO_BITFIELD_TYPE) Save
 Align to the base type of the bit-field
Index: gcc/config/rs6000/aix43.h
===================================================================
--- gcc/config/rs6000/aix43.h	(revision 173345)
+++ gcc/config/rs6000/aix43.h	(working copy)
@@ -1,7 +1,7 @@ 
 /* Definitions of target machine for GNU compiler,
    for IBM RS/6000 POWER running AIX version 4.3.
    Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
-   2007, 2009, 2010 Free Software Foundation, Inc.
+   2007, 2009, 2010, 2011 Free Software Foundation, Inc.
    Contributed by David Edelsohn (edelsohn@gnu.org).
 
    This file is part of GCC.
@@ -39,7 +39,7 @@  do {									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
       rs6000_long_double_type_size = 64;				\
-      if (rs6000_explicit_options.long_double)				\
+      if (global_options_set.x_rs6000_long_double_type_size)		\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
   if (TARGET_POWERPC64 && ! TARGET_64BIT)				\
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 173345)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -47,10 +47,6 @@  enum rs6000_dependence_cost rs6000_sched
 TargetVariable
 enum rs6000_nop_insertion rs6000_sched_insert_nops = sched_finish_none
 
-;; Size of long double.
-TargetVariable
-unsigned char rs6000_long_double_type_size
-
 ;; IEEE quad extended precision long double.
 TargetVariable
 unsigned char rs6000_ieeequad
@@ -59,18 +55,10 @@  unsigned char rs6000_ieeequad
 TargetVariable
 unsigned char rs6000_altivec_abi
 
-;; Nonzero if we want SPE SIMD instructions.
-TargetVariable
-int rs6000_spe
-
 ;; Nonzero if we want SPE ABI extensions.
 TargetVariable
 unsigned char rs6000_spe_abi
 
-;; Nonzero if floating point operations are done in the GPRs.
-TargetVariable
-unsigned char rs6000_float_gprs
-
 ;; Nonzero if we want Darwin's struct-by-value-in-regs ABI.
 TargetVariable
 unsigned char rs6000_darwin64_abi
@@ -311,7 +299,7 @@  Target Report
 Generate software reciprocal divide and square root for better throughput.
 
 mrecip=
-Target Report RejectNegative Joined
+Target Report RejectNegative Joined Var(rs6000_recip_name)
 Generate software reciprocal divide and square root for better throughput.
 
 mrecip-precision
@@ -378,7 +366,7 @@  Target RejectNegative Alias(misel)
 Deprecated option.  Use -misel instead
 
 mspe
-Target
+Target Var(rs6000_spe) Save
 Generate SPE SIMD instructions on E500
 
 mpaired
@@ -410,9 +398,21 @@  Target RejectNegative Joined
 -mtune=	Schedule code for given CPU
 
 mtraceback=
-Target RejectNegative Joined
+Target RejectNegative Joined Enum(rs6000_traceback_type) Var(rs6000_traceback)
 -mtraceback=	Select full, part, or no traceback table
 
+Enum
+Name(rs6000_traceback_type) Type(enum rs6000_traceback_type)
+
+EnumValue
+Enum(rs6000_traceback_type) String(full) Value(traceback_full)
+
+EnumValue
+Enum(rs6000_traceback_type) String(part) Value(traceback_part)
+
+EnumValue
+Enum(rs6000_traceback_type) String(no) Value(traceback_none)
+
 mlongcall
 Target Report Var(rs6000_default_long_calls) Save
 Avoid all range limits on call instructions
@@ -430,25 +430,51 @@  Target Var(rs6000_warn_altivec_long) Ini
 Warn about deprecated 'vector long ...' AltiVec type usage
 
 mfloat-gprs=
-Target RejectNegative Joined
+Target RejectNegative Joined Enum(rs6000_float_gprs) Var(rs6000_float_gprs) Save
 -mfloat-gprs=	Select GPR floating point method
 
+Enum
+Name(rs6000_float_gprs) Type(unsigned char)
+Valid arguments to -mfloat-gprs=:
+
+EnumValue
+Enum(rs6000_float_gprs) String(yes) Value(1)
+
+EnumValue
+Enum(rs6000_float_gprs) String(single) Value(1)
+
+EnumValue
+Enum(rs6000_float_gprs) String(double) Value(2)
+
+EnumValue
+Enum(rs6000_float_gprs) String(no) Value(0)
+
 mlong-double-
-Target RejectNegative Joined UInteger
+Target RejectNegative Joined UInteger Var(rs6000_long_double_type_size) Save
 -mlong-double-<n>	Specify size of long double (64 or 128 bits)
 
 msched-costly-dep=
-Target RejectNegative Joined 
+Target RejectNegative Joined Var(rs6000_sched_costly_dep_str)
 Determine which dependences between insns are considered costly
 
 minsert-sched-nops=
-Target RejectNegative Joined
+Target RejectNegative Joined Var(rs6000_sched_insert_nops_str)
 Specify which post scheduling nop insertion scheme to apply
 
 malign-
-Target RejectNegative Joined
+Target RejectNegative Joined Enum(rs6000_alignment_flags) Var(rs6000_alignment_flags)
 Specify alignment of structure fields default/natural
 
+Enum
+Name(rs6000_alignment_flags) Type(unsigned char)
+Valid arguments to -malign-:
+
+EnumValue
+Enum(rs6000_alignment_flags) String(power) Value(MASK_ALIGN_POWER)
+
+EnumValue
+Enum(rs6000_alignment_flags) String(natural) Value(MASK_ALIGN_NATURAL)
+
 mprioritize-restricted-insns=
 Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) Save
 Specify scheduling priority for dispatch slot restricted insns
@@ -466,9 +492,27 @@  Target RejectNegative Var(rs6000_simple_
 Floating point unit does not support divide & sqrt
 
 mfpu=
-Target RejectNegative Joined 
+Target RejectNegative Joined Enum(fpu_type_t)
 -mfpu=	Specify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu)
 
+Enum
+Name(fpu_type_t) Type(enum fpu_type_t)
+
+EnumValue
+Enum(fpu_type_t) String(none) Value(FPU_NONE)
+
+EnumValue
+Enum(fpu_type_t) String(sp_lite) Value(FPU_SF_LITE)
+
+EnumValue
+Enum(fpu_type_t) String(dp_lite) Value(FPU_DF_LITE)
+
+EnumValue
+Enum(fpu_type_t) String(sp_full) Value(FPU_SF_FULL)
+
+EnumValue
+Enum(fpu_type_t) String(dp_full) Value(FPU_DF_FULL)
+
 mxilinx-fpu
 Target Var(rs6000_xilinx_fpu) Save
 Specify Xilinx FPU.
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(revision 173345)
+++ gcc/config/rs6000/linux64.h	(working copy)
@@ -93,7 +93,7 @@  extern int dot_symbols;
 #define	SUBSUBTARGET_OVERRIDE_OPTIONS				\
   do								\
     {								\
-      if (!rs6000_explicit_options.alignment)			\
+      if (!global_options_set.x_rs6000_alignment_flags)		\
 	rs6000_alignment_flags = MASK_ALIGN_NATURAL;		\
       if (TARGET_64BIT)						\
 	{							\
@@ -125,14 +125,14 @@  extern int dot_symbols;
 	    }							\
 	  if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0)	\
 	    {							\
-	      if (rs6000_explicit_options.cmodel		\
+	      if (global_options_set.x_rs6000_current_cmodel	\
 		  && rs6000_current_cmodel != CMODEL_SMALL)	\
 		error ("-mcmodel incompatible with other toc options"); \
 	      SET_CMODEL (CMODEL_SMALL);			\
 	    }							\
 	  else							\
 	    {							\
-	      if (!rs6000_explicit_options.cmodel)		\
+	      if (!global_options_set.x_rs6000_current_cmodel)	\
 		SET_CMODEL (CMODEL_MEDIUM);			\
 	      if (rs6000_current_cmodel != CMODEL_SMALL)	\
 		{						\
@@ -150,7 +150,7 @@  extern int dot_symbols;
 	      TARGET_PROFILE_KERNEL = 0;			\
 	      error (INVALID_32BIT, "profile-kernel");		\
 	    }							\
-	  if (rs6000_explicit_options.cmodel)			\
+	  if (global_options_set.x_rs6000_current_cmodel)	\
 	    {							\
 	      SET_CMODEL (CMODEL_SMALL);			\
 	      error (INVALID_32BIT, "cmodel");			\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 173345)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -148,16 +148,6 @@  struct rs6000_cpu_select rs6000_select[3
   { (const char *)0,	"-mtune=",		1,	0 },
 };
 
-/* String variables to hold the various options.  */
-static const char *rs6000_sched_insert_nops_str;
-static const char *rs6000_sched_costly_dep_str;
-static const char *rs6000_recip_name;
-
-#ifdef USING_ELFOS_H
-static const char *rs6000_abi_name;
-static const char *rs6000_sdata_name;
-#endif
-
 /* Support targetm.vectorize.builtin_mask_for_load.  */
 static GTY(()) tree altivec_builtin_mask_for_load;
 
@@ -227,20 +217,6 @@  static GTY(()) section *read_only_privat
 static GTY(()) section *sdata2_section;
 static GTY(()) section *toc_section;
 
-/* True for any options that were explicitly set.  */
-static struct {
-  bool aix_struct_ret;		/* True if -maix-struct-ret was used.  */
-  bool alignment;		/* True if -malign- was used.  */
-  bool spe_abi;			/* True if -mabi=spe/no-spe was used.  */
-  bool altivec_abi;		/* True if -mabi=altivec/no-altivec used.  */
-  bool spe;			/* True if -mspe= was used.  */
-  bool float_gprs;		/* True if -mfloat-gprs= was used.  */
-  bool long_double;	        /* True if -mlong-double- was used.  */
-  bool ieee;			/* True if -mabi=ieee/ibmlongdouble used.  */
-  bool vrsave;			/* True if -mvrsave was used.  */
-  bool cmodel;			/* True if -mcmodel was used.  */
-} rs6000_explicit_options;
-
 struct builtin_description
 {
   /* mask is not const because we're going to alter it below.  This
@@ -2678,6 +2654,17 @@  rs6000_option_override_internal (bool gl
     = ((global_init_p || target_option_default_node == NULL)
        ? NULL : TREE_TARGET_OPTION (target_option_default_node));
 
+  /* On 64-bit Darwin, power alignment is ABI-incompatible with some C
+     library functions, so warn about it. The flag may be useful for
+     performance studies from time to time though, so don't disable it
+     entirely.  */
+  if (global_options_set.x_rs6000_alignment_flags
+      && rs6000_alignment_flags == MASK_ALIGN_POWER
+      && DEFAULT_ABI == ABI_DARWIN
+      && TARGET_64BIT)
+    warning (0, "-malign-power is not supported for 64-bit Darwin;"
+	     " it is incompatible with the installed C and C++ libraries");
+
   /* Numerous experiment shows that IRA based loop pressure
      calculation works better for RTL loop invariant motion on targets
      with enough (>= 32) registers.  It is an expensive optimization.
@@ -2901,7 +2888,7 @@  rs6000_option_override_internal (bool gl
 	}
     }
 
-  if (!rs6000_explicit_options.long_double)
+  if (!global_options_set.x_rs6000_long_double_type_size)
     {
       if (main_target_opt != NULL
 	  && (main_target_opt->x_rs6000_long_double_type_size
@@ -2912,7 +2899,7 @@  rs6000_option_override_internal (bool gl
     }
 
 #ifndef POWERPC_LINUX
-  if (!rs6000_explicit_options.ieee)
+  if (!global_options_set.x_rs6000_ieeequad)
     rs6000_ieeequad = 1;
 #endif
 
@@ -2937,7 +2924,7 @@  rs6000_option_override_internal (bool gl
      be explicitly overridden in either case.  */
   if (TARGET_ELF)
     {
-      if (!rs6000_explicit_options.altivec_abi
+      if (!global_options_set.x_rs6000_altivec_abi
 	  && (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX))
 	{
 	  if (main_target_opt != NULL &&
@@ -2948,7 +2935,7 @@  rs6000_option_override_internal (bool gl
 	}
 
       /* Enable VRSAVE for AltiVec ABI, unless explicitly overridden.  */
-      if (!rs6000_explicit_options.vrsave)
+      if (!global_options_set.x_TARGET_ALTIVEC_VRSAVE)
 	TARGET_ALTIVEC_VRSAVE = rs6000_altivec_abi;
     }
 
@@ -3003,11 +2990,11 @@  rs6000_option_override_internal (bool gl
 	error ("target attribute or pragma changes SPE ABI");
       else
 	{
-	  if (!rs6000_explicit_options.spe_abi)
+	  if (!global_options_set.x_rs6000_spe_abi)
 	    rs6000_spe_abi = 0;
-	  if (!rs6000_explicit_options.spe)
+	  if (!global_options_set.x_rs6000_spe)
 	    rs6000_spe = 0;
-	  if (!rs6000_explicit_options.float_gprs)
+	  if (!global_options_set.x_rs6000_float_gprs)
 	    rs6000_float_gprs = 0;
 	}
       if (!(target_flags_explicit & MASK_ISEL))
@@ -3095,7 +3082,7 @@  rs6000_option_override_internal (bool gl
       /* Set aix_struct_return last, after the ABI is determined.
 	 If -maix-struct-return or -msvr4-struct-return was explicitly
 	 used, don't override with the ABI default.  */
-      if (!rs6000_explicit_options.aix_struct_ret)
+      if (!global_options_set.x_aix_struct_return)
 	aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
 
 #if 0
@@ -3848,19 +3835,6 @@  rs6000_option_default_params (void)
   set_default_param_value (PARAM_MAX_GROW_COPY_BB_INSNS, 16);
 }
 
-static enum fpu_type_t
-rs6000_parse_fpu_option (const char *option)
-{
-  if (!strcmp("none", option)) return FPU_NONE;
-  if (!strcmp("sp_lite", option)) return FPU_SF_LITE;
-  if (!strcmp("dp_lite", option)) return FPU_DF_LITE;
-  if (!strcmp("sp_full", option)) return FPU_SF_FULL;
-  if (!strcmp("dp_full", option)) return FPU_DF_FULL;
-  error("unknown value %s for -mfpu", option);
-  return FPU_NONE;
-}
-
-
 /* Handler for the Mathematical Acceleration Subsystem (mass) interface to a
    library with vectorized intrinsics.  */
 
@@ -4194,7 +4168,7 @@  rs6000_builtin_vectorized_function (tree
 static bool
 rs6000_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
 		      const struct cl_decoded_option *decoded,
-		      location_t loc ATTRIBUTE_UNUSED)
+		      location_t loc)
 {
   enum fpu_type_t fpu_type = FPU_NONE;
   char *p, *q;
@@ -4208,52 +4182,41 @@  rs6000_handle_option (struct gcc_options
   switch (code)
     {
     case OPT_mno_power:
-      target_flags &= ~(MASK_POWER | MASK_POWER2
-			| MASK_MULTIPLE | MASK_STRING);
-      target_flags_explicit |= (MASK_POWER | MASK_POWER2
+      opts->x_target_flags &= ~(MASK_POWER | MASK_POWER2
 				| MASK_MULTIPLE | MASK_STRING);
+      opts_set->x_target_flags |= (MASK_POWER | MASK_POWER2
+				   | MASK_MULTIPLE | MASK_STRING);
       break;
     case OPT_mno_powerpc:
-      target_flags &= ~(MASK_POWERPC | MASK_PPC_GPOPT
-			| MASK_PPC_GFXOPT | MASK_POWERPC64);
-      target_flags_explicit |= (MASK_POWERPC | MASK_PPC_GPOPT
+      opts->x_target_flags &= ~(MASK_POWERPC | MASK_PPC_GPOPT
 				| MASK_PPC_GFXOPT | MASK_POWERPC64);
+      opts_set->x_target_flags |= (MASK_POWERPC | MASK_PPC_GPOPT
+				   | MASK_PPC_GFXOPT | MASK_POWERPC64);
       break;
     case OPT_mfull_toc:
-      target_flags &= ~MASK_MINIMAL_TOC;
-      TARGET_NO_FP_IN_TOC = 0;
-      TARGET_NO_SUM_IN_TOC = 0;
-      target_flags_explicit |= MASK_MINIMAL_TOC;
+      opts->x_target_flags &= ~MASK_MINIMAL_TOC;
+      opts->x_TARGET_NO_FP_IN_TOC = 0;
+      opts->x_TARGET_NO_SUM_IN_TOC = 0;
+      opts_set->x_target_flags |= MASK_MINIMAL_TOC;
 #ifdef TARGET_USES_SYSV4_OPT
       /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be
 	 just the same as -mminimal-toc.  */
-      target_flags |= MASK_MINIMAL_TOC;
-      target_flags_explicit |= MASK_MINIMAL_TOC;
+      opts->x_target_flags |= MASK_MINIMAL_TOC;
+      opts_set->x_target_flags |= MASK_MINIMAL_TOC;
 #endif
       break;
 
 #ifdef TARGET_USES_SYSV4_OPT
     case OPT_mtoc:
       /* Make -mtoc behave like -mminimal-toc.  */
-      target_flags |= MASK_MINIMAL_TOC;
-      target_flags_explicit |= MASK_MINIMAL_TOC;
+      opts->x_target_flags |= MASK_MINIMAL_TOC;
+      opts_set->x_target_flags |= MASK_MINIMAL_TOC;
       break;
 #endif
 
 #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
     case OPT_mcmodel_:
-      if (strcmp (arg, "small") == 0)
-	rs6000_current_cmodel = CMODEL_SMALL;
-      else if (strcmp (arg, "medium") == 0)
-	rs6000_current_cmodel = CMODEL_MEDIUM;
-      else if (strcmp (arg, "large") == 0)
-	rs6000_current_cmodel = CMODEL_LARGE;
-      else
-	{
-	  error ("invalid option for -mcmodel: '%s'", arg);
-	  return false;
-	}
-      rs6000_explicit_options.cmodel = true;
+      /* Fall through.  */
 #endif
 
 #ifdef TARGET_USES_AIX64_OPT
@@ -4261,9 +4224,9 @@  rs6000_handle_option (struct gcc_options
 #else
     case OPT_m64:
 #endif
-      target_flags |= MASK_POWERPC64 | MASK_POWERPC;
-      target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
-      target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
+      opts->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
+      opts->x_target_flags |= ~opts_set->x_target_flags & MASK_PPC_GFXOPT;
+      opts_set->x_target_flags |= MASK_POWERPC64 | MASK_POWERPC;
       break;
 
 #ifdef TARGET_USES_AIX64_OPT
@@ -4271,35 +4234,33 @@  rs6000_handle_option (struct gcc_options
 #else
     case OPT_m32:
 #endif
-      target_flags &= ~MASK_POWERPC64;
-      target_flags_explicit |= MASK_POWERPC64;
-      break;
-
-    case OPT_minsert_sched_nops_:
-      rs6000_sched_insert_nops_str = arg;
+      opts->x_target_flags &= ~MASK_POWERPC64;
+      opts_set->x_target_flags |= MASK_POWERPC64;
       break;
 
     case OPT_mminimal_toc:
       if (value == 1)
 	{
-	  TARGET_NO_FP_IN_TOC = 0;
-	  TARGET_NO_SUM_IN_TOC = 0;
+	  opts->x_TARGET_NO_FP_IN_TOC = 0;
+	  opts->x_TARGET_NO_SUM_IN_TOC = 0;
 	}
       break;
 
     case OPT_mpower:
       if (value == 1)
 	{
-	  target_flags |= (MASK_MULTIPLE | MASK_STRING);
-	  target_flags_explicit |= (MASK_MULTIPLE | MASK_STRING);
+	  opts->x_target_flags |= (MASK_MULTIPLE | MASK_STRING);
+	  opts_set->x_target_flags |= (MASK_MULTIPLE | MASK_STRING);
 	}
       break;
 
     case OPT_mpower2:
       if (value == 1)
 	{
-	  target_flags |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
-	  target_flags_explicit |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
+	  opts->x_target_flags |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
+	  opts_set->x_target_flags |= (MASK_POWER
+				       | MASK_MULTIPLE
+				       | MASK_STRING);
 	}
       break;
 
@@ -4307,29 +4268,14 @@  rs6000_handle_option (struct gcc_options
     case OPT_mpowerpc_gfxopt:
       if (value == 1)
 	{
-	  target_flags |= MASK_POWERPC;
-	  target_flags_explicit |= MASK_POWERPC;
+	  opts->x_target_flags |= MASK_POWERPC;
+	  opts_set->x_target_flags |= MASK_POWERPC;
 	}
       break;
 
-    case OPT_maix_struct_return:
-    case OPT_msvr4_struct_return:
-      rs6000_explicit_options.aix_struct_ret = true;
-      break;
-
-    case OPT_mvrsave:
-      rs6000_explicit_options.vrsave = true;
-      TARGET_ALTIVEC_VRSAVE = value;
-      break;
-
-    case OPT_mspe:
-      rs6000_explicit_options.spe = true;
-      rs6000_spe = value;
-      break;
-
     case OPT_mdebug_:
       p = ASTRDUP (arg);
-      rs6000_debug = 0;
+      opts->x_rs6000_debug = 0;
 
       while ((q = strtok (p, ",")) != NULL)
 	{
@@ -4360,55 +4306,36 @@  rs6000_handle_option (struct gcc_options
 	  else if (! strcmp (q, "target"))
 	    mask = MASK_DEBUG_TARGET;
 	  else
-	    error ("unknown -mdebug-%s switch", q);
+	    error_at (loc, "unknown -mdebug-%s switch", q);
 
 	  if (invert)
-	    rs6000_debug &= ~mask;
+	    opts->x_rs6000_debug &= ~mask;
 	  else	
-	    rs6000_debug |= mask;
+	    opts->x_rs6000_debug |= mask;
 	}
       break;
 
 #ifdef TARGET_USES_SYSV4_OPT
-    case OPT_mcall_:
-      rs6000_abi_name = arg;
-      break;
-
-    case OPT_msdata_:
-      rs6000_sdata_name = arg;
-      break;
-
-    case OPT_mtls_size_:
-      if (strcmp (arg, "16") == 0)
-	rs6000_tls_size = 16;
-      else if (strcmp (arg, "32") == 0)
-	rs6000_tls_size = 32;
-      else if (strcmp (arg, "64") == 0)
-	rs6000_tls_size = 64;
-      else
-	error ("bad value %qs for -mtls-size switch", arg);
-      break;
-
     case OPT_mrelocatable:
       if (value == 1)
 	{
-	  target_flags |= MASK_MINIMAL_TOC;
-	  target_flags_explicit |= MASK_MINIMAL_TOC;
-	  TARGET_NO_FP_IN_TOC = 1;
+	  opts->x_target_flags |= MASK_MINIMAL_TOC;
+	  opts_set->x_target_flags |= MASK_MINIMAL_TOC;
+	  opts->x_TARGET_NO_FP_IN_TOC = 1;
 	}
       break;
 
     case OPT_mrelocatable_lib:
       if (value == 1)
 	{
-	  target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
-	  target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
-	  TARGET_NO_FP_IN_TOC = 1;
+	  opts->x_target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
+	  opts_set->x_target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
+	  opts->x_TARGET_NO_FP_IN_TOC = 1;
 	}
       else
 	{
-	  target_flags &= ~MASK_RELOCATABLE;
-	  target_flags_explicit |= MASK_RELOCATABLE;
+	  opts->x_target_flags &= ~MASK_RELOCATABLE;
+	  opts_set->x_target_flags |= MASK_RELOCATABLE;
 	}
       break;
 #endif
@@ -4416,204 +4343,147 @@  rs6000_handle_option (struct gcc_options
     case OPT_mabi_:
       if (!strcmp (arg, "altivec"))
 	{
-	  rs6000_explicit_options.altivec_abi = true;
-	  rs6000_altivec_abi = 1;
+	  opts_set->x_rs6000_altivec_abi = true;
+	  opts->x_rs6000_altivec_abi = 1;
 
 	  /* Enabling the AltiVec ABI turns off the SPE ABI.  */
-	  rs6000_spe_abi = 0;
+	  opts->x_rs6000_spe_abi = 0;
 	}
       else if (! strcmp (arg, "no-altivec"))
 	{
-	  rs6000_explicit_options.altivec_abi = true;
-	  rs6000_altivec_abi = 0;
+	  opts_set->x_rs6000_altivec_abi = true;
+	  opts->x_rs6000_altivec_abi = 0;
 	}
       else if (! strcmp (arg, "spe"))
 	{
-	  rs6000_explicit_options.spe_abi = true;
-	  rs6000_spe_abi = 1;
-	  rs6000_altivec_abi = 0;
+	  opts_set->x_rs6000_spe_abi = true;
+	  opts->x_rs6000_spe_abi = 1;
+	  opts->x_rs6000_altivec_abi = 0;
 	  if (!TARGET_SPE_ABI)
-	    error ("not configured for ABI: '%s'", arg);
+	    error_at (loc, "not configured for ABI: '%s'", arg);
 	}
       else if (! strcmp (arg, "no-spe"))
 	{
-	  rs6000_explicit_options.spe_abi = true;
-	  rs6000_spe_abi = 0;
+	  opts_set->x_rs6000_spe_abi = true;
+	  opts->x_rs6000_spe_abi = 0;
 	}
 
       /* These are here for testing during development only, do not
 	 document in the manual please.  */
       else if (! strcmp (arg, "d64"))
 	{
-	  rs6000_darwin64_abi = 1;
-	  warning (0, "using darwin64 ABI");
+	  opts->x_rs6000_darwin64_abi = 1;
+	  warning_at (loc, 0, "using darwin64 ABI");
 	}
       else if (! strcmp (arg, "d32"))
 	{
-	  rs6000_darwin64_abi = 0;
-	  warning (0, "using old darwin ABI");
+	  opts->x_rs6000_darwin64_abi = 0;
+	  warning_at (loc, 0, "using old darwin ABI");
 	}
 
       else if (! strcmp (arg, "ibmlongdouble"))
 	{
-	  rs6000_explicit_options.ieee = true;
-	  rs6000_ieeequad = 0;
-	  warning (0, "using IBM extended precision long double");
+	  opts_set->x_rs6000_ieeequad = true;
+	  opts->x_rs6000_ieeequad = 0;
+	  warning_at (loc, 0, "using IBM extended precision long double");
 	}
       else if (! strcmp (arg, "ieeelongdouble"))
 	{
-	  rs6000_explicit_options.ieee = true;
-	  rs6000_ieeequad = 1;
-	  warning (0, "using IEEE extended precision long double");
+	  opts_set->x_rs6000_ieeequad = true;
+	  opts->x_rs6000_ieeequad = 1;
+	  warning_at (loc, 0, "using IEEE extended precision long double");
 	}
 
       else
 	{
-	  error ("unknown ABI specified: '%s'", arg);
+	  error_at (loc, "unknown ABI specified: '%s'", arg);
 	  return false;
 	}
       break;
 
     case OPT_mcpu_:
       rs6000_select[1].string = arg;
-      rs6000_cpu_index = rs6000_cpu_name_lookup (arg);
-      if (rs6000_cpu_index < 0)
-	error ("bad value (%s) for -mcpu", arg);
+      opts->x_rs6000_cpu_index = rs6000_cpu_name_lookup (arg);
+      if (opts->x_rs6000_cpu_index < 0)
+	error_at (loc, "bad value (%s) for -mcpu", arg);
       break;
 
     case OPT_mtune_:
       rs6000_select[2].string = arg;
-      rs6000_tune_index = rs6000_cpu_name_lookup (arg);
-      if (rs6000_tune_index < 0)
-	error ("bad value (%s) for -mtune", arg);
-      break;
-
-    case OPT_mtraceback_:
-      if (! strncmp (arg, "full", 4))
-	rs6000_traceback = traceback_full;
-      else if (! strncmp (arg, "part", 4))
-	rs6000_traceback = traceback_part;
-      else if (! strncmp (arg, "no", 2))
-	rs6000_traceback = traceback_none;
-      else
-	error ("unknown -mtraceback arg %qs; expecting %<full%>, "
-	       "%<partial%> or %<none%>", arg);
-      break;
-
-    case OPT_mfloat_gprs_:
-      rs6000_explicit_options.float_gprs = true;
-      if (! strcmp (arg, "yes") || ! strcmp (arg, "single"))
-	rs6000_float_gprs = 1;
-      else if (! strcmp (arg, "double"))
-	rs6000_float_gprs = 2;
-      else if (! strcmp (arg, "no"))
-	rs6000_float_gprs = 0;
-      else
-	{
-	  error ("invalid option for -mfloat-gprs: '%s'", arg);
-	  return false;
-	}
+      opts->x_rs6000_tune_index = rs6000_cpu_name_lookup (arg);
+      if (opts->x_rs6000_tune_index < 0)
+	error_at (loc, "bad value (%s) for -mtune", arg);
       break;
 
     case OPT_mlong_double_:
-      rs6000_explicit_options.long_double = true;
-      rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
       if (value != 64 && value != 128)
 	{
-	  error ("unknown switch -mlong-double-%s", arg);
-	  rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
-	  return false;
-	}
-      else
-	rs6000_long_double_type_size = value;
-      break;
-
-    case OPT_msched_costly_dep_:
-      rs6000_sched_costly_dep_str = arg;
-      break;
-
-    case OPT_malign_:
-      rs6000_explicit_options.alignment = true;
-      if (! strcmp (arg, "power"))
-	{
-	  /* On 64-bit Darwin, power alignment is ABI-incompatible with
-	     some C library functions, so warn about it. The flag may be
-	     useful for performance studies from time to time though, so
-	     don't disable it entirely.  */
-	  if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
-	    warning (0, "-malign-power is not supported for 64-bit Darwin;"
-		     " it is incompatible with the installed C and C++ libraries");
-	  rs6000_alignment_flags = MASK_ALIGN_POWER;
-	}
-      else if (! strcmp (arg, "natural"))
-	rs6000_alignment_flags = MASK_ALIGN_NATURAL;
-      else
-	{
-	  error ("unknown -malign-XXXXX option specified: '%s'", arg);
+	  error_at (loc, "unknown switch -mlong-double-%s", arg);
+	  opts->x_rs6000_long_double_type_size
+	    = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
 	  return false;
 	}
       break;
 
     case OPT_msingle_float:
       if (!TARGET_SINGLE_FPU) 
-	warning (0, "-msingle-float option equivalent to -mhard-float");
+	warning_at (loc, 0,
+		    "-msingle-float option equivalent to -mhard-float");
       /* -msingle-float implies -mno-double-float and TARGET_HARD_FLOAT. */
-      rs6000_double_float = 0;
-      target_flags &= ~MASK_SOFT_FLOAT;
-      target_flags_explicit |= MASK_SOFT_FLOAT;
+      opts->x_rs6000_double_float = 0;
+      opts->x_target_flags &= ~MASK_SOFT_FLOAT;
+      opts_set->x_target_flags |= MASK_SOFT_FLOAT;
       break;
 
     case OPT_mdouble_float:
       /* -mdouble-float implies -msingle-float and TARGET_HARD_FLOAT. */
-      rs6000_single_float = 1;
-      target_flags &= ~MASK_SOFT_FLOAT;
-      target_flags_explicit |= MASK_SOFT_FLOAT;
+      opts->x_rs6000_single_float = 1;
+      opts->x_target_flags &= ~MASK_SOFT_FLOAT;
+      opts_set->x_target_flags |= MASK_SOFT_FLOAT;
       break;
 
     case OPT_msimple_fpu:
       if (!TARGET_SINGLE_FPU) 
-	warning (0, "-msimple-fpu option ignored");
+	warning_at (loc, 0, "-msimple-fpu option ignored");
       break;
 
     case OPT_mhard_float:
       /* -mhard_float implies -msingle-float and -mdouble-float. */
-      rs6000_single_float = rs6000_double_float = 1;
+      opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
       break;
 
     case OPT_msoft_float:
       /* -msoft_float implies -mnosingle-float and -mnodouble-float. */
-      rs6000_single_float = rs6000_double_float = 0;
+      opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
       break;
 
     case OPT_mfpu_:
-      fpu_type = rs6000_parse_fpu_option(arg);
-      if (fpu_type != FPU_NONE) 
-      /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on HARD_FLOAT. */
-      {
-        target_flags &= ~MASK_SOFT_FLOAT;
-        target_flags_explicit |= MASK_SOFT_FLOAT;
-        rs6000_xilinx_fpu = 1;
-        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL) 
-        rs6000_single_float = 1;
-        if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL) 
-          rs6000_single_float = rs6000_double_float = 1;
-        if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE) 
-          rs6000_simple_fpu = 1;
-      }
+      fpu_type = (enum fpu_type_t) value;
+      if (fpu_type != FPU_NONE)
+	{
+	  /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on
+	     HARD_FLOAT. */
+	  opts->x_target_flags &= ~MASK_SOFT_FLOAT;
+	  opts_set->x_target_flags |= MASK_SOFT_FLOAT;
+	  opts->x_rs6000_xilinx_fpu = 1;
+	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL) 
+	    opts->x_rs6000_single_float = 1;
+	  if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL) 
+	    opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
+	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE) 
+	    opts->x_rs6000_simple_fpu = 1;
+	}
       else
-      {
-        /* -mfpu=none is equivalent to -msoft-float */
-        target_flags |= MASK_SOFT_FLOAT;
-        target_flags_explicit |= MASK_SOFT_FLOAT;
-        rs6000_single_float = rs6000_double_float = 0;
-      }
+	{
+	  /* -mfpu=none is equivalent to -msoft-float.  */
+	  opts->x_target_flags |= MASK_SOFT_FLOAT;
+	  opts_set->x_target_flags |= MASK_SOFT_FLOAT;
+	  opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
+	}
+      /* Fall through.  */
 
     case OPT_mrecip:
-      rs6000_recip_name = (value) ? "default" : "none";
-      break;
-
-    case OPT_mrecip_:
-      rs6000_recip_name = arg;
+      opts->x_rs6000_recip_name = (value) ? "default" : "none";
       break;
     }
   return true;
Index: gcc/config/rs6000/aix52.h
===================================================================
--- gcc/config/rs6000/aix52.h	(revision 173345)
+++ gcc/config/rs6000/aix52.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Definitions of target machine for GNU compiler,
    for IBM RS/6000 POWER running AIX V5.2.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by David Edelsohn (edelsohn@gnu.org).
 
@@ -39,7 +39,7 @@  do {									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
       rs6000_long_double_type_size = 64;				\
-      if (rs6000_explicit_options.long_double)				\
+      if (global_options_set.x_rs6000_long_double_type_size)		\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
   if (TARGET_POWERPC64 && ! TARGET_64BIT)				\
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 173345)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -354,8 +354,6 @@  extern const char *host_detect_local_cpu
 #define PROCESSOR_DEFAULT   PROCESSOR_RIOS1
 #define PROCESSOR_DEFAULT64 PROCESSOR_RS64A
 
-extern enum fpu_type_t fpu_type;
-
 /* Specify the dialect of assembler to use.  New mnemonics is dialect one
    and the old mnemonics are dialect zero.  */
 #define ASSEMBLER_DIALECT (TARGET_NEW_MNEMONICS ? 1 : 0)
Index: gcc/config/rs6000/aix61.h
===================================================================
--- gcc/config/rs6000/aix61.h	(revision 173345)
+++ gcc/config/rs6000/aix61.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Definitions of target machine for GNU compiler,
    for IBM RS/6000 POWER running AIX V6.1.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by David Edelsohn (edelsohn@gnu.org).
 
@@ -39,7 +39,7 @@  do {									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
       rs6000_long_double_type_size = 64;				\
-      if (rs6000_explicit_options.long_double)				\
+      if (global_options_set.x_rs6000_long_double_type_size)		\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
   if (TARGET_POWERPC64 && ! TARGET_64BIT)				\
Index: gcc/config/rs6000/eabispe.h
===================================================================
--- gcc/config/rs6000/eabispe.h	(revision 173345)
+++ gcc/config/rs6000/eabispe.h	(working copy)
@@ -28,24 +28,14 @@ 
 #define SUBSUBTARGET_OVERRIDE_OPTIONS \
   if (rs6000_select[1].string == NULL) \
     rs6000_cpu = PROCESSOR_PPC8540; \
-  if (!rs6000_explicit_options.spe_abi) \
+  if (!global_options_set.x_rs6000_spe_abi) \
     rs6000_spe_abi = 1; \
-  if (!rs6000_explicit_options.float_gprs) \
+  if (!global_options_set.x_rs6000_float_gprs) \
     rs6000_float_gprs = 1; \
-  if (!rs6000_explicit_options.spe) \
+  if (!global_options_set.x_rs6000_spe) \
     rs6000_spe = 1; \
   if (target_flags & MASK_64BIT) \
     error ("-m64 not supported in this configuration")
 
-/* The e500 ABI says that either long doubles are 128 bits, or if
-   implemented in any other size, the compiler/linker should error out.
-   We have no emulation libraries for 128 bit long doubles, and I hate
-   the dozens of failures on the regression suite.  So I'm breaking ABI
-   specifications, until I properly fix the emulation.
-
-   Enable these later.
-#define RS6000_DEFAULT_LONG_DOUBLE_SIZE (TARGET_SPE ? 128 : 64)
-*/
-
 #undef  ASM_DEFAULT_SPEC
 #define	ASM_DEFAULT_SPEC "-mppc -mspe -me500"
Index: gcc/config/rs6000/e500-double.h
===================================================================
--- gcc/config/rs6000/e500-double.h	(revision 173345)
+++ gcc/config/rs6000/e500-double.h	(working copy)
@@ -1,5 +1,5 @@ 
 /* Target definitions for E500 with double precision FP.
-   Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2006, 2007, 2011 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez (aldyh@redhat.com).
 
    This file is part of GCC.
@@ -20,5 +20,5 @@ 
 
 #undef  SUB3TARGET_OVERRIDE_OPTIONS
 #define SUB3TARGET_OVERRIDE_OPTIONS \
-  if (!rs6000_explicit_options.float_gprs) \
+  if (!global_options_set.x_rs6000_float_gprs) \
     rs6000_float_gprs = 2;