]>
Commit | Line | Data |
---|---|---|
e4ea20c8 | 1 | /* Target-specific code for C family languages. |
83ffe9cd | 2 | Copyright (C) 2015-2023 Free Software Foundation, Inc. |
e4ea20c8 KT |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GCC 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 GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
8fcc61f8 RS |
20 | #define IN_TARGET_CODE 1 |
21 | ||
e4ea20c8 KT |
22 | #include "config.h" |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "input.h" | |
4d0cdd0c | 27 | #include "memmodel.h" |
e4ea20c8 KT |
28 | #include "tm_p.h" |
29 | #include "flags.h" | |
30 | #include "c-family/c-common.h" | |
31 | #include "cpplib.h" | |
32 | #include "c-family/c-pragma.h" | |
33 | #include "langhooks.h" | |
34 | #include "target.h" | |
35 | ||
36 | ||
37 | #define builtin_define(TXT) cpp_define (pfile, TXT) | |
38 | #define builtin_assert(TXT) cpp_assert (pfile, TXT) | |
39 | ||
40 | ||
41 | static void | |
42 | aarch64_def_or_undef (bool def_p, const char *macro, cpp_reader *pfile) | |
43 | { | |
44 | if (def_p) | |
45 | cpp_define (pfile, macro); | |
46 | else | |
47 | cpp_undef (pfile, macro); | |
48 | } | |
49 | ||
50 | /* Define the macros that we always expect to have on AArch64. */ | |
51 | ||
52 | static void | |
53 | aarch64_define_unconditional_macros (cpp_reader *pfile) | |
54 | { | |
55 | builtin_define ("__aarch64__"); | |
56 | builtin_define ("__ARM_64BIT_STATE"); | |
57 | ||
58 | builtin_define ("__ARM_ARCH_ISA_A64"); | |
59 | builtin_define_with_int_value ("__ARM_ALIGN_MAX_PWR", 28); | |
60 | builtin_define_with_int_value ("__ARM_ALIGN_MAX_STACK_PWR", 16); | |
61 | ||
62 | /* __ARM_ARCH_8A is not mandated by ACLE but we define it unconditionally | |
63 | as interoperability with the same arm macro. */ | |
64 | builtin_define ("__ARM_ARCH_8A"); | |
65 | ||
786177a3 | 66 | builtin_define_with_int_value ("__ARM_ARCH_PROFILE", |
2a4788ac | 67 | AARCH64_ISA_V8R ? 'R' : 'A'); |
e4ea20c8 KT |
68 | builtin_define ("__ARM_FEATURE_CLZ"); |
69 | builtin_define ("__ARM_FEATURE_IDIV"); | |
70 | builtin_define ("__ARM_FEATURE_UNALIGNED"); | |
71 | builtin_define ("__ARM_PCS_AAPCS64"); | |
72 | builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8); | |
1a7a35c7 RH |
73 | |
74 | builtin_define ("__GCC_ASM_FLAG_OUTPUTS__"); | |
e4ea20c8 KT |
75 | } |
76 | ||
77 | /* Undefine/redefine macros that depend on the current backend state and may | |
78 | need to change when a target pragma modifies the backend state. */ | |
79 | ||
80 | static void | |
81 | aarch64_update_cpp_builtins (cpp_reader *pfile) | |
82 | { | |
83 | aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile); | |
84 | ||
2a4788ac | 85 | builtin_define_with_int_value ("__ARM_ARCH", AARCH64_ISA_V9A ? 9 : 8); |
e4ea20c8 KT |
86 | |
87 | builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM", | |
88 | flag_short_enums ? 1 : 4); | |
89 | aarch64_def_or_undef (TARGET_BIG_END, "__AARCH64EB__", pfile); | |
90 | aarch64_def_or_undef (TARGET_BIG_END, "__ARM_BIG_ENDIAN", pfile); | |
91 | aarch64_def_or_undef (!TARGET_BIG_END, "__AARCH64EL__", pfile); | |
92 | ||
93 | aarch64_def_or_undef (TARGET_FLOAT, "__ARM_FEATURE_FMA", pfile); | |
94 | ||
a3164184 | 95 | if (TARGET_FLOAT) |
e4ea20c8 KT |
96 | { |
97 | builtin_define_with_int_value ("__ARM_FP", 0x0E); | |
98 | builtin_define ("__ARM_FP16_FORMAT_IEEE"); | |
99 | builtin_define ("__ARM_FP16_ARGS"); | |
100 | } | |
101 | else | |
102 | cpp_undef (pfile, "__ARM_FP"); | |
103 | ||
c61465bd MW |
104 | aarch64_def_or_undef (TARGET_FP_F16INST, |
105 | "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", pfile); | |
106 | aarch64_def_or_undef (TARGET_SIMD_F16INST, | |
107 | "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", pfile); | |
108 | ||
e4ea20c8 KT |
109 | aarch64_def_or_undef (TARGET_SIMD, "__ARM_FEATURE_NUMERIC_MAXMIN", pfile); |
110 | aarch64_def_or_undef (TARGET_SIMD, "__ARM_NEON", pfile); | |
111 | ||
112 | ||
113 | aarch64_def_or_undef (TARGET_CRC32, "__ARM_FEATURE_CRC32", pfile); | |
1ddc47c0 | 114 | aarch64_def_or_undef (TARGET_DOTPROD, "__ARM_FEATURE_DOTPROD", pfile); |
9d63f43b | 115 | aarch64_def_or_undef (TARGET_COMPLEX, "__ARM_FEATURE_COMPLEX", pfile); |
e1d5d19e | 116 | aarch64_def_or_undef (TARGET_JSCVT, "__ARM_FEATURE_JCVT", pfile); |
e4ea20c8 KT |
117 | |
118 | cpp_undef (pfile, "__AARCH64_CMODEL_TINY__"); | |
119 | cpp_undef (pfile, "__AARCH64_CMODEL_SMALL__"); | |
120 | cpp_undef (pfile, "__AARCH64_CMODEL_LARGE__"); | |
121 | ||
122 | switch (aarch64_cmodel) | |
123 | { | |
124 | case AARCH64_CMODEL_TINY: | |
125 | case AARCH64_CMODEL_TINY_PIC: | |
126 | builtin_define ("__AARCH64_CMODEL_TINY__"); | |
127 | break; | |
128 | case AARCH64_CMODEL_SMALL: | |
129 | case AARCH64_CMODEL_SMALL_PIC: | |
130 | builtin_define ("__AARCH64_CMODEL_SMALL__"); | |
131 | break; | |
132 | case AARCH64_CMODEL_LARGE: | |
133 | builtin_define ("__AARCH64_CMODEL_LARGE__"); | |
134 | break; | |
135 | default: | |
136 | break; | |
137 | } | |
138 | ||
139 | aarch64_def_or_undef (TARGET_ILP32, "_ILP32", pfile); | |
140 | aarch64_def_or_undef (TARGET_ILP32, "__ILP32__", pfile); | |
141 | ||
142 | aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile); | |
89c9a60c | 143 | aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile); |
43cacb12 RS |
144 | aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE", pfile); |
145 | cpp_undef (pfile, "__ARM_FEATURE_SVE_BITS"); | |
146 | if (TARGET_SVE) | |
147 | { | |
148 | int bits; | |
149 | if (!BITS_PER_SVE_VECTOR.is_constant (&bits)) | |
150 | bits = 0; | |
151 | builtin_define_with_int_value ("__ARM_FEATURE_SVE_BITS", bits); | |
152 | } | |
ef4af9ed | 153 | aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE_VECTOR_OPERATORS", |
38e62001 | 154 | pfile); |
36696774 RS |
155 | aarch64_def_or_undef (TARGET_SVE_I8MM, |
156 | "__ARM_FEATURE_SVE_MATMUL_INT8", pfile); | |
157 | aarch64_def_or_undef (TARGET_SVE_F32MM, | |
158 | "__ARM_FEATURE_SVE_MATMUL_FP32", pfile); | |
159 | aarch64_def_or_undef (TARGET_SVE_F64MM, | |
160 | "__ARM_FEATURE_SVE_MATMUL_FP64", pfile); | |
0617e23c | 161 | aarch64_def_or_undef (TARGET_SVE2, "__ARM_FEATURE_SVE2", pfile); |
0a09a948 RS |
162 | aarch64_def_or_undef (TARGET_SVE2_AES, "__ARM_FEATURE_SVE2_AES", pfile); |
163 | aarch64_def_or_undef (TARGET_SVE2_BITPERM, | |
164 | "__ARM_FEATURE_SVE2_BITPERM", pfile); | |
165 | aarch64_def_or_undef (TARGET_SVE2_SHA3, "__ARM_FEATURE_SVE2_SHA3", pfile); | |
166 | aarch64_def_or_undef (TARGET_SVE2_SM4, "__ARM_FEATURE_SVE2_SM4", pfile); | |
11e554b3 | 167 | |
abb3c64e | 168 | aarch64_def_or_undef (TARGET_LSE, "__ARM_FEATURE_ATOMICS", pfile); |
27086ea3 MC |
169 | aarch64_def_or_undef (TARGET_AES, "__ARM_FEATURE_AES", pfile); |
170 | aarch64_def_or_undef (TARGET_SHA2, "__ARM_FEATURE_SHA2", pfile); | |
171 | aarch64_def_or_undef (TARGET_SHA3, "__ARM_FEATURE_SHA3", pfile); | |
172 | aarch64_def_or_undef (TARGET_SHA3, "__ARM_FEATURE_SHA512", pfile); | |
173 | aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM3", pfile); | |
174 | aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM4", pfile); | |
175 | aarch64_def_or_undef (TARGET_F16FML, "__ARM_FEATURE_FP16_FML", pfile); | |
176 | ||
10bd1d96 | 177 | aarch64_def_or_undef (TARGET_FRINT, "__ARM_FEATURE_FRINT", pfile); |
89626179 | 178 | aarch64_def_or_undef (TARGET_TME, "__ARM_FEATURE_TME", pfile); |
c5dc215d | 179 | aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile); |
ef01e6bb | 180 | aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile); |
89626179 | 181 | |
63b6808e SN |
182 | aarch64_def_or_undef (aarch64_bti_enabled (), |
183 | "__ARM_FEATURE_BTI_DEFAULT", pfile); | |
184 | ||
a1faa8e2 SN |
185 | cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT"); |
186 | if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE) | |
187 | { | |
188 | int v = 0; | |
189 | if (aarch64_ra_sign_key == AARCH64_KEY_A) | |
190 | v |= 1; | |
191 | if (aarch64_ra_sign_key == AARCH64_KEY_B) | |
192 | v |= 2; | |
193 | if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL) | |
194 | v |= 4; | |
195 | builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v); | |
196 | } | |
197 | ||
688f4eb2 KT |
198 | aarch64_def_or_undef (TARGET_PAUTH, "__ARM_FEATURE_PAUTH", pfile); |
199 | aarch64_def_or_undef (TARGET_BTI, "__ARM_FEATURE_BTI", pfile); | |
a93e1d5c DZ |
200 | aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile); |
201 | aarch64_def_or_undef (TARGET_BF16_SIMD, | |
202 | "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile); | |
203 | aarch64_def_or_undef (TARGET_BF16_FP, | |
204 | "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); | |
fdcddba8 PW |
205 | aarch64_def_or_undef (TARGET_LS64, |
206 | "__ARM_FEATURE_LS64", pfile); | |
c1b0a767 | 207 | aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile); |
a93e1d5c | 208 | |
11e554b3 JG |
209 | /* Not for ACLE, but required to keep "float.h" correct if we switch |
210 | target between implementations that do or do not support ARMv8.2-A | |
211 | 16-bit floating-point extensions. */ | |
212 | cpp_undef (pfile, "__FLT_EVAL_METHOD__"); | |
213 | builtin_define_with_int_value ("__FLT_EVAL_METHOD__", | |
214 | c_flt_eval_method (true)); | |
215 | cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__"); | |
216 | builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__", | |
217 | c_flt_eval_method (false)); | |
e4ea20c8 KT |
218 | } |
219 | ||
220 | /* Implement TARGET_CPU_CPP_BUILTINS. */ | |
221 | ||
222 | void | |
223 | aarch64_cpu_cpp_builtins (cpp_reader *pfile) | |
224 | { | |
225 | aarch64_define_unconditional_macros (pfile); | |
226 | aarch64_update_cpp_builtins (pfile); | |
227 | } | |
228 | ||
229 | /* Hook to validate the current #pragma GCC target and set the state, and | |
230 | update the macros based on what was changed. If ARGS is NULL, then | |
231 | POP_TARGET is used to reset the options. */ | |
232 | ||
233 | static bool | |
234 | aarch64_pragma_target_parse (tree args, tree pop_target) | |
235 | { | |
236 | /* If args is not NULL then process it and setup the target-specific | |
237 | information that it specifies. */ | |
238 | if (args) | |
239 | { | |
ab93e9b7 | 240 | if (!aarch64_process_target_attr (args)) |
e4ea20c8 KT |
241 | return false; |
242 | ||
243 | aarch64_override_options_internal (&global_options); | |
244 | } | |
245 | ||
246 | /* args is NULL, restore to the state described in pop_target. */ | |
247 | else | |
248 | { | |
249 | pop_target = pop_target ? pop_target : target_option_default_node; | |
ba948b37 | 250 | cl_target_option_restore (&global_options, &global_options_set, |
e4ea20c8 KT |
251 | TREE_TARGET_OPTION (pop_target)); |
252 | } | |
253 | ||
254 | target_option_current_node | |
ba948b37 | 255 | = build_target_option_node (&global_options, &global_options_set); |
e4ea20c8 KT |
256 | |
257 | aarch64_reset_previous_fndecl (); | |
258 | /* For the definitions, ensure all newly defined macros are considered | |
259 | as used for -Wunused-macros. There is no point warning about the | |
260 | compiler predefined macros. */ | |
261 | cpp_options *cpp_opts = cpp_get_options (parse_in); | |
262 | unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros; | |
263 | cpp_opts->warn_unused_macros = 0; | |
264 | ||
1dbe26b9 | 265 | cpp_force_token_locations (parse_in, BUILTINS_LOCATION); |
e4ea20c8 | 266 | aarch64_update_cpp_builtins (parse_in); |
1dbe26b9 | 267 | cpp_stop_forcing_token_locations (parse_in); |
e4ea20c8 KT |
268 | |
269 | cpp_opts->warn_unused_macros = saved_warn_unused_macros; | |
270 | ||
acfc1ac1 KT |
271 | /* If we're popping or reseting make sure to update the globals so that |
272 | the optab availability predicates get recomputed. */ | |
273 | if (pop_target) | |
274 | aarch64_save_restore_target_globals (pop_target); | |
275 | ||
e4ea20c8 KT |
276 | return true; |
277 | } | |
278 | ||
624d0f07 RS |
279 | /* Implement "#pragma GCC aarch64". */ |
280 | static void | |
281 | aarch64_pragma_aarch64 (cpp_reader *) | |
282 | { | |
283 | tree x; | |
284 | if (pragma_lex (&x) != CPP_STRING) | |
285 | { | |
286 | error ("%<#pragma GCC aarch64%> requires a string parameter"); | |
287 | return; | |
288 | } | |
289 | ||
290 | const char *name = TREE_STRING_POINTER (x); | |
291 | if (strcmp (name, "arm_sve.h") == 0) | |
292 | aarch64_sve::handle_arm_sve_h (); | |
8197ab94 JW |
293 | else if (strcmp (name, "arm_neon.h") == 0) |
294 | handle_arm_neon_h (); | |
af3cadb5 TC |
295 | else if (strcmp (name, "arm_acle.h") == 0) |
296 | handle_arm_acle_h (); | |
624d0f07 RS |
297 | else |
298 | error ("unknown %<#pragma GCC aarch64%> option %qs", name); | |
299 | } | |
300 | ||
301 | /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */ | |
302 | static tree | |
303 | aarch64_resolve_overloaded_builtin (unsigned int uncast_location, | |
304 | tree fndecl, void *uncast_arglist) | |
305 | { | |
306 | vec<tree, va_gc> empty = {}; | |
307 | location_t location = (location_t) uncast_location; | |
308 | vec<tree, va_gc> *arglist = (uncast_arglist | |
309 | ? (vec<tree, va_gc> *) uncast_arglist | |
310 | : &empty); | |
311 | unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); | |
312 | unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; | |
313 | tree new_fndecl; | |
314 | switch (code & AARCH64_BUILTIN_CLASS) | |
315 | { | |
316 | case AARCH64_BUILTIN_GENERAL: | |
ef01e6bb DZ |
317 | return aarch64_resolve_overloaded_builtin_general (location, fndecl, |
318 | uncast_arglist); | |
624d0f07 RS |
319 | case AARCH64_BUILTIN_SVE: |
320 | new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode, | |
321 | arglist); | |
322 | break; | |
323 | } | |
324 | if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node) | |
325 | return new_fndecl; | |
326 | return build_function_call_vec (location, vNULL, new_fndecl, arglist, | |
327 | NULL, fndecl); | |
328 | } | |
329 | ||
330 | /* Implement TARGET_CHECK_BUILTIN_CALL. */ | |
331 | static bool | |
332 | aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc, | |
333 | tree fndecl, tree orig_fndecl, | |
334 | unsigned int nargs, tree *args) | |
335 | { | |
336 | unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); | |
337 | unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; | |
338 | switch (code & AARCH64_BUILTIN_CLASS) | |
339 | { | |
340 | case AARCH64_BUILTIN_GENERAL: | |
341 | return true; | |
342 | ||
343 | case AARCH64_BUILTIN_SVE: | |
344 | return aarch64_sve::check_builtin_call (loc, arg_loc, subcode, | |
345 | orig_fndecl, nargs, args); | |
346 | } | |
347 | gcc_unreachable (); | |
348 | } | |
349 | ||
e4ea20c8 KT |
350 | /* Implement REGISTER_TARGET_PRAGMAS. */ |
351 | ||
352 | void | |
353 | aarch64_register_pragmas (void) | |
354 | { | |
355 | /* Update pragma hook to allow parsing #pragma GCC target. */ | |
356 | targetm.target_option.pragma_parse = aarch64_pragma_target_parse; | |
624d0f07 RS |
357 | |
358 | targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin; | |
359 | targetm.check_builtin_call = aarch64_check_builtin_call; | |
360 | ||
361 | c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64); | |
e4ea20c8 | 362 | } |