Index: gcc/doc/options.texi
===================================================================
--- gcc/doc/options.texi	(revision 166875)
+++ gcc/doc/options.texi	(working copy)
@@ -52,6 +52,32 @@ for variables set in option handlers rat
 @code{Var} properties.
 
 @item
+A variable record to define a variable used to store option
+information.  These records have two fields: the string
+@samp{TargetVariable}, and a declaration of the type and name of the
+variable, optionally with an initializer (but without any trailing
+@samp{;}).  @samp{TargetVariable} is a combination of @samp{Variable}
+and @samp{TargetSave} records in that the variable is defined in the
+@code{gcc_options} structure, but these variables are also stored in
+the @code{cl_target_option} structure.  The variables are saved in the
+target save code and restored in the target restore code.
+
+@item
+A variable record to record any additional files that the
+@file{options.h} file should include.  This is useful to provide
+enumeration or structure definitions needed for target variables.
+These records have two fields: the string @samp{HeaderInclude} and the
+name of the include file.
+
+@item
+A variable record to record any additional files that the
+@file{options.c} file should include.  This is useful to provide
+inline functions needed for target variables and/or @code{#ifdef}
+sequences to properly set up the initialization.  These records have
+two fields: the string @samp{SourceInclude} and the name of the
+include file.
+
+@item
 An option definition record.  These records have the following fields:
 @enumerate
 @item
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 166875)
+++ gcc/configure.ac	(working copy)
@@ -1382,8 +1382,10 @@ fi
 
 # Convert extra_options into a form suitable for Makefile use.
 extra_opt_files=
+all_opt_files=
 for f in $extra_options; do
   extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+  all_opt_files="$all_opt_files $srcdir/config/$f"
 done
 AC_SUBST(extra_opt_files)
 
@@ -4458,6 +4460,7 @@ changequote([,])dnl
 	all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
 	if test -f $srcdir/$gcc_subdir/lang.opt; then
 	    lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
 	fi
 	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
 	    lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -4508,6 +4511,14 @@ do
 done
 
 # --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+AC_SUBST_FILE(option_includes)
+
+# --------
 # UNSORTED
 # --------
 
@@ -4769,3 +4780,4 @@ done
 ], 
 [subdirs='$subdirs'])
 AC_OUTPUT
+
Index: gcc/configure
===================================================================
--- gcc/configure	(revision 166875)
+++ gcc/configure	(working copy)
@@ -849,7 +849,8 @@ PACKAGE_TARNAME
 PACKAGE_NAME
 PATH_SEPARATOR
 SHELL'
-ac_subst_files='language_hooks'
+ac_subst_files='option_includes
+language_hooks'
 ac_user_opts='
 enable_option_checking
 with_build_libsubdir
@@ -10638,8 +10639,10 @@ fi
 
 # Convert extra_options into a form suitable for Makefile use.
 extra_opt_files=
+all_opt_files=
 for f in $extra_options; do
   extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+  all_opt_files="$all_opt_files $srcdir/config/$f"
 done
 
 
@@ -17283,7 +17286,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17286 "configure"
+#line 17289 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17389,7 +17392,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17392 "configure"
+#line 17395 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25672,6 +25675,7 @@ do
 	all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
 	if test -f $srcdir/$gcc_subdir/lang.opt; then
 	    lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
 	fi
 	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
 	    lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
@@ -25724,6 +25728,14 @@ do
 done
 
 # --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+
+
+# --------
 # UNSORTED
 # --------
 
@@ -27389,3 +27401,4 @@ if test -n "$ac_unrecognized_opts" && te
 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
 fi
 
+
Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(revision 166875)
+++ gcc/optc-gen.awk	(working copy)
@@ -31,7 +31,10 @@ BEGIN {
 	n_langs = 0
 	n_target_save = 0
 	n_extra_vars = 0
-        quote = "\042"
+	n_extra_target_vars = 0
+	n_extra_c_includes = 0
+	n_extra_h_includes = 0
+	quote = "\042"
 	comma = ","
 	FS=SUBSEP
 	# Default the name of header created from opth-gen.awk to options.h
@@ -53,6 +56,30 @@ BEGIN {
 			extra_vars[n_extra_vars] = $2
 			n_extra_vars++
 		}
+		else if ($1 == "TargetVariable") {
+			# Combination of TargetSave and Variable
+			extra_vars[n_extra_vars] = $2
+			n_extra_vars++
+
+			var = $2
+			sub(" *=.*", "", var)
+			orig_var = var
+			name = var
+			type = var
+			sub("^.*[ *]", "", name)
+			sub(" *" name "$", "", type)
+			target_save_decl[n_target_save] = type " x_" name
+			n_target_save++
+
+			extra_target_vars[n_extra_target_vars] = name
+			n_extra_target_vars++;
+		}
+		else if ($1 == "HeaderInclude") {
+			extra_h_includes[n_extra_h_includes++] = $2;
+		}
+		else if ($1 == "SourceInclude")  {
+			extra_c_includes[n_extra_c_includes++] = $2;
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
@@ -82,7 +109,17 @@ print "#include " quote "target.h" quote
 print "#endif /* GCC_DRIVER */"
 print ""
 
+if (n_extra_c_includes > 0) {
+	for (i = 0; i < n_extra_c_includes; i++) {
+		print "#include " quote extra_c_includes[i] quote
+	}
+	print ""
+}
+
 have_save = 0;
+if (n_extra_target_vars)
+	have_save = 1
+
 print "const struct gcc_options global_options_init =\n{"
 for (i = 0; i < n_extra_vars; i++) {
 	var = extra_vars[i]
@@ -304,11 +341,13 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 1;
 n_opt_other = 0;
 var_opt_char[0] = "optimize";
 var_opt_char[1] = "optimize_size";
 var_opt_range["optimize"] = "0, 255";
 var_opt_range["optimize_size"] = "0, 255";
+var_opt_enum[0] = "flag_fp_contract_mode";
 
 # Sort by size to mimic how the structure is laid out to be friendlier to the
 # cache.
@@ -330,6 +369,9 @@ for (i = 0; i < n_opts; i++) {
 		else if (otype ~ "^((un)?signed +)?short *$")
 			var_opt_short[n_opt_short++] = name;
 
+		else if (otype ~ ("^enum +[_" alnum "]+ *"))
+			var_opt_enum[n_opt_enum++] = name;
+
 		else if (otype ~ "^((un)?signed +)?char *$") {
 			var_opt_char[n_opt_char++] = name;
 			if (otype ~ "^unsigned +char *$")
@@ -357,6 +399,10 @@ for (i = 0; i < n_opt_int; i++) {
 	print "  ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  ptr->x_" var_opt_enum[i] " = opts->x_" var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_short; i++) {
 	print "  ptr->x_" var_opt_short[i] " = opts->x_" var_opt_short[i] ";";
 }
@@ -381,6 +427,10 @@ for (i = 0; i < n_opt_int; i++) {
 	print "  opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  opts->x_" var_opt_enum[i] " = ptr->x_" var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_short; i++) {
 	print "  opts->x_" var_opt_short[i] " = ptr->x_" var_opt_short[i] ";";
 }
@@ -419,6 +469,14 @@ for (i = 0; i < n_opt_int; i++) {
 	print "";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  fprintf (file, \"%*s%s (%#x)\\n\",";
+	print "           indent_to, \"\",";
+	print "           \"" var_opt_enum[i] "\",";
+	print "           (int) ptr->x_" var_opt_enum[i] ");";
+	print "";
+}
+
 for (i = 0; i < n_opt_short; i++) {
 	print "  if (ptr->x_" var_opt_short[i] ")";
 	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
@@ -448,6 +506,7 @@ print "{";
 n_target_char = 0;
 n_target_short = 0;
 n_target_int = 0;
+n_target_enum = 0;
 n_target_other = 0;
 
 if (have_save) {
@@ -468,6 +527,9 @@ if (have_save) {
 			else if (otype ~ "^((un)?signed +)?short *$")
 				var_target_short[n_target_short++] = name;
 
+			else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+				var_target_enum[n_target_enum++] = name;
+
 			else if (otype ~ "^((un)?signed +)?char *$") {
 				var_target_char[n_target_char++] = name;
 				if (otype ~ "^unsigned +char *$")
@@ -499,10 +561,18 @@ print "  if (targetm.target_option.save)
 print "    targetm.target_option.save (ptr);";
 print "";
 
+for (i = 0; i < n_extra_target_vars; i++) {
+	print "  ptr->x_" extra_target_vars[i] " = opts->x_" extra_target_vars[i] ";";
+}
+
 for (i = 0; i < n_target_other; i++) {
 	print "  ptr->x_" var_target_other[i] " = opts->x_" var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  ptr->x_" var_target_enum[i] " = opts->x_" var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  ptr->x_" var_target_int[i] " = opts->x_" var_target_int[i] ";";
 }
@@ -523,10 +593,18 @@ print "void";
 print "cl_target_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)";
 print "{";
 
+for (i = 0; i < n_extra_target_vars; i++) {
+	print "  opts->x_" extra_target_vars[i] " = ptr->x_" extra_target_vars[i] ";";
+}
+
 for (i = 0; i < n_target_other; i++) {
 	print "  opts->x_" var_target_other[i] " = ptr->x_" var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  opts->x_" var_target_enum[i] " = ptr->x_" var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  opts->x_" var_target_int[i] " = ptr->x_" var_target_int[i] ";";
 }
@@ -565,6 +643,15 @@ for (i = 0; i < n_target_other; i++) {
 	print "";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  if (ptr->x_" var_target_enum[i] ")";
+	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
+	print "             indent, \"\",";
+	print "             \"" var_target_enum[i] "\",";
+	print "             ptr->x_" var_target_enum[i] ");";
+	print "";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  if (ptr->x_" var_target_int[i] ")";
 	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
Index: gcc/opth-gen.awk
===================================================================
--- gcc/opth-gen.awk	(revision 166875)
+++ gcc/opth-gen.awk	(working copy)
@@ -29,7 +29,12 @@ BEGIN {
 	n_langs = 0
 	n_target_save = 0
 	n_extra_vars = 0
+	n_extra_target_vars = 0
 	n_extra_masks = 0
+	n_extra_c_includes = 0
+	n_extra_h_includes = 0
+	have_save = 0;
+	quote = "\042"
 	FS=SUBSEP
 }
 
@@ -48,6 +53,30 @@ BEGIN {
 			extra_vars[n_extra_vars] = $2
 			n_extra_vars++
 		}
+		else if ($1 == "TargetVariable") {
+			# Combination of TargetSave and Variable
+			extra_vars[n_extra_vars] = $2
+			n_extra_vars++
+
+			var = $2
+			sub(" *=.*", "", var)
+			orig_var = var
+			name = var
+			type = var
+			sub("^.*[ *]", "", name)
+			sub(" *" name "$", "", type)
+			target_save_decl[n_target_save] = type " x_" name
+			n_target_save++
+
+			extra_target_vars[n_extra_target_vars] = name
+			n_extra_target_vars++
+		}
+		else if ($1 == "HeaderInclude") {
+			extra_h_includes[n_extra_h_includes++] = $2;
+		}
+		else if ($1 == "SourceInclude")  {
+			extra_c_includes[n_extra_c_includes++] = $2;
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
@@ -73,11 +102,21 @@ print ""
 print "#include \"flag-types.h\""
 print ""
 
-have_save = 0;
+if (n_extra_h_includes > 0) {
+	for (i = 0; i < n_extra_h_includes; i++) {
+		print "#include " quote extra_h_includes[i] quote
+	}
+	print ""
+}
 
 print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
 print "#ifndef GENERATOR_FILE"
-print "struct gcc_options\n{"
+print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
+print "struct GTY(()) gcc_options"
+print "#else"
+print "struct gcc_options"
+print "#endif"
+print "{"
 print "#endif"
 
 for (i = 0; i < n_extra_vars; i++) {
@@ -151,9 +190,11 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 1;
 n_opt_other = 0;
 var_opt_char[0] = "unsigned char x_optimize";
 var_opt_char[1] = "unsigned char x_optimize_size";
+var_opt_enum[0] = "enum fp_contract_mode x_flag_fp_contract_mode";
 
 for (i = 0; i < n_opts; i++) {
 	if (flag_set_p("Optimization", flags[i])) {
@@ -175,6 +216,9 @@ for (i = 0; i < n_opts; i++) {
 		else if (otype ~ "^((un)?signed +)?char *$")
 			var_opt_char[n_opt_char++] = otype "x_" name;
 
+		else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+			var_opt_enum[n_opt_enum++] = otype "x_" name;
+
 		else
 			var_opt_other[n_opt_other++] = otype "x_" name;
 	}
@@ -188,6 +232,10 @@ for (i = 0; i < n_opt_int; i++) {
 	print "  " var_opt_int[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  " var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_short; i++) {
 	print "  " var_opt_short[i] ";";
 }
@@ -207,6 +255,7 @@ print "{";
 n_target_char = 0;
 n_target_short = 0;
 n_target_int = 0;
+n_target_enum = 0;
 n_target_other = 0;
 
 for (i = 0; i < n_target_save; i++) {
@@ -219,6 +268,9 @@ for (i = 0; i < n_target_save; i++) {
 	else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$")
 		var_target_char[n_target_char++] = target_save_decl[i];
 
+	else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) {
+		var_target_enum[n_target_enum++] = target_save_decl[i];
+	}
 	else
 		var_target_other[n_target_other++] = target_save_decl[i];
 }
@@ -244,6 +296,9 @@ if (have_save) {
 			else if (otype ~ "^((un)?signed +)?char *$")
 				var_target_char[n_target_char++] = otype "x_" name;
 
+			else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+"))
+				var_target_enum[n_target_enum++] = otype "x_" name;
+
 			else
 				var_target_other[n_target_other++] = otype "x_" name;
 		}
@@ -256,6 +311,10 @@ for (i = 0; i < n_target_other; i++) {
 	print "  " var_target_other[i] ";";
 }
 
+for (i = 0; i < n_target_enum; i++) {
+	print "  " var_target_enum[i] ";";
+}
+
 for (i = 0; i < n_target_int; i++) {
 	print "  " var_target_int[i] ";";
 }
Index: gcc/opt-include.awk
===================================================================
--- gcc/opt-include.awk	(revision 0)
+++ gcc/opt-include.awk	(revision 0)
@@ -0,0 +1,30 @@
+#  Copyright (C) 2010
+#  Free Software Foundation, Inc.
+#  Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records and emits the include files
+# listed by the HeaderInclude directive.
+
+BEGIN {
+	h_next = 0
+	c_next = 0
+}
+
+(h_next != 0)	  { print "OPTIONS_H_EXTRA += $(srcdir)/" $1; h_next = 0 }
+(c_next != 0)	  { print "OPTIONS_C_EXTRA += $(srcdir)/" $1; c_next = 0 }
+/^HeaderInclude$/ { h_next = 1; c_next = 0 }
+/^SourceInclude$/ { h_next = 0; c_next = 1 }
