1#  Copyright (C) 2003,2004,2005,2006,2007,2008, 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 header file.
23#
24# This program uses functions from opt-functions.awk
25# Usage: awk -f opt-functions.awk -f opth-gen.awk < inputfile > options.h
26
27BEGIN {
28	n_opts = 0
29	n_langs = 0
30	n_target_save = 0
31	n_extra_masks = 0
32	quote = "\042"
33	comma = ","
34	FS=SUBSEP
35}
36
37# Collect the text and flags of each option into an array
38	{
39		if ($1 == "Language") {
40			langs[n_langs] = $2
41			n_langs++;
42		}
43		else if ($1 == "TargetSave") {
44			# Make sure the declarations are put in source order
45			target_save_decl[n_target_save] = $2
46			n_target_save++
47		}
48		else {
49			name = opt_args("Mask", $1)
50			if (name == "") {
51				opts[n_opts]  = $1
52				flags[n_opts] = $2
53				help[n_opts]  = $3
54				n_opts++;
55			}
56			else {
57				extra_masks[n_extra_masks++] = name
58			}
59		}
60	}
61
62# Dump out an enumeration into a .h file.
63# Combine the flags of duplicate options.
64END {
65print "/* This file is auto-generated by opth-gen.awk.  */"
66print ""
67print "#ifndef OPTIONS_H"
68print "#define OPTIONS_H"
69print ""
70print "extern int target_flags;"
71print "extern int target_flags_explicit;"
72print ""
73
74have_save = 0;
75
76for (i = 0; i < n_opts; i++) {
77	if (flag_set_p("Save", flags[i]))
78		have_save = 1;
79
80	name = var_name(flags[i]);
81	if (name == "")
82		continue;
83
84	if (name in var_seen)
85		continue;
86
87	var_seen[name] = 1;
88	print "extern " var_type(flags[i]) name ";"
89}
90print ""
91
92# All of the optimization switches gathered together so they can be saved and restored.
93# This will allow attribute((cold)) to turn on space optimization.
94
95# Change the type of normal switches from int to unsigned char to save space.
96# Also, order the structure so that pointer fields occur first, then int
97# fields, and then char fields to provide the best packing.
98
99print "#if !defined(GCC_DRIVER) && !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
100print ""
101print "/* Structure to save/restore optimization and target specific options.  */";
102print "struct GTY(()) cl_optimization";
103print "{";
104
105n_opt_char = 2;
106n_opt_short = 0;
107n_opt_int = 0;
108n_opt_other = 0;
109var_opt_char[0] = "unsigned char optimize";
110var_opt_char[1] = "unsigned char optimize_size";
111
112for (i = 0; i < n_opts; i++) {
113	if (flag_set_p("Optimization", flags[i])) {
114		name = var_name(flags[i])
115		if(name == "")
116			continue;
117
118		if(name in var_opt_seen)
119			continue;
120
121		var_opt_seen[name]++;
122		otype = var_type_struct(flags[i]);
123		if (otype ~ "^((un)?signed +)?int *$")
124			var_opt_int[n_opt_int++] = otype name;
125
126		else if (otype ~ "^((un)?signed +)?short *$")
127			var_opt_short[n_opt_short++] = otype name;
128
129		else if (otype ~ "^((un)?signed +)?char *$")
130			var_opt_char[n_opt_char++] = otype name;
131
132		else
133			var_opt_other[n_opt_other++] = otype name;
134	}
135}
136
137for (i = 0; i < n_opt_other; i++) {
138	print "  " var_opt_other[i] ";";
139}
140
141for (i = 0; i < n_opt_int; i++) {
142	print "  " var_opt_int[i] ";";
143}
144
145for (i = 0; i < n_opt_short; i++) {
146	print "  " var_opt_short[i] ";";
147}
148
149for (i = 0; i < n_opt_char; i++) {
150	print "  " var_opt_char[i] ";";
151}
152
153print "};";
154print "";
155
156# Target and optimization save/restore/print functions.
157print "/* Structure to save/restore selected target specific options.  */";
158print "struct GTY(()) cl_target_option";
159print "{";
160
161n_target_char = 0;
162n_target_short = 0;
163n_target_int = 0;
164n_target_other = 0;
165
166for (i = 0; i < n_target_save; i++) {
167	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_a-zA-Z0-9]+$")
168		var_target_int[n_target_int++] = target_save_decl[i];
169
170	else if (target_save_decl[i] ~ "^((un)?signed +)?short +[_a-zA-Z0-9]+$")
171		var_target_short[n_target_short++] = target_save_decl[i];
172
173	else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_a-zA-Z0-9]+$")
174		var_target_char[n_target_char++] = target_save_decl[i];
175
176	else
177		var_target_other[n_target_other++] = target_save_decl[i];
178}
179
180if (have_save) {
181	for (i = 0; i < n_opts; i++) {
182		if (flag_set_p("Save", flags[i])) {
183			name = var_name(flags[i])
184			if(name == "")
185				name = "target_flags";
186
187			if(name in var_save_seen)
188				continue;
189
190			var_save_seen[name]++;
191			otype = var_type_struct(flags[i])
192			if (otype ~ "^((un)?signed +)?int *$")
193				var_target_int[n_target_int++] = otype name;
194
195			else if (otype ~ "^((un)?signed +)?short *$")
196				var_target_short[n_target_short++] = otype name;
197
198			else if (otype ~ "^((un)?signed +)?char *$")
199				var_target_char[n_target_char++] = otype name;
200
201			else
202				var_target_other[n_target_other++] = otype name;
203		}
204	}
205} else {
206	var_target_int[n_target_int++] = "int target_flags";
207}
208
209for (i = 0; i < n_target_other; i++) {
210	print "  " var_target_other[i] ";";
211}
212
213for (i = 0; i < n_target_int; i++) {
214	print "  " var_target_int[i] ";";
215}
216
217for (i = 0; i < n_target_short; i++) {
218	print "  " var_target_short[i] ";";
219}
220
221for (i = 0; i < n_target_char; i++) {
222	print "  " var_target_char[i] ";";
223}
224
225print "};";
226print "";
227print "";
228print "/* Save optimization variables into a structure.  */"
229print "extern void cl_optimization_save (struct cl_optimization *);";
230print "";
231print "/* Restore optimization variables from a structure.  */";
232print "extern void cl_optimization_restore (struct cl_optimization *);";
233print "";
234print "/* Print optimization variables from a structure.  */";
235print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);";
236print "";
237print "/* Save selected option variables into a structure.  */"
238print "extern void cl_target_option_save (struct cl_target_option *);";
239print "";
240print "/* Restore selected option variables from a structure.  */"
241print "extern void cl_target_option_restore (struct cl_target_option *);";
242print "";
243print "/* Print target option variables from a structure.  */";
244print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);";
245print "#endif";
246print "";
247
248for (i = 0; i < n_opts; i++) {
249	name = opt_args("Mask", flags[i])
250	vname = var_name(flags[i])
251	mask = "MASK_"
252	if (vname != "") {
253		mask = "OPTION_MASK_"
254	}
255	if (name != "" && !flag_set_p("MaskExists", flags[i]))
256		print "#define " mask name " (1 << " masknum[vname]++ ")"
257}
258for (i = 0; i < n_extra_masks; i++) {
259	print "#define MASK_" extra_masks[i] " (1 << " masknum[""]++ ")"
260}
261
262for (var in masknum) {
263	if (masknum[var] > 31) {
264		if (var == "")
265			print "#error too many target masks"
266		else
267			print "#error too many masks for " var
268	}
269}
270print ""
271
272for (i = 0; i < n_opts; i++) {
273	name = opt_args("Mask", flags[i])
274	vname = var_name(flags[i])
275	macro = "OPTION_"
276	mask = "OPTION_MASK_"
277	if (vname == "") {
278		vname = "target_flags"
279		macro = "TARGET_"
280		mask = "MASK_"
281	}
282	if (name != "" && !flag_set_p("MaskExists", flags[i]))
283		print "#define " macro name \
284		      " ((" vname " & " mask name ") != 0)"
285}
286for (i = 0; i < n_extra_masks; i++) {
287	print "#define TARGET_" extra_masks[i] \
288	      " ((target_flags & MASK_" extra_masks[i] ") != 0)"
289}
290print ""
291
292for (i = 0; i < n_opts; i++) {
293	opt = opt_args("InverseMask", flags[i])
294	if (opt ~ ",") {
295		vname = var_name(flags[i])
296		macro = "OPTION_"
297		mask = "OPTION_MASK_"
298		if (vname == "") {
299			vname = "target_flags"
300			macro = "TARGET_"
301			mask = "MASK_"
302		}
303		print "#define " macro nth_arg(1, opt) \
304		      " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
305	}
306}
307print ""
308
309for (i = 0; i < n_langs; i++) {
310	macros[i] = "CL_" langs[i]
311	gsub( "[^A-Za-z0-9_]", "X", macros[i] )
312	s = substr("            ", length (macros[i]))
313	print "#define " macros[i] s " (1 << " i ")"
314    }
315print "#define CL_LANG_ALL   ((1 << " n_langs ") - 1)"
316
317print ""
318print "enum opt_code"
319print "{"
320	
321for (i = 0; i < n_opts; i++)
322	back_chain[i] = "N_OPTS";
323
324for (i = 0; i < n_opts; i++) {
325	# Combine the flags of identical switches.  Switches
326	# appear many times if they are handled by many front
327	# ends, for example.
328	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
329		flags[i + 1] = flags[i] " " flags[i + 1];
330		i++;
331	}
332
333	len = length (opts[i]);
334	enum = "OPT_" opts[i]
335	if (opts[i] == "finline-limit=" || opts[i] == "Wlarger-than=" \
336	    || opts[i] == "ftemplate-depth=")
337		enum = enum "eq"
338	if (opts[i] == "gdwarf+")
339		enum = "OPT_gdwarfplus"
340	gsub ("[^A-Za-z0-9]", "_", enum)
341
342	# If this switch takes joined arguments, back-chain all
343	# subsequent switches to it for which it is a prefix.  If
344	# a later switch S is a longer prefix of a switch T, T
345	# will be back-chained to S in a later iteration of this
346	# for() loop, which is what we want.
347	if (flag_set_p("Joined.*", flags[i])) {
348		for (j = i + 1; j < n_opts; j++) {
349			if (substr (opts[j], 1, len) != opts[i])
350				break;
351			back_chain[j] = enum;
352		}
353	}
354
355	s = substr("                                         ", length (enum))
356	if (i + 1 == n_opts)
357		comma = ""
358
359	if (help[i] == "")
360		hlp = "0"
361	else
362		hlp = "N_(\"" help[i] "\")";
363
364	print "  " enum "," s "/* -" opts[i] " */"
365}
366
367print "  N_OPTS"
368print "};"
369print ""
370print "#endif /* OPTIONS_H */"
371}
372