1 /* Target-specific code for C family languages.
2 Copyright (C) 2015-2022 Free Software Foundation, Inc.
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
20 #define IN_TARGET_CODE 1
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "input.h"
27 #include "memmodel.h"
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
aarch64_def_or_undef(bool def_p,const char * macro,cpp_reader * pfile)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
aarch64_define_unconditional_macros(cpp_reader * pfile)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
66 builtin_define_with_int_value ("__ARM_ARCH_PROFILE",
67 AARCH64_ISA_V8_R ? 'R' : 'A');
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);
73
74 builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
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
aarch64_update_cpp_builtins(cpp_reader * pfile)81 aarch64_update_cpp_builtins (cpp_reader *pfile)
82 {
83 aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile);
84
85 builtin_define_with_int_value ("__ARM_ARCH", aarch64_architecture_version);
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
95 if (TARGET_FLOAT || TARGET_SIMD)
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
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
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);
114 aarch64_def_or_undef (TARGET_DOTPROD, "__ARM_FEATURE_DOTPROD", pfile);
115 aarch64_def_or_undef (TARGET_COMPLEX, "__ARM_FEATURE_COMPLEX", pfile);
116 aarch64_def_or_undef (TARGET_JSCVT, "__ARM_FEATURE_JCVT", pfile);
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);
143 aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
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 }
153 aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE_VECTOR_OPERATORS",
154 pfile);
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);
161 aarch64_def_or_undef (TARGET_SVE2, "__ARM_FEATURE_SVE2", pfile);
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);
167
168 aarch64_def_or_undef (TARGET_LSE, "__ARM_FEATURE_ATOMICS", pfile);
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
177 aarch64_def_or_undef (TARGET_FRINT, "__ARM_FEATURE_FRINT", pfile);
178 aarch64_def_or_undef (TARGET_TME, "__ARM_FEATURE_TME", pfile);
179 aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile);
180 aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile);
181
182 aarch64_def_or_undef (aarch64_bti_enabled (),
183 "__ARM_FEATURE_BTI_DEFAULT", pfile);
184
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
198 aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile);
199 aarch64_def_or_undef (TARGET_BF16_SIMD,
200 "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile);
201 aarch64_def_or_undef (TARGET_BF16_FP,
202 "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile);
203 aarch64_def_or_undef (TARGET_LS64,
204 "__ARM_FEATURE_LS64", pfile);
205 aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile);
206
207 /* Not for ACLE, but required to keep "float.h" correct if we switch
208 target between implementations that do or do not support ARMv8.2-A
209 16-bit floating-point extensions. */
210 cpp_undef (pfile, "__FLT_EVAL_METHOD__");
211 builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
212 c_flt_eval_method (true));
213 cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
214 builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
215 c_flt_eval_method (false));
216 }
217
218 /* Implement TARGET_CPU_CPP_BUILTINS. */
219
220 void
aarch64_cpu_cpp_builtins(cpp_reader * pfile)221 aarch64_cpu_cpp_builtins (cpp_reader *pfile)
222 {
223 aarch64_define_unconditional_macros (pfile);
224 aarch64_update_cpp_builtins (pfile);
225 }
226
227 /* Hook to validate the current #pragma GCC target and set the state, and
228 update the macros based on what was changed. If ARGS is NULL, then
229 POP_TARGET is used to reset the options. */
230
231 static bool
aarch64_pragma_target_parse(tree args,tree pop_target)232 aarch64_pragma_target_parse (tree args, tree pop_target)
233 {
234 /* If args is not NULL then process it and setup the target-specific
235 information that it specifies. */
236 if (args)
237 {
238 if (!aarch64_process_target_attr (args))
239 return false;
240
241 aarch64_override_options_internal (&global_options);
242 }
243
244 /* args is NULL, restore to the state described in pop_target. */
245 else
246 {
247 pop_target = pop_target ? pop_target : target_option_default_node;
248 cl_target_option_restore (&global_options, &global_options_set,
249 TREE_TARGET_OPTION (pop_target));
250 }
251
252 target_option_current_node
253 = build_target_option_node (&global_options, &global_options_set);
254
255 aarch64_reset_previous_fndecl ();
256 /* For the definitions, ensure all newly defined macros are considered
257 as used for -Wunused-macros. There is no point warning about the
258 compiler predefined macros. */
259 cpp_options *cpp_opts = cpp_get_options (parse_in);
260 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
261 cpp_opts->warn_unused_macros = 0;
262
263 cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
264 aarch64_update_cpp_builtins (parse_in);
265 cpp_stop_forcing_token_locations (parse_in);
266
267 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
268
269 /* If we're popping or reseting make sure to update the globals so that
270 the optab availability predicates get recomputed. */
271 if (pop_target)
272 aarch64_save_restore_target_globals (pop_target);
273
274 /* Initialize SIMD builtins if we haven't already.
275 Set current_target_pragma to NULL for the duration so that
276 the builtin initialization code doesn't try to tag the functions
277 being built with the attributes specified by any current pragma, thus
278 going into an infinite recursion. */
279 if (TARGET_SIMD)
280 {
281 tree saved_current_target_pragma = current_target_pragma;
282 current_target_pragma = NULL;
283 aarch64_init_simd_builtins ();
284 current_target_pragma = saved_current_target_pragma;
285 }
286
287 return true;
288 }
289
290 /* Implement "#pragma GCC aarch64". */
291 static void
aarch64_pragma_aarch64(cpp_reader *)292 aarch64_pragma_aarch64 (cpp_reader *)
293 {
294 tree x;
295 if (pragma_lex (&x) != CPP_STRING)
296 {
297 error ("%<#pragma GCC aarch64%> requires a string parameter");
298 return;
299 }
300
301 const char *name = TREE_STRING_POINTER (x);
302 if (strcmp (name, "arm_sve.h") == 0)
303 aarch64_sve::handle_arm_sve_h ();
304 else if (strcmp (name, "arm_neon.h") == 0)
305 handle_arm_neon_h ();
306 else if (strcmp (name, "arm_acle.h") == 0)
307 handle_arm_acle_h ();
308 else
309 error ("unknown %<#pragma GCC aarch64%> option %qs", name);
310 }
311
312 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
313 static tree
aarch64_resolve_overloaded_builtin(unsigned int uncast_location,tree fndecl,void * uncast_arglist)314 aarch64_resolve_overloaded_builtin (unsigned int uncast_location,
315 tree fndecl, void *uncast_arglist)
316 {
317 vec<tree, va_gc> empty = {};
318 location_t location = (location_t) uncast_location;
319 vec<tree, va_gc> *arglist = (uncast_arglist
320 ? (vec<tree, va_gc> *) uncast_arglist
321 : &empty);
322 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
323 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
324 tree new_fndecl;
325 switch (code & AARCH64_BUILTIN_CLASS)
326 {
327 case AARCH64_BUILTIN_GENERAL:
328 return aarch64_resolve_overloaded_builtin_general (location, fndecl,
329 uncast_arglist);
330 case AARCH64_BUILTIN_SVE:
331 new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode,
332 arglist);
333 break;
334 }
335 if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node)
336 return new_fndecl;
337 return build_function_call_vec (location, vNULL, new_fndecl, arglist,
338 NULL, fndecl);
339 }
340
341 /* Implement TARGET_CHECK_BUILTIN_CALL. */
342 static bool
aarch64_check_builtin_call(location_t loc,vec<location_t> arg_loc,tree fndecl,tree orig_fndecl,unsigned int nargs,tree * args)343 aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc,
344 tree fndecl, tree orig_fndecl,
345 unsigned int nargs, tree *args)
346 {
347 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
348 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
349 switch (code & AARCH64_BUILTIN_CLASS)
350 {
351 case AARCH64_BUILTIN_GENERAL:
352 return true;
353
354 case AARCH64_BUILTIN_SVE:
355 return aarch64_sve::check_builtin_call (loc, arg_loc, subcode,
356 orig_fndecl, nargs, args);
357 }
358 gcc_unreachable ();
359 }
360
361 /* Implement REGISTER_TARGET_PRAGMAS. */
362
363 void
aarch64_register_pragmas(void)364 aarch64_register_pragmas (void)
365 {
366 /* Update pragma hook to allow parsing #pragma GCC target. */
367 targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
368
369 targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin;
370 targetm.check_builtin_call = aarch64_check_builtin_call;
371
372 c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64);
373 }
374