1 /* params.c - Run-time parameters.
2    Copyright (C) 2001-2019 Free Software Foundation, Inc.
3    Written by Mark Mitchell <mark@codesourcery.com>.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "common/common-target.h"
25 #include "params.h"
26 #include "params-enum.h"
27 #include "diagnostic-core.h"
28 #include "diagnostic.h"
29 #include "spellcheck.h"
30 
31 /* An array containing the compiler parameters and their current
32    values.  */
33 
34 param_info *compiler_params;
35 
36 /* The number of entries in the table.  */
37 static size_t num_compiler_params;
38 
39 /* Whether the parameters have all been initialized and had their
40    default values determined.  */
41 static bool params_finished;
42 
43 #define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX)
44 #define DEFPARAMENUM5(ENUM, OPTION, HELP, DEFAULT, V0, V1, V2, V3, V4)	\
45   static const char *values_ ## ENUM [] = { #V0, #V1, #V2, #V3, #V4, NULL };
46 #include "params.def"
47 #undef DEFPARAMENUM5
48 #undef DEFPARAM
49 
50 static const param_info lang_independent_params[] = {
51 #define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX) \
52   { OPTION, DEFAULT, MIN, MAX, HELP, NULL },
53 #define DEFPARAMENUM5(ENUM, OPTION, HELP, DEFAULT,	     \
54 		      V0, V1, V2, V3, V4)		     \
55   { OPTION, (int)ENUM ## _KIND_ ## DEFAULT, 0, 4, HELP, values_ ## ENUM },
56 #include "params.def"
57 #undef DEFPARAM
58 #undef DEFPARAMENUM5
59   { NULL, 0, 0, 0, NULL, NULL }
60 };
61 
62 static bool
63 validate_param (const int value, const param_info param, const int index);
64 
65 
66 /* Add the N PARAMS to the current list of compiler parameters.  */
67 
68 void
add_params(const param_info params[],size_t n)69 add_params (const param_info params[], size_t n)
70 {
71   gcc_assert (!params_finished);
72 
73   /* Allocate enough space for the new parameters.  */
74   compiler_params = XRESIZEVEC (param_info, compiler_params,
75 				num_compiler_params + n);
76   param_info *dst_params = compiler_params + num_compiler_params;
77 
78   /* Copy them into the table.  */
79   memcpy (dst_params, params, n * sizeof (param_info));
80 
81   /* Keep track of how many parameters we have.  */
82   num_compiler_params += n;
83 
84   /* Initialize the pretty printing machinery in case we need to print an error,
85      but be sure not to initialize it if something else already has, e.g. a
86      language front-end like cc1.  */
87   if (!diagnostic_ready_p ())
88     diagnostic_initialize (global_dc, 0);
89 
90   /* Now perform some validation and validation failures trigger an error so
91      initialization will stop.  */
92   for (size_t i = num_compiler_params - n; i < n; i++)
93     validate_param (params[i].default_value, params[i], (int)i);
94 }
95 
96 /* Add all parameters and default values that can be set in both the
97    driver and the compiler proper.  */
98 
99 void
global_init_params(void)100 global_init_params (void)
101 {
102   gcc_assert (!params_finished);
103 
104   add_params (lang_independent_params, LAST_PARAM);
105   targetm_common.option_default_params ();
106 }
107 
108 /* Note that all parameters have been added and all default values
109    set.  */
110 
111 void
finish_params(void)112 finish_params (void)
113 {
114   params_finished = true;
115 }
116 
117 /* Reset all state within params.c so that we can rerun the compiler
118    within the same process.  For use by toplev::finalize.  */
119 
120 void
params_c_finalize(void)121 params_c_finalize (void)
122 {
123   XDELETEVEC (compiler_params);
124   compiler_params = NULL;
125   num_compiler_params = 0;
126   params_finished = false;
127 }
128 
129 /* Set the value of the parameter given by NUM to VALUE in PARAMS and
130    PARAMS_SET.  If EXPLICIT_P, this is being set by the user;
131    otherwise it is being set implicitly by the compiler.  */
132 
133 static void
set_param_value_internal(compiler_param num,int value,int * params,int * params_set,bool explicit_p)134 set_param_value_internal (compiler_param num, int value,
135 			  int *params, int *params_set,
136 			  bool explicit_p)
137 {
138   size_t i = (size_t) num;
139 
140   gcc_assert (params_finished);
141 
142   params[i] = value;
143   if (explicit_p)
144     params_set[i] = true;
145 }
146 
147 /* Validate PARAM and write an error if invalid.  */
148 
149 static bool
validate_param(const int value,const param_info param,const int index)150 validate_param (const int value, const param_info param, const int index)
151 {
152   /* These paremeters interpret bounds of 0 to be unbounded, as such don't
153      perform any range validation on 0 parameters.  */
154   if (value < param.min_value && param.min_value != 0)
155     {
156       error ("minimum value of parameter %qs is %u",
157 	     param.option, param.min_value);
158       return false;
159     }
160   else if (param.max_value > param.min_value && value > param.max_value)
161     {
162       error ("maximum value of parameter %qs is %u",
163 	     param.option, param.max_value);
164       return false;
165     }
166   else if (targetm_common.option_validate_param (value, index))
167     return true;
168 
169   return false;
170 }
171 
172 /* Return true if it can find the matching entry for NAME in the parameter
173    table, and assign the entry index to INDEX.  Return false otherwise.  */
174 
175 bool
find_param(const char * name,enum compiler_param * index)176 find_param (const char *name, enum compiler_param *index)
177 {
178   for (size_t i = 0; i < num_compiler_params; ++i)
179     if (strcmp (compiler_params[i].option, name) == 0)
180       {
181 	*index = (enum compiler_param) i;
182 	return true;
183       }
184 
185   return false;
186 }
187 
188 /* Look for the closest match for NAME in the parameter table, returning it
189    if it is a reasonable suggestion for a misspelling.  Return NULL
190    otherwise.  */
191 
192 const char *
find_param_fuzzy(const char * name)193 find_param_fuzzy (const char *name)
194 {
195   best_match <const char *, const char *> bm (name);
196   for (size_t i = 0; i < num_compiler_params; ++i)
197     bm.consider (compiler_params[i].option);
198   return bm.get_best_meaningful_candidate ();
199 }
200 
201 /* Return true if param with entry index INDEX should be defined using strings.
202    If so, return the value corresponding to VALUE_NAME in *VALUE_P.  */
203 
204 bool
param_string_value_p(enum compiler_param index,const char * value_name,int * value_p)205 param_string_value_p (enum compiler_param index, const char *value_name,
206 		      int *value_p)
207 {
208   param_info *entry = &compiler_params[(int) index];
209   if (entry->value_names == NULL)
210     return false;
211 
212   *value_p = -1;
213 
214   for (int i = 0; entry->value_names[i] != NULL; ++i)
215     if (strcmp (entry->value_names[i], value_name) == 0)
216       {
217 	*value_p = i;
218 	return true;
219       }
220 
221   return true;
222 }
223 
224 /* Set the VALUE associated with the parameter given by NAME in PARAMS
225    and PARAMS_SET.  */
226 
227 void
set_param_value(const char * name,int value,int * params,int * params_set)228 set_param_value (const char *name, int value,
229 		 int *params, int *params_set)
230 {
231   size_t i;
232 
233   /* Make sure nobody tries to set a parameter to an invalid value.  */
234   gcc_assert (value != INVALID_PARAM_VAL);
235 
236   enum compiler_param index;
237   if (!find_param (name, &index))
238     {
239       /* If we didn't find this parameter, issue an error message.  */
240       error ("invalid parameter %qs", name);
241       return;
242     }
243   i = (size_t)index;
244 
245   if (validate_param (value, compiler_params[i], i))
246     set_param_value_internal ((compiler_param) i, value,
247 			      params, params_set, true);
248 }
249 
250 /* Set the value of the parameter given by NUM to VALUE in PARAMS and
251    PARAMS_SET, implicitly, if it has not been set explicitly by the
252    user either via the commandline or configure.  */
253 
254 void
maybe_set_param_value(compiler_param num,int value,int * params,int * params_set)255 maybe_set_param_value (compiler_param num, int value,
256 		       int *params, int *params_set)
257 {
258   if (!params_set[(int) num])
259     set_param_value_internal (num, value, params, params_set, false);
260 }
261 
262 /* Set the default value of a parameter given by NUM to VALUE, before
263    option processing.  */
264 
265 void
set_default_param_value(compiler_param num,int value)266 set_default_param_value (compiler_param num, int value)
267 {
268   gcc_assert (!params_finished);
269 
270   compiler_params[(int) num].default_value = value;
271 }
272 
273 /* Return the default value of parameter NUM.  */
274 
275 int
default_param_value(compiler_param num)276 default_param_value (compiler_param num)
277 {
278   return compiler_params[(int) num].default_value;
279 }
280 
281 /* Initialize an array PARAMS with default values of the
282    parameters.  */
283 
284 void
init_param_values(int * params)285 init_param_values (int *params)
286 {
287   size_t i;
288 
289   gcc_assert (params_finished);
290 
291   for (i = 0; i < num_compiler_params; i++)
292     params[i] = compiler_params[i].default_value;
293 }
294 
295 /* Return the current value of num_compiler_params, for the benefit of
296    plugins that use parameters as features.  */
297 
298 size_t
get_num_compiler_params(void)299 get_num_compiler_params (void)
300 {
301   return num_compiler_params;
302 }
303