1#  Copyright (C) 2003-2021 Free Software Foundation, Inc.
2#  Contributed by Kelley Cook, June 2004.
3#  Original code from Neil Booth, May 2003.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the
7# Free Software Foundation; either version 3, or (at your option) any
8# later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; see the file COPYING3.  If not see
17# <http://www.gnu.org/licenses/>.
18
19# This Awk script reads in the option records generated from
20# opt-gather.awk, combines the flags of duplicate options and generates a
21# C header file.
22#
23# This program uses functions from opt-functions.awk and code from
24# opt-read.awk.
25# Usage: awk -f opt-functions.awk -f opt-read.awk -f opth-gen.awk \
26#            < inputfile > options.h
27
28# Dump out an enumeration into a .h file.
29# Combine the flags of duplicate options.
30END {
31print "/* This file is auto-generated by opth-gen.awk.  */"
32print ""
33print "#ifndef OPTIONS_H"
34print "#define OPTIONS_H"
35print ""
36print "#include \"flag-types.h\""
37print ""
38
39if (n_extra_h_includes > 0) {
40	for (i = 0; i < n_extra_h_includes; i++) {
41		print "#include " quote extra_h_includes[i] quote
42	}
43	print ""
44}
45
46print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
47print "#ifndef GENERATOR_FILE"
48print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
49print "struct GTY(()) gcc_options"
50print "#else"
51print "struct gcc_options"
52print "#endif"
53print "{"
54print "#endif"
55
56for (i = 0; i < n_extra_vars; i++) {
57	var = extra_vars[i]
58	sub(" *=.*", "", var)
59	orig_var = var
60	name = var
61	type = var
62	type_after = var
63	sub("^.*[ *]", "", name)
64	sub("\\[.*\\]$", "", name)
65	sub("\\[.*\\]$", "", type)
66	sub(" *" name "$", "", type)
67	sub("^.*" name, "", type_after)
68	var_seen[name] = 1
69	print "#ifdef GENERATOR_FILE"
70	print "extern " orig_var ";"
71	print "#else"
72	print "  " type " x_" name type_after ";"
73	print "#define " name " global_options.x_" name
74	print "#endif"
75}
76
77for (i = 0; i < n_opts; i++) {
78	if (flag_set_p("Save", flags[i]))
79		have_save = 1;
80
81	name = var_name(flags[i]);
82	if (name == "")
83		continue;
84
85	if (name in var_seen)
86		continue;
87
88	var_seen[name] = 1;
89	print "#ifdef GENERATOR_FILE"
90	print "extern " var_type(flags[i]) name ";"
91	print "#else"
92	print "  " var_type(flags[i]) "x_" name ";"
93	print "#define " name " global_options.x_" name
94	print "#endif"
95}
96for (i = 0; i < n_opts; i++) {
97	name = static_var(opts[i], flags[i]);
98	if (name != "") {
99		print "#ifndef GENERATOR_FILE"
100		print "  " var_type(flags[i]) "x_" name ";"
101		print "#define x_" name " do_not_use"
102		print "#endif"
103	}
104}
105for (i = 0; i < n_opts; i++) {
106	if (flag_set_p("SetByCombined", flags[i])) {
107		print "#ifndef GENERATOR_FILE"
108		print "  bool frontend_set_" var_name(flags[i]) ";"
109		print "#endif"
110	}
111}
112print "#ifndef GENERATOR_FILE"
113print "};"
114print "extern struct gcc_options global_options;"
115print "extern const struct gcc_options global_options_init;"
116print "extern struct gcc_options global_options_set;"
117print "#define target_flags_explicit global_options_set.x_target_flags"
118print "#endif"
119print "#endif"
120print ""
121
122# All of the optimization switches gathered together so they can be saved and restored.
123# This will allow attribute((cold)) to turn on space optimization.
124
125# Change the type of normal switches from int to unsigned char to save space.
126# Also, order the structure so that pointer fields occur first, then int
127# fields, and then char fields to provide the best packing.
128
129print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
130print ""
131print "/* Structure to save/restore optimization and target specific options.  */";
132print "struct GTY(()) cl_optimization";
133print "{";
134
135n_opt_char = 4;
136n_opt_short = 0;
137n_opt_int = 0;
138n_opt_enum = 0;
139n_opt_other = 0;
140n_opt_explicit = 4;
141var_opt_char[0] = "unsigned char x_optimize";
142var_opt_char[1] = "unsigned char x_optimize_size";
143var_opt_char[2] = "unsigned char x_optimize_debug";
144var_opt_char[3] = "unsigned char x_optimize_fast";
145
146for (i = 0; i < n_opts; i++) {
147	if (flag_set_p("(Optimization|PerFunction)", flags[i])) {
148		name = var_name(flags[i])
149		if(name == "")
150			continue;
151
152		if(name in var_opt_seen)
153			continue;
154
155		var_opt_seen[name]++;
156		n_opt_explicit++;
157		otype = var_type_struct(flags[i]);
158		if (otype ~ "^((un)?signed +)?int *$")
159			var_opt_int[n_opt_int++] = otype "x_" name;
160
161		else if (otype ~ "^((un)?signed +)?short *$")
162			var_opt_short[n_opt_short++] = otype "x_" name;
163
164		else if (otype ~ "^((un)?signed +)?char *$")
165			var_opt_char[n_opt_char++] = otype "x_" name;
166
167		else if (otype ~ ("^enum +[_" alnum "]+ *$"))
168			var_opt_enum[n_opt_enum++] = otype "x_" name;
169
170		else
171			var_opt_other[n_opt_other++] = otype "x_" name;
172	}
173}
174
175for (i = 0; i < n_opt_other; i++) {
176	print "  " var_opt_other[i] ";";
177}
178
179for (i = 0; i < n_opt_int; i++) {
180	print "  " var_opt_int[i] ";";
181}
182
183for (i = 0; i < n_opt_enum; i++) {
184	print "  " var_opt_enum[i] ";";
185}
186
187for (i = 0; i < n_opt_short; i++) {
188	print "  " var_opt_short[i] ";";
189}
190
191for (i = 0; i < n_opt_char; i++) {
192	print "  " var_opt_char[i] ";";
193}
194
195print "  /* " n_opt_explicit " members */";
196print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_opt_explicit + 63) / 64) "];";
197
198print "};";
199print "";
200
201# Target and optimization save/restore/print functions.
202print "/* Structure to save/restore selected target specific options.  */";
203print "struct GTY(()) cl_target_option";
204print "{";
205
206n_target_char = 0;
207n_target_short = 0;
208n_target_int = 0;
209n_target_enum = 0;
210n_target_other = 0;
211n_target_explicit = n_extra_target_vars;
212n_target_explicit_mask = 0;
213
214for (i = 0; i < n_target_save; i++) {
215	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
216		var_target_int[n_target_int++] = target_save_decl[i];
217
218	else if (target_save_decl[i] ~ "^((un)?signed +)?short +[_" alnum "]+$")
219		var_target_short[n_target_short++] = target_save_decl[i];
220
221	else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$")
222		var_target_char[n_target_char++] = target_save_decl[i];
223
224	else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) {
225		var_target_enum[n_target_enum++] = target_save_decl[i];
226	}
227	else
228		var_target_other[n_target_other++] = target_save_decl[i];
229}
230
231if (have_save) {
232	for (i = 0; i < n_opts; i++) {
233		if (flag_set_p("Save", flags[i])) {
234			name = var_name(flags[i])
235			if(name == "")
236				name = "target_flags";
237
238			if(name in var_save_seen)
239				continue;
240
241			var_save_seen[name]++;
242			n_target_explicit++;
243			otype = var_type_struct(flags[i])
244
245			if (opt_args("Mask", flags[i]) != "" \
246			    || opt_args("InverseMask", flags[i]))
247				var_target_explicit_mask[n_target_explicit_mask++] \
248				    = otype "explicit_mask_" name;
249
250			if (otype ~ "^((un)?signed +)?int *$")
251				var_target_int[n_target_int++] = otype "x_" name;
252
253			else if (otype ~ "^((un)?signed +)?short *$")
254				var_target_short[n_target_short++] = otype "x_" name;
255
256			else if (otype ~ "^((un)?signed +)?char *$")
257				var_target_char[n_target_char++] = otype "x_" name;
258
259			else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+"))
260				var_target_enum[n_target_enum++] = otype "x_" name;
261
262			else
263				var_target_other[n_target_other++] = otype "x_" name;
264		}
265	}
266} else {
267	var_target_int[n_target_int++] = "int x_target_flags";
268	n_target_explicit++;
269	var_target_explicit_mask[n_target_explicit_mask++] \
270	    = "int explicit_mask_target_flags";
271}
272
273for (i = 0; i < n_target_other; i++) {
274	print "  " var_target_other[i] ";";
275}
276
277for (i = 0; i < n_target_enum; i++) {
278	print "  " var_target_enum[i] ";";
279}
280
281for (i = 0; i < n_target_int; i++) {
282	print "  " var_target_int[i] ";";
283}
284
285for (i = 0; i < n_target_short; i++) {
286	print "  " var_target_short[i] ";";
287}
288
289for (i = 0; i < n_target_char; i++) {
290	print "  " var_target_char[i] ";";
291}
292
293print "  /* " n_target_explicit - n_target_explicit_mask " members */";
294if (n_target_explicit > n_target_explicit_mask) {
295	print "  unsigned HOST_WIDE_INT explicit_mask[" \
296	  int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
297}
298
299for (i = 0; i < n_target_explicit_mask; i++) {
300	print "  " var_target_explicit_mask[i] ";";
301}
302
303print "};";
304print "";
305print "";
306print "/* Save optimization variables into a structure.  */"
307print "extern void cl_optimization_save (struct cl_optimization *, struct gcc_options *, struct gcc_options *);";
308print "";
309print "/* Restore optimization variables from a structure.  */";
310print "extern void cl_optimization_restore (struct gcc_options *, struct gcc_options *, struct cl_optimization *);";
311print "";
312print "/* Print optimization variables from a structure.  */";
313print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);";
314print "";
315print "/* Print different optimization variables from structures provided as arguments.  */";
316print "extern void cl_optimization_print_diff (FILE *, int, cl_optimization *ptr1, cl_optimization *ptr2);";
317print "";
318print "/* Save selected option variables into a structure.  */"
319print "extern void cl_target_option_save (struct cl_target_option *, struct gcc_options *, struct gcc_options *);";
320print "";
321print "/* Restore selected option variables from a structure.  */"
322print "extern void cl_target_option_restore (struct gcc_options *, struct gcc_options *, struct cl_target_option *);";
323print "";
324print "/* Print target option variables from a structure.  */";
325print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);";
326print "";
327print "/* Print different target option variables from structures provided as arguments.  */";
328print "extern void cl_target_option_print_diff (FILE *, int, cl_target_option *ptr1, cl_target_option *ptr2);";
329print "";
330print "/* Compare two target option variables from a structure.  */";
331print "extern bool cl_target_option_eq (const struct cl_target_option *, const struct cl_target_option *);";
332print "";
333print "/* Free heap memory used by target option variables.  */";
334print "extern void cl_target_option_free (struct cl_target_option *);";
335print "";
336print "/* Hash option variables from a structure.  */";
337print "extern hashval_t cl_target_option_hash (const struct cl_target_option *);";
338print "";
339print "/* Hash optimization from a structure.  */";
340print "extern hashval_t cl_optimization_hash (const struct cl_optimization *);";
341print "";
342print "/* Compare two optimization options.  */";
343print "extern bool cl_optimization_option_eq (cl_optimization const *ptr1, cl_optimization const *ptr2);"
344print "";
345print "/* Free heap memory used by optimization options.  */";
346print "extern void cl_optimization_option_free (cl_optimization *ptr1);"
347print "";
348print "/* Compare and report difference for a part of cl_optimization options.  */";
349print "extern void cl_optimization_compare (gcc_options *ptr1, gcc_options *ptr2);";
350print "";
351print "/* Generator files may not have access to location_t, and don't need these.  */"
352print "#if defined(UNKNOWN_LOCATION)"
353print "bool                                                                  "
354print "common_handle_option_auto (struct gcc_options *opts,                  "
355print "                           struct gcc_options *opts_set,              "
356print "                           const struct cl_decoded_option *decoded,   "
357print "                           unsigned int lang_mask, int kind,          "
358print "                           location_t loc,                            "
359print "                           const struct cl_option_handlers *handlers, "
360print "                           diagnostic_context *dc);                   "
361for (i = 0; i < n_langs; i++) {
362    lang_name = lang_sanitized_name(langs[i]);
363    print "bool"
364    print lang_name "_handle_option_auto (struct gcc_options *opts,"
365    print "                           struct gcc_options *opts_set,"
366    print "                           size_t scode, const char *arg,"
367    print "                           HOST_WIDE_INT value,"
368    print "                           unsigned int lang_mask, int kind,"
369    print "                           location_t loc,"
370    print "                           const struct cl_option_handlers *handlers,"
371    print "                           diagnostic_context *dc);"
372}
373print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
374print "                             struct cpp_options * cpp_opts);"
375print "void init_global_opts_from_cpp(struct gcc_options * opts,      "
376print "                               const struct cpp_options * cpp_opts);"
377print "#endif";
378print "#endif";
379print "";
380
381for (i = 0; i < n_opts; i++) {
382	name = opt_args("Mask", flags[i])
383	if (name == "") {
384		opt = opt_args("InverseMask", flags[i])
385		if (opt ~ ",")
386			name = nth_arg(0, opt)
387		else
388			name = opt
389	}
390	if (name != "" && mask_bits[name] == 0) {
391		mask_bits[name] = 1
392		vname = var_name(flags[i])
393		mask = "MASK_"
394		mask_1 = "1U"
395		if (vname != "") {
396			mask = "OPTION_MASK_"
397			if (host_wide_int[vname] == "yes")
398				mask_1 = "HOST_WIDE_INT_1U"
399		} else
400			extra_mask_bits[name] = 1
401		print "#define " mask name " (" mask_1 " << " masknum[vname]++ ")"
402	}
403}
404for (i = 0; i < n_extra_masks; i++) {
405	if (extra_mask_bits[extra_masks[i]] == 0)
406		print "#define MASK_" extra_masks[i] " (1U << " masknum[""]++ ")"
407}
408
409for (var in masknum) {
410	if (var != "" && host_wide_int[var] == "yes") {
411		print "#if defined(HOST_BITS_PER_WIDE_INT) && " masknum[var] " > HOST_BITS_PER_WIDE_INT"
412		print "#error too many masks for " var
413		print "#endif"
414	}
415	else if (masknum[var] > 32) {
416		if (var == "")
417			print "#error too many target masks"
418		else
419			print "#error too many masks for " var
420	}
421}
422print ""
423
424for (i = 0; i < n_opts; i++) {
425	name = opt_args("Mask", flags[i])
426	if (name == "") {
427		opt = opt_args("InverseMask", flags[i])
428		if (opt ~ ",")
429			name = nth_arg(0, opt)
430		else
431			name = opt
432	}
433	if (name != "" && mask_macros[name] == 0) {
434		mask_macros[name] = 1
435		vname = var_name(flags[i])
436		mask = "OPTION_MASK_"
437		if (vname == "") {
438			vname = "target_flags"
439			mask = "MASK_"
440			extra_mask_macros[name] = 1
441		}
442		print "#define TARGET_" name \
443		      " ((" vname " & " mask name ") != 0)"
444		print "#define TARGET_" name "_P(" vname ")" \
445		      " (((" vname ") & " mask name ") != 0)"
446	}
447}
448for (i = 0; i < n_extra_masks; i++) {
449	if (extra_mask_macros[extra_masks[i]] == 0)
450		print "#define TARGET_" extra_masks[i] \
451		      " ((target_flags & MASK_" extra_masks[i] ") != 0)"
452}
453print ""
454
455for (i = 0; i < n_opts; i++) {
456	opt = opt_args("InverseMask", flags[i])
457	if (opt ~ ",") {
458		vname = var_name(flags[i])
459		mask = "OPTION_MASK_"
460		if (vname == "") {
461			vname = "target_flags"
462			mask = "MASK_"
463		}
464		print "#define TARGET_" nth_arg(1, opt) \
465		      " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
466	}
467}
468print ""
469
470for (i = 0; i < n_langs; i++) {
471        macros[i] = "CL_" lang_sanitized_name(langs[i])
472	s = substr("            ", length (macros[i]))
473	print "#define " macros[i] s " (1U << " i ")"
474    }
475print "#define CL_LANG_ALL   ((1U << " n_langs ") - 1)"
476
477print ""
478print "enum opt_code"
479print "{"
480
481for (i = 0; i < n_opts; i++)
482	back_chain[i] = "N_OPTS";
483
484enum_value = 0
485for (i = 0; i < n_opts; i++) {
486	# Combine the flags of identical switches.  Switches
487	# appear many times if they are handled by many front
488	# ends, for example.
489	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
490		flags[i + 1] = flags[i] " " flags[i + 1];
491		i++;
492	}
493
494	len = length (opts[i]);
495	enum = opt_enum(opts[i])
496	enum_string = enum " = " enum_value ","
497
498	# Aliases do not get enumeration names.
499	if ((flag_set_p("Alias.*", flags[i]) \
500	     && !flag_set_p("SeparateAlias", flags[i])) \
501	    || flag_set_p("Ignore", flags[i])) {
502		enum_string = "/* " enum_string " */"
503	}
504
505	# If this switch takes joined arguments, back-chain all
506	# subsequent switches to it for which it is a prefix.  If
507	# a later switch S is a longer prefix of a switch T, T
508	# will be back-chained to S in a later iteration of this
509	# for() loop, which is what we want.
510	if (flag_set_p("Joined.*", flags[i])) {
511		for (j = i + 1; j < n_opts; j++) {
512			if (substr (opts[j], 1, len) != opts[i])
513				break;
514			back_chain[j] = enum;
515		}
516	}
517
518	s = substr("                                          ",
519		   length (enum_string))
520
521	if (help[i] == "")
522		hlp = "0"
523	else
524		hlp = "N_(\"" help[i] "\")";
525
526	print "  " enum_string s "/* -" opts[i] " */"
527	enum_value++
528}
529
530print "  N_OPTS,"
531print "  OPT_SPECIAL_unknown,"
532print "  OPT_SPECIAL_ignore,"
533print "  OPT_SPECIAL_warn_removed,"
534print "  OPT_SPECIAL_program_name,"
535print "  OPT_SPECIAL_input_file"
536print "};"
537print ""
538print "#ifdef GCC_C_COMMON_C"
539print "/* Mapping from cpp message reasons to the options that enable them.  */"
540print "#include <cpplib.h>"
541print "struct cpp_reason_option_codes_t"
542print "{"
543print "  /* cpplib message reason.  */"
544print "  const enum cpp_warning_reason reason;"
545print "  /* gcc option that controls this message.  */"
546print "  const int option_code;"
547print "};"
548print ""
549print "static const struct cpp_reason_option_codes_t cpp_reason_option_codes[] = {"
550for (i = 0; i < n_opts; i++) {
551    # With identical flags, pick only the last one.  The
552    # earlier loop ensured that it has all flags merged,
553    # and a nonempty help text if one of the texts was nonempty.
554    while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
555        i++;
556    }
557    cpp_reason = nth_arg(0, opt_args("CppReason", flags[i]));
558    if (cpp_reason != "") {
559        cpp_reason = cpp_reason ",";
560        printf("  {%-40s %s},\n", cpp_reason, opt_enum(opts[i]))
561    }
562}
563printf("  {%-40s 0},\n", "CPP_W_NONE,")
564print "};"
565print "#endif"
566print ""
567print "#endif /* OPTIONS_H */"
568}
569