Index: gcc/doc/options.texi
===================================================================
--- gcc/doc/options.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ 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
===================================================================
--- gcc/configure	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/configure	(working copy)
@@ -853,7 +853,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
@@ -10498,8 +10499,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
 
 
@@ -17143,7 +17146,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17146 "configure"
+#line 17149 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17249,7 +17252,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17252 "configure"
+#line 17255 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25483,6 +25486,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"
@@ -25546,6 +25550,14 @@ do
 done
 
 # --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+
+
+# --------
 # UNSORTED
 # --------
 
@@ -27214,3 +27226,4 @@ if test -n "$ac_unrecognized_opts" && te
 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
 fi
 
+
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/configure.ac	(working copy)
@@ -1396,8 +1396,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)
 
@@ -4448,6 +4450,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"
@@ -4509,6 +4512,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
 # --------
 
@@ -4771,3 +4782,4 @@ done
 ], 
 [subdirs='$subdirs'])
 AC_OUTPUT
+
Index: gcc/opt-include.awk
===================================================================
--- gcc/opt-include.awk	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 0)
+++ gcc/opt-include.awk	(revision 166071)
@@ -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 }
Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ 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,6 +341,7 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 0;
 n_opt_other = 0;
 var_opt_char[0] = "optimize";
 var_opt_char[1] = "optimize_size";
@@ -330,6 +368,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 *$")
@@ -353,6 +394,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  ptr->x_" var_opt_other[i] " = opts->x_" var_opt_other[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_int; i++) {
 	print "  ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
 }
@@ -377,6 +422,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  opts->x_" var_opt_other[i] " = ptr->x_" var_opt_other[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_int; i++) {
 	print "  opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
 }
@@ -410,6 +459,15 @@ for (i = 0; i < n_opt_other; i++) {
 	print "";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  if (ptr->x_" var_opt_enum[i] ")";
+	print "    fprintf (file, \"%*s%s (%#x)\\n\",";
+	print "             indent_to, \"\",";
+	print "             \"" var_opt_enum[i] "\",";
+	print "             ptr->x_" var_opt_enum[i] ");";
+	print "";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  if (ptr->x_" var_opt_int[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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ 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,6 +190,7 @@ print "{";
 n_opt_char = 2;
 n_opt_short = 0;
 n_opt_int = 0;
+n_opt_enum = 0;
 n_opt_other = 0;
 var_opt_char[0] = "unsigned char x_optimize";
 var_opt_char[1] = "unsigned char x_optimize_size";
@@ -175,6 +215,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;
 	}
@@ -184,6 +227,10 @@ for (i = 0; i < n_opt_other; i++) {
 	print "  " var_opt_other[i] ";";
 }
 
+for (i = 0; i < n_opt_enum; i++) {
+	print "  " var_opt_enum[i] ";";
+}
+
 for (i = 0; i < n_opt_int; i++) {
 	print "  " var_opt_int[i] ";";
 }
@@ -207,6 +254,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 +267,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 +295,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 +310,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/Makefile.in
===================================================================
--- gcc/Makefile.in	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 166071)
+++ gcc/Makefile.in	(working copy)
@@ -812,6 +812,16 @@ T_TARGET : $(T_TARGET)
 # at build time.
 SPECS = specs
 
+# Extra include files that are defined by HeaderInclude directives in
+# the .opt files
+OPTIONS_H_EXTRA =
+
+# Extra include files that are defined by SourceInclude directives in
+# the .opt files
+OPTIONS_C_EXTRA =
+
+@option_includes@
+
 # End of variables for you to override.
 
 # GTM_H lists the config files that the generator files depend on,
@@ -899,7 +909,7 @@ RECOG_H = recog.h
 ALIAS_H = alias.h coretypes.h
 EMIT_RTL_H = emit-rtl.h
 FLAGS_H = flags.h coretypes.h flag-types.h $(OPTIONS_H)
-OPTIONS_H = options.h flag-types.h
+OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
 FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) vecprim.h $(TM_H)
 EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
 OPTABS_H = optabs.h insn-codes.h
@@ -2238,9 +2248,10 @@ s-options-h: optionlist $(srcdir)/opt-fu
 	$(STAMP) $@
 
 options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H) \
-	$(TM_H) opts.h intl.h
+	$(TM_H) opts.h intl.h $(OPTIONS_C_EXTRA)
 
-gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
+gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h \
+	$(OPTIONS_C_EXTRA)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) \
 		-DGCC_DRIVER options.c
 
@@ -2818,7 +2829,7 @@ opts.o : opts.c opts.h $(OPTIONS_H) $(TO
    output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
    $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
-opts-common.o : opts-common.c opts.h $(FLAGS_H) $(CONFIG_H) $(SYSTEM_H) \
+opts-common.o : opts-common.c opts.h $(FLAGS_H) $(OPTIONS_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h intl.h $(DIAGNOSTIC_H) $(TM_H)
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \
