xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/optc-gen.awk (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1#  Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
2#  Free Software Foundation, Inc.
3#  Contributed by Kelley Cook, June 2004.
4#  Original code from Neil Booth, May 2003.
5#
6# This program is free software; you can redistribute it and/or modify it
7# under the terms of the GNU General Public License as published by the
8# Free Software Foundation; either version 3, or (at your option) any
9# later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; see the file COPYING3.  If not see
18# <http://www.gnu.org/licenses/>.
19
20# This Awk script reads in the option records generated from
21# opt-gather.awk, combines the flags of duplicate options and generates a
22# C file.
23#
24# This program uses functions from opt-functions.awk
25#
26# Usage: awk -f opt-functions.awk -f optc-gen.awk \
27#            [-v header_name=header.h] < inputfile > options.c
28
29BEGIN {
30	n_opts = 0
31	n_langs = 0
32	n_target_save = 0
33        quote = "\042"
34	comma = ","
35	FS=SUBSEP
36	# Default the name of header created from opth-gen.awk to options.h
37	if (header_name == "") header_name="options.h"
38}
39
40# Collect the text and flags of each option into an array
41	{
42		if ($1 == "Language") {
43			langs[n_langs] = $2
44			n_langs++;
45		}
46		else if ($1 == "TargetSave") {
47			# Make sure the declarations are put in source order
48			target_save_decl[n_target_save] = $2
49			n_target_save++
50		}
51		else {
52			name = opt_args("Mask", $1)
53			if (name == "") {
54				opts[n_opts]  = $1
55				flags[n_opts] = $2
56				help[n_opts]  = $3
57				for (i = 4; i <= NF; i++)
58					help[n_opts] = help[n_opts] " " $i
59				n_opts++;
60			}
61		}
62	}
63
64# Dump that array of options into a C file.
65END {
66print "/* This file is auto-generated by optc-gen.awk.  */"
67print ""
68n_headers = split(header_name, headers, " ")
69for (i = 1; i <= n_headers; i++)
70	print "#include " quote headers[i] quote
71print "#include " quote "opts.h" quote
72print "#include " quote "intl.h" quote
73print ""
74print "#ifdef GCC_DRIVER"
75print "int target_flags;"
76print "#else"
77print "#include " quote "flags.h" quote
78print "#include " quote "target.h" quote
79print "#endif /* GCC_DRIVER */"
80print ""
81
82have_save = 0;
83for (i = 0; i < n_opts; i++) {
84	if (flag_set_p("Save", flags[i]))
85		have_save = 1;
86
87	name = var_name(flags[i]);
88	if (name == "")
89		continue;
90
91	if (flag_set_p("VarExists", flags[i])) {
92		# Need it for the gcc driver.
93		if (name in var_seen)
94			continue;
95		init = ""
96		gcc_driver = 1
97	}
98	else {
99		init = opt_args("Init", flags[i])
100		if (init != "")
101			init = " = " init;
102		else if (name in var_seen)
103			continue;
104		gcc_driver = 0
105	}
106
107	if (gcc_driver == 1)
108		print "#ifdef GCC_DRIVER"
109	print "/* Set by -" opts[i] "."
110	print "   " help[i] "  */"
111	print var_type(flags[i]) name init ";"
112	if (gcc_driver == 1)
113		print "#endif /* GCC_DRIVER */"
114	print ""
115
116	var_seen[name] = 1;
117}
118
119print ""
120print "/* Local state variables.  */"
121for (i = 0; i < n_opts; i++) {
122	name = static_var(opts[i], flags[i]);
123	if (name != "")
124		print "static " var_type(flags[i]) name ";"
125}
126print ""
127
128print "const char * const lang_names[] =\n{"
129for (i = 0; i < n_langs; i++) {
130	macros[i] = "CL_" langs[i]
131	gsub( "[^A-Za-z0-9_]", "X", macros[i] )
132	s = substr("         ", length (macros[i]))
133	print "  " quote langs[i] quote ","
134    }
135
136print "  0\n};\n"
137print "const unsigned int cl_options_count = N_OPTS;\n"
138print "const unsigned int cl_lang_count = " n_langs ";\n"
139
140print "const struct cl_option cl_options[] =\n{"
141
142j = 0
143for (i = 0; i < n_opts; i++) {
144	back_chain[i] = "N_OPTS";
145	indices[opts[i]] = j;
146	# Combine the flags of identical switches.  Switches
147	# appear many times if they are handled by many front
148	# ends, for example.
149	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
150		flags[i + 1] = flags[i] " " flags[i + 1];
151		if (help[i + 1] == "")
152			help[i + 1] = help[i]
153		else if (help[i] != "" && help[i + 1] != help[i])
154			print "warning: multiple different help strings for " \
155				opts[i] ":\n\t" help[i] "\n\t" help[i + 1] \
156				| "cat 1>&2"
157		i++;
158		back_chain[i] = "N_OPTS";
159		indices[opts[i]] = j;
160	}
161	j++;
162}
163
164for (i = 0; i < n_opts; i++) {
165	# With identical flags, pick only the last one.  The
166	# earlier loop ensured that it has all flags merged,
167	# and a nonempty help text if one of the texts was nonempty.
168	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
169		i++;
170	}
171
172	len = length (opts[i]);
173	enum = "OPT_" opts[i]
174	if (opts[i] == "finline-limit=" || opts[i] == "Wlarger-than=" \
175	    || opts[i] == "ftemplate-depth=")
176		enum = enum "eq"
177	gsub ("[^A-Za-z0-9]", "_", enum)
178
179	# If this switch takes joined arguments, back-chain all
180	# subsequent switches to it for which it is a prefix.  If
181	# a later switch S is a longer prefix of a switch T, T
182	# will be back-chained to S in a later iteration of this
183	# for() loop, which is what we want.
184	if (flag_set_p("Joined.*", flags[i])) {
185		for (j = i + 1; j < n_opts; j++) {
186			if (substr (opts[j], 1, len) != opts[i])
187				break;
188			back_chain[j] = enum;
189		}
190	}
191
192	s = substr("                                  ", length (opts[i]))
193	if (i + 1 == n_opts)
194		comma = ""
195
196	if (help[i] == "")
197		hlp = "0"
198	else
199		hlp = quote help[i] quote;
200
201	neg = opt_args("Negative", flags[i]);
202	if (neg != "")
203		idx = indices[neg]
204	else {
205		if (flag_set_p("RejectNegative", flags[i]))
206			idx = -1;
207		else {
208			if (opts[i] ~ "^[Wfm]")
209				idx = indices[opts[i]];
210			else
211				idx = -1;
212		}
213	}
214	# Split the printf after %u to work around an ia64-hp-hpux11.23
215	# awk bug.
216	printf("  { %c-%s%c,\n    %s,\n    %s, %u,",
217	       quote, opts[i], quote, hlp, back_chain[i], len)
218	printf(" %d,\n", idx)
219	condition = opt_args("Condition", flags[i])
220	cl_flags = switch_flags(flags[i])
221	if (condition != "")
222		printf("#if %s\n" \
223		       "    %s,\n" \
224		       "#else\n" \
225		       "    CL_DISABLED,\n" \
226		       "#endif\n",
227		       condition, cl_flags, cl_flags)
228	else
229		printf("    %s,\n", cl_flags)
230	printf("    %s, %s }%s\n", var_ref(opts[i], flags[i]),
231	       var_set(flags[i]), comma)
232}
233
234print "};"
235
236print "";
237print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
238print "";
239print "/* Save optimization variables into a structure.  */"
240print "void";
241print "cl_optimization_save (struct cl_optimization *ptr)";
242print "{";
243
244n_opt_char = 2;
245n_opt_short = 0;
246n_opt_int = 0;
247n_opt_other = 0;
248var_opt_char[0] = "optimize";
249var_opt_char[1] = "optimize_size";
250var_opt_range["optimize"] = "0, 255";
251var_opt_range["optimize_size"] = "0, 255";
252
253# Sort by size to mimic how the structure is laid out to be friendlier to the
254# cache.
255
256for (i = 0; i < n_opts; i++) {
257	if (flag_set_p("Optimization", flags[i])) {
258		name = var_name(flags[i])
259		if(name == "")
260			continue;
261
262		if(name in var_opt_seen)
263			continue;
264
265		var_opt_seen[name]++;
266		otype = var_type_struct(flags[i]);
267		if (otype ~ "^((un)?signed +)?int *$")
268			var_opt_int[n_opt_int++] = name;
269
270		else if (otype ~ "^((un)?signed +)?short *$")
271			var_opt_short[n_opt_short++] = name;
272
273		else if (otype ~ "^((un)?signed +)?char *$") {
274			var_opt_char[n_opt_char++] = name;
275			if (otype ~ "^unsigned +char *$")
276				var_opt_range[name] = "0, 255"
277			else if (otype ~ "^signed +char *$")
278				var_opt_range[name] = "-128, 127"
279		}
280		else
281			var_opt_other[n_opt_other++] = name;
282	}
283}
284
285for (i = 0; i < n_opt_char; i++) {
286	name = var_opt_char[i];
287	if (var_opt_range[name] != "")
288		print "  gcc_assert (IN_RANGE (" name ", " var_opt_range[name] "));";
289}
290
291print "";
292for (i = 0; i < n_opt_other; i++) {
293	print "  ptr->" var_opt_other[i] " = " var_opt_other[i] ";";
294}
295
296for (i = 0; i < n_opt_int; i++) {
297	print "  ptr->" var_opt_int[i] " = " var_opt_int[i] ";";
298}
299
300for (i = 0; i < n_opt_short; i++) {
301	print "  ptr->" var_opt_short[i] " = " var_opt_short[i] ";";
302}
303
304for (i = 0; i < n_opt_char; i++) {
305	print "  ptr->" var_opt_char[i] " = " var_opt_char[i] ";";
306}
307
308print "}";
309
310print "";
311print "/* Restore optimization options from a structure.  */";
312print "void";
313print "cl_optimization_restore (struct cl_optimization *ptr)";
314print "{";
315
316for (i = 0; i < n_opt_other; i++) {
317	print "  " var_opt_other[i] " = ptr->" var_opt_other[i] ";";
318}
319
320for (i = 0; i < n_opt_int; i++) {
321	print "  " var_opt_int[i] " = ptr->" var_opt_int[i] ";";
322}
323
324for (i = 0; i < n_opt_short; i++) {
325	print "  " var_opt_short[i] " = ptr->" var_opt_short[i] ";";
326}
327
328for (i = 0; i < n_opt_char; i++) {
329	print "  " var_opt_char[i] " = ptr->" var_opt_char[i] ";";
330}
331
332print "  targetm.override_options_after_change ();";
333print "}";
334
335print "";
336print "/* Print optimization options from a structure.  */";
337print "void";
338print "cl_optimization_print (FILE *file,";
339print "                       int indent_to,";
340print "                       struct cl_optimization *ptr)";
341print "{";
342
343print "  fputs (\"\\n\", file);";
344for (i = 0; i < n_opt_other; i++) {
345	print "  if (ptr->" var_opt_other[i] ")";
346	print "    fprintf (file, \"%*s%s (0x%lx)\\n\",";
347	print "             indent_to, \"\",";
348	print "             \"" var_opt_other[i] "\",";
349	print "             (unsigned long)ptr->" var_opt_other[i] ");";
350	print "";
351}
352
353for (i = 0; i < n_opt_int; i++) {
354	print "  if (ptr->" var_opt_int[i] ")";
355	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
356	print "             indent_to, \"\",";
357	print "             \"" var_opt_int[i] "\",";
358	print "             ptr->" var_opt_int[i] ");";
359	print "";
360}
361
362for (i = 0; i < n_opt_short; i++) {
363	print "  if (ptr->" var_opt_short[i] ")";
364	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
365	print "             indent_to, \"\",";
366	print "             \"" var_opt_short[i] "\",";
367	print "             ptr->" var_opt_short[i] ");";
368	print "";
369}
370
371for (i = 0; i < n_opt_char; i++) {
372	print "  if (ptr->" var_opt_char[i] ")";
373	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
374	print "             indent_to, \"\",";
375	print "             \"" var_opt_char[i] "\",";
376	print "             ptr->" var_opt_char[i] ");";
377	print "";
378}
379
380print "}";
381
382print "";
383print "/* Save selected option variables into a structure.  */"
384print "void";
385print "cl_target_option_save (struct cl_target_option *ptr)";
386print "{";
387
388n_target_char = 0;
389n_target_short = 0;
390n_target_int = 0;
391n_target_other = 0;
392
393if (have_save) {
394	for (i = 0; i < n_opts; i++) {
395		if (flag_set_p("Save", flags[i])) {
396			name = var_name(flags[i])
397			if(name == "")
398				name = "target_flags";
399
400			if(name in var_save_seen)
401				continue;
402
403			var_save_seen[name]++;
404			otype = var_type_struct(flags[i])
405			if (otype ~ "^((un)?signed +)?int *$")
406				var_target_int[n_target_int++] = name;
407
408			else if (otype ~ "^((un)?signed +)?short *$")
409				var_target_short[n_target_short++] = name;
410
411			else if (otype ~ "^((un)?signed +)?char *$") {
412				var_target_char[n_target_char++] = name;
413				if (otype ~ "^unsigned +char *$")
414					var_target_range[name] = "0, 255"
415				else if (otype ~ "^signed +char *$")
416					var_target_range[name] = "-128, 127"
417			}
418			else
419				var_target_other[n_target_other++] = name;
420		}
421	}
422} else {
423	var_target_int[n_target_int++] = "target_flags";
424}
425
426have_assert = 0;
427for (i = 0; i < n_target_char; i++) {
428	name = var_target_char[i];
429	if (var_target_range[name] != "") {
430		have_assert = 1;
431		print "  gcc_assert (IN_RANGE (" name ", " var_target_range[name] "));";
432	}
433}
434
435if (have_assert)
436	print "";
437
438print "  if (targetm.target_option.save)";
439print "    targetm.target_option.save (ptr);";
440print "";
441
442for (i = 0; i < n_target_other; i++) {
443	print "  ptr->" var_target_other[i] " = " var_target_other[i] ";";
444}
445
446for (i = 0; i < n_target_int; i++) {
447	print "  ptr->" var_target_int[i] " = " var_target_int[i] ";";
448}
449
450for (i = 0; i < n_target_short; i++) {
451	print "  ptr->" var_target_short[i] " = " var_target_short[i] ";";
452}
453
454for (i = 0; i < n_target_char; i++) {
455	print "  ptr->" var_target_char[i] " = " var_target_char[i] ";";
456}
457
458print "}";
459
460print "";
461print "/* Restore selected current options from a structure.  */";
462print "void";
463print "cl_target_option_restore (struct cl_target_option *ptr)";
464print "{";
465
466for (i = 0; i < n_target_other; i++) {
467	print "  " var_target_other[i] " = ptr->" var_target_other[i] ";";
468}
469
470for (i = 0; i < n_target_int; i++) {
471	print "  " var_target_int[i] " = ptr->" var_target_int[i] ";";
472}
473
474for (i = 0; i < n_target_short; i++) {
475	print "  " var_target_short[i] " = ptr->" var_target_short[i] ";";
476}
477
478for (i = 0; i < n_target_char; i++) {
479	print "  " var_target_char[i] " = ptr->" var_target_char[i] ";";
480}
481
482# This must occur after the normal variables in case the code depends on those
483# variables.
484print "";
485print "  if (targetm.target_option.restore)";
486print "    targetm.target_option.restore (ptr);";
487
488print "}";
489
490print "";
491print "/* Print optimization options from a structure.  */";
492print "void";
493print "cl_target_option_print (FILE *file,";
494print "                        int indent,";
495print "                        struct cl_target_option *ptr)";
496print "{";
497
498print "  fputs (\"\\n\", file);";
499for (i = 0; i < n_target_other; i++) {
500	print "  if (ptr->" var_target_other[i] ")";
501	print "    fprintf (file, \"%*s%s (0x%lx)\\n\",";
502	print "             indent, \"\",";
503	print "             \"" var_target_other[i] "\",";
504	print "             (unsigned long)ptr->" var_target_other[i] ");";
505	print "";
506}
507
508for (i = 0; i < n_target_int; i++) {
509	print "  if (ptr->" var_target_int[i] ")";
510	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
511	print "             indent, \"\",";
512	print "             \"" var_target_int[i] "\",";
513	print "             ptr->" var_target_int[i] ");";
514	print "";
515}
516
517for (i = 0; i < n_target_short; i++) {
518	print "  if (ptr->" var_target_short[i] ")";
519	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
520	print "             indent, \"\",";
521	print "             \"" var_target_short[i] "\",";
522	print "             ptr->" var_target_short[i] ");";
523	print "";
524}
525
526for (i = 0; i < n_target_char; i++) {
527	print "  if (ptr->" var_target_char[i] ")";
528	print "    fprintf (file, \"%*s%s (0x%x)\\n\",";
529	print "             indent, \"\",";
530	print "             \"" var_target_char[i] "\",";
531	print "             ptr->" var_target_char[i] ");";
532	print "";
533}
534
535print "";
536print "  if (targetm.target_option.print)";
537print "    targetm.target_option.print (file, indent, ptr);";
538
539print "}";
540print "#endif";
541
542}
543