]>
Commit | Line | Data |
---|---|---|
df401d54 | 1 | /* Common hooks for AArch64. |
fbd26352 | 2 | Copyright (C) 2012-2019 Free Software Foundation, Inc. |
df401d54 | 3 | Contributed by ARM Ltd. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU General Public License as published | |
9 | by the Free Software Foundation; either version 3, or (at your | |
10 | option) any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | License 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" | |
e1b9f860 | 22 | #define INCLUDE_STRING |
df401d54 | 23 | #include "system.h" |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
ad7b10a2 | 26 | #include "memmodel.h" |
df401d54 | 27 | #include "tm_p.h" |
28 | #include "common/common-target.h" | |
29 | #include "common/common-target-def.h" | |
30 | #include "opts.h" | |
31 | #include "flags.h" | |
9dc3dccb | 32 | #include "diagnostic.h" |
f86dbd4b | 33 | #include "params.h" |
df401d54 | 34 | |
35 | #ifdef TARGET_BIG_ENDIAN_DEFAULT | |
36 | #undef TARGET_DEFAULT_TARGET_FLAGS | |
37 | #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END) | |
38 | #endif | |
39 | ||
40 | #undef TARGET_HANDLE_OPTION | |
41 | #define TARGET_HANDLE_OPTION aarch64_handle_option | |
42 | ||
43 | #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
44 | #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table | |
f86dbd4b | 45 | #undef TARGET_OPTION_DEFAULT_PARAMS |
46 | #define TARGET_OPTION_DEFAULT_PARAMS aarch64_option_default_params | |
47 | #undef TARGET_OPTION_VALIDATE_PARAM | |
48 | #define TARGET_OPTION_VALIDATE_PARAM aarch64_option_validate_param | |
df401d54 | 49 | |
50 | /* Set default optimization options. */ | |
51 | static const struct default_options aarch_option_optimization_table[] = | |
52 | { | |
53 | /* Enable section anchors by default at -O1 or higher. */ | |
54 | { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, | |
c228c1ff | 55 | /* Disable fomit-frame-pointer by default. */ |
56 | { OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 0 }, | |
b0e7ddf0 | 57 | /* Enable -fsched-pressure by default when optimizing. */ |
58 | { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, | |
65c4a832 | 59 | /* Enable redundant extension instructions removal at -O2 and higher. */ |
60 | { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, | |
9cbee213 | 61 | #if (TARGET_DEFAULT_ASYNC_UNWIND_TABLES == 1) |
62 | { OPT_LEVELS_ALL, OPT_fasynchronous_unwind_tables, NULL, 1 }, | |
63 | { OPT_LEVELS_ALL, OPT_funwind_tables, NULL, 1}, | |
64 | #endif | |
df401d54 | 65 | { OPT_LEVELS_NONE, 0, NULL, 0 } |
66 | }; | |
67 | ||
f86dbd4b | 68 | /* Implement target validation TARGET_OPTION_DEFAULT_PARAM. */ |
69 | ||
70 | static bool | |
71 | aarch64_option_validate_param (const int value, const int param) | |
72 | { | |
73 | /* Check that both parameters are the same. */ | |
74 | if (param == (int) PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE) | |
75 | { | |
76 | if (value != 12 && value != 16) | |
77 | { | |
78 | error ("only values 12 (4 KB) and 16 (64 KB) are supported for guard " | |
79 | "size. Given value %d (%llu KB) is out of range", | |
80 | value, (1ULL << value) / 1024ULL); | |
81 | return false; | |
82 | } | |
83 | } | |
84 | ||
85 | return true; | |
86 | } | |
87 | ||
88 | /* Implement TARGET_OPTION_DEFAULT_PARAMS. */ | |
89 | ||
90 | static void | |
91 | aarch64_option_default_params (void) | |
92 | { | |
93 | /* We assume the guard page is 64k. */ | |
94 | int index = (int) PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE; | |
95 | set_default_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE, | |
96 | DEFAULT_STK_CLASH_GUARD_SIZE == 0 | |
97 | ? 16 : DEFAULT_STK_CLASH_GUARD_SIZE); | |
98 | ||
99 | int guard_size | |
100 | = default_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE); | |
101 | ||
102 | /* Set the interval parameter to be the same as the guard size. This way the | |
103 | mid-end code does the right thing for us. */ | |
104 | set_default_param_value (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL, | |
105 | guard_size); | |
106 | ||
107 | /* Validate the options. */ | |
108 | aarch64_option_validate_param (guard_size, index); | |
109 | } | |
110 | ||
df401d54 | 111 | /* Implement TARGET_HANDLE_OPTION. |
112 | This function handles the target specific options for CPU/target selection. | |
113 | ||
03189b5b | 114 | -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU. |
115 | If either of -march or -mtune is given, they override their | |
116 | respective component of -mcpu. This logic is implemented | |
117 | in config/aarch64/aarch64.c:aarch64_override_options. */ | |
df401d54 | 118 | |
aadb8e17 | 119 | bool |
df401d54 | 120 | aarch64_handle_option (struct gcc_options *opts, |
121 | struct gcc_options *opts_set ATTRIBUTE_UNUSED, | |
122 | const struct cl_decoded_option *decoded, | |
123 | location_t loc ATTRIBUTE_UNUSED) | |
124 | { | |
125 | size_t code = decoded->opt_index; | |
126 | const char *arg = decoded->arg; | |
aadb8e17 | 127 | int val = decoded->value; |
df401d54 | 128 | |
129 | switch (code) | |
130 | { | |
131 | case OPT_march_: | |
132 | opts->x_aarch64_arch_string = arg; | |
df401d54 | 133 | return true; |
134 | ||
135 | case OPT_mcpu_: | |
136 | opts->x_aarch64_cpu_string = arg; | |
df401d54 | 137 | return true; |
138 | ||
139 | case OPT_mtune_: | |
140 | opts->x_aarch64_tune_string = arg; | |
141 | return true; | |
142 | ||
aadb8e17 | 143 | case OPT_mgeneral_regs_only: |
144 | opts->x_target_flags |= MASK_GENERAL_REGS_ONLY; | |
145 | return true; | |
146 | ||
147 | case OPT_mfix_cortex_a53_835769: | |
148 | opts->x_aarch64_fix_a53_err835769 = val; | |
149 | return true; | |
150 | ||
151 | case OPT_mstrict_align: | |
1d3fdc51 | 152 | if (val) |
153 | opts->x_target_flags |= MASK_STRICT_ALIGN; | |
154 | else | |
155 | opts->x_target_flags &= ~MASK_STRICT_ALIGN; | |
aadb8e17 | 156 | return true; |
157 | ||
158 | case OPT_momit_leaf_frame_pointer: | |
279b9397 | 159 | opts->x_flag_omit_leaf_frame_pointer = val; |
aadb8e17 | 160 | return true; |
161 | ||
df401d54 | 162 | default: |
163 | return true; | |
164 | } | |
165 | } | |
166 | ||
167 | struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; | |
60ae84fc | 168 | |
9dc3dccb | 169 | /* An ISA extension in the co-processor and main instruction set space. */ |
170 | struct aarch64_option_extension | |
171 | { | |
172 | const char *const name; | |
a702492c | 173 | const unsigned long flag_canonical; |
9dc3dccb | 174 | const unsigned long flags_on; |
175 | const unsigned long flags_off; | |
176 | }; | |
177 | ||
178 | /* ISA extensions in AArch64. */ | |
179 | static const struct aarch64_option_extension all_extensions[] = | |
180 | { | |
a702492c | 181 | #define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \ |
182 | {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF}, | |
9dc3dccb | 183 | #include "config/aarch64/aarch64-option-extensions.def" |
a702492c | 184 | {NULL, 0, 0, 0} |
9dc3dccb | 185 | }; |
186 | ||
187 | struct processor_name_to_arch | |
188 | { | |
189 | const std::string processor_name; | |
190 | const enum aarch64_arch arch; | |
191 | const unsigned long flags; | |
192 | }; | |
193 | ||
194 | struct arch_to_arch_name | |
195 | { | |
196 | const enum aarch64_arch arch; | |
197 | const std::string arch_name; | |
a702492c | 198 | const unsigned long flags; |
9dc3dccb | 199 | }; |
200 | ||
201 | /* Map processor names to the architecture revision they implement and | |
202 | the default set of architectural feature flags they support. */ | |
203 | static const struct processor_name_to_arch all_cores[] = | |
204 | { | |
7a2c84f9 | 205 | #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \ |
9dc3dccb | 206 | {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS}, |
207 | #include "config/aarch64/aarch64-cores.def" | |
9dc3dccb | 208 | {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8}, |
209 | {"", aarch64_no_arch, 0} | |
210 | }; | |
211 | ||
212 | /* Map architecture revisions to their string representation. */ | |
213 | static const struct arch_to_arch_name all_architectures[] = | |
214 | { | |
215 | #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \ | |
a702492c | 216 | {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS}, |
9dc3dccb | 217 | #include "config/aarch64/aarch64-arches.def" |
a702492c | 218 | {aarch64_no_arch, "", 0} |
9dc3dccb | 219 | }; |
220 | ||
a702492c | 221 | /* Parse the architecture extension string STR and update ISA_FLAGS |
222 | with the architecture features turned on or off. Return a | |
242dc50c | 223 | aarch64_parse_opt_result describing the result. |
224 | When the STR string contains an invalid extension, | |
225 | a copy of the string is created and stored to INVALID_EXTENSION. */ | |
a702492c | 226 | |
227 | enum aarch64_parse_opt_result | |
242dc50c | 228 | aarch64_parse_extension (const char *str, unsigned long *isa_flags, |
229 | std::string *invalid_extension) | |
a702492c | 230 | { |
231 | /* The extension string is parsed left to right. */ | |
232 | const struct aarch64_option_extension *opt = NULL; | |
233 | ||
234 | /* Flag to say whether we are adding or removing an extension. */ | |
235 | int adding_ext = -1; | |
236 | ||
237 | while (str != NULL && *str != 0) | |
238 | { | |
239 | const char *ext; | |
240 | size_t len; | |
241 | ||
242 | str++; | |
243 | ext = strchr (str, '+'); | |
244 | ||
245 | if (ext != NULL) | |
246 | len = ext - str; | |
247 | else | |
248 | len = strlen (str); | |
249 | ||
250 | if (len >= 2 && strncmp (str, "no", 2) == 0) | |
251 | { | |
252 | adding_ext = 0; | |
253 | len -= 2; | |
254 | str += 2; | |
255 | } | |
256 | else if (len > 0) | |
257 | adding_ext = 1; | |
258 | ||
259 | if (len == 0) | |
260 | return AARCH64_PARSE_MISSING_ARG; | |
261 | ||
262 | ||
263 | /* Scan over the extensions table trying to find an exact match. */ | |
264 | for (opt = all_extensions; opt->name != NULL; opt++) | |
265 | { | |
266 | if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0) | |
267 | { | |
268 | /* Add or remove the extension. */ | |
269 | if (adding_ext) | |
270 | *isa_flags |= (opt->flags_on | opt->flag_canonical); | |
271 | else | |
272 | *isa_flags &= ~(opt->flags_off | opt->flag_canonical); | |
273 | break; | |
274 | } | |
275 | } | |
276 | ||
277 | if (opt->name == NULL) | |
278 | { | |
279 | /* Extension not found in list. */ | |
242dc50c | 280 | if (invalid_extension) |
281 | *invalid_extension = std::string (str, len); | |
a702492c | 282 | return AARCH64_PARSE_INVALID_FEATURE; |
283 | } | |
284 | ||
285 | str = ext; | |
286 | }; | |
287 | ||
288 | return AARCH64_PARSE_OK; | |
289 | } | |
290 | ||
242dc50c | 291 | /* Append all architecture extension candidates to the CANDIDATES vector. */ |
292 | ||
293 | void | |
294 | aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates) | |
295 | { | |
296 | const struct aarch64_option_extension *opt; | |
297 | for (opt = all_extensions; opt->name != NULL; opt++) | |
298 | candidates->safe_push (opt->name); | |
299 | } | |
300 | ||
a702492c | 301 | /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS |
302 | gives the default set of flags which are implied by whatever -march | |
303 | we'd put out. Our job is to figure out the minimal set of "+" and | |
304 | "+no" feature flags to put out, and to put them out grouped such | |
305 | that all the "+" flags come before the "+no" flags. */ | |
9dc3dccb | 306 | |
307 | std::string | |
a702492c | 308 | aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags, |
309 | unsigned long default_arch_flags) | |
9dc3dccb | 310 | { |
311 | const struct aarch64_option_extension *opt = NULL; | |
312 | std::string outstr = ""; | |
313 | ||
a702492c | 314 | /* Pass one: Find all the things we need to turn on. As a special case, |
315 | we always want to put out +crc if it is enabled. */ | |
9dc3dccb | 316 | for (opt = all_extensions; opt->name != NULL; opt++) |
a702492c | 317 | if ((isa_flags & opt->flag_canonical |
318 | && !(default_arch_flags & opt->flag_canonical)) | |
319 | || (default_arch_flags & opt->flag_canonical | |
320 | && opt->flag_canonical == AARCH64_ISA_CRC)) | |
9dc3dccb | 321 | { |
322 | outstr += "+"; | |
323 | outstr += opt->name; | |
324 | } | |
a702492c | 325 | |
326 | /* Pass two: Find all the things we need to turn off. */ | |
327 | for (opt = all_extensions; opt->name != NULL; opt++) | |
328 | if ((~isa_flags) & opt->flag_canonical | |
329 | && !((~default_arch_flags) & opt->flag_canonical)) | |
330 | { | |
331 | outstr += "+no"; | |
332 | outstr += opt->name; | |
333 | } | |
334 | ||
9dc3dccb | 335 | return outstr; |
336 | } | |
60ae84fc | 337 | |
9dc3dccb | 338 | /* Attempt to rewrite NAME, which has been passed on the command line |
339 | as a -mcpu option to an equivalent -march value. If we can do so, | |
340 | return the new string, otherwise return an error. */ | |
60ae84fc | 341 | |
342 | const char * | |
343 | aarch64_rewrite_selected_cpu (const char *name) | |
344 | { | |
9dc3dccb | 345 | std::string original_string (name); |
a702492c | 346 | std::string extension_str; |
9dc3dccb | 347 | std::string processor; |
348 | size_t extension_pos = original_string.find_first_of ('+'); | |
60ae84fc | 349 | |
9dc3dccb | 350 | /* Strip and save the extension string. */ |
351 | if (extension_pos != std::string::npos) | |
352 | { | |
353 | processor = original_string.substr (0, extension_pos); | |
a702492c | 354 | extension_str = original_string.substr (extension_pos, |
355 | std::string::npos); | |
9dc3dccb | 356 | } |
357 | else | |
358 | { | |
359 | /* No extensions. */ | |
360 | processor = original_string; | |
361 | } | |
e06408d0 | 362 | |
9dc3dccb | 363 | const struct processor_name_to_arch* p_to_a; |
364 | for (p_to_a = all_cores; | |
365 | p_to_a->arch != aarch64_no_arch; | |
366 | p_to_a++) | |
367 | { | |
368 | if (p_to_a->processor_name == processor) | |
369 | break; | |
370 | } | |
e06408d0 | 371 | |
9dc3dccb | 372 | const struct arch_to_arch_name* a_to_an; |
373 | for (a_to_an = all_architectures; | |
374 | a_to_an->arch != aarch64_no_arch; | |
375 | a_to_an++) | |
376 | { | |
377 | if (a_to_an->arch == p_to_a->arch) | |
378 | break; | |
379 | } | |
60ae84fc | 380 | |
9dc3dccb | 381 | /* We couldn't find that proceesor name, or the processor name we |
382 | found does not map to an architecture we understand. */ | |
383 | if (p_to_a->arch == aarch64_no_arch | |
384 | || a_to_an->arch == aarch64_no_arch) | |
385 | fatal_error (input_location, "unknown value %qs for -mcpu", name); | |
386 | ||
a702492c | 387 | unsigned long extensions = p_to_a->flags; |
242dc50c | 388 | aarch64_parse_extension (extension_str.c_str (), &extensions, NULL); |
a702492c | 389 | |
9dc3dccb | 390 | std::string outstr = a_to_an->arch_name |
a702492c | 391 | + aarch64_get_extension_string_for_isa_flags (extensions, |
392 | a_to_an->flags); | |
9dc3dccb | 393 | |
394 | /* We are going to memory leak here, nobody elsewhere | |
395 | in the callchain is going to clean up after us. The alternative is | |
396 | to allocate a static buffer, and assert that it is big enough for our | |
397 | modified string, which seems much worse! */ | |
398 | return xstrdup (outstr.c_str ()); | |
60ae84fc | 399 | } |
400 | ||
401 | /* Called by the driver to rewrite a name passed to the -mcpu | |
402 | argument in preparation to be passed to the assembler. The | |
5f273397 | 403 | names passed from the commend line will be in ARGV, we want |
404 | to use the right-most argument, which should be in | |
405 | ARGV[ARGC - 1]. ARGC should always be greater than 0. */ | |
60ae84fc | 406 | |
407 | const char * | |
408 | aarch64_rewrite_mcpu (int argc, const char **argv) | |
409 | { | |
5f273397 | 410 | gcc_assert (argc); |
411 | return aarch64_rewrite_selected_cpu (argv[argc - 1]); | |
60ae84fc | 412 | } |
413 | ||
414 | #undef AARCH64_CPU_NAME_LENGTH | |
415 |