1 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
2
3 This file is part of GCC.
4
5 GCC is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
8 version.
9
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GCC; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
18
19 #define IN_TARGET_CODE 1
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "c-family/c-common.h"
26 #include "memmodel.h"
27 #include "tm_p.h"
28 #include "c-family/c-pragma.h"
29 #include "stringpool.h"
30 #include "arm-builtins.h"
31 #include "arm-protos.h"
32
33 tree
arm_resolve_cde_builtin(location_t loc,tree fndecl,void * arglist)34 arm_resolve_cde_builtin (location_t loc, tree fndecl, void *arglist)
35 {
36 vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (arglist);
37 unsigned param_num = params ? params->length() : 0;
38 unsigned num_args = list_length (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) - 1;
39 /* Ensure this function has the correct number of arguments.
40 This won't happen when using the intrinsics defined by the ACLE, since
41 they're exposed to the user via a wrapper in the arm_cde.h header that has
42 the correct number of arguments ... hence the compiler would already catch
43 an incorrect number of arguments there.
44
45 It is still possible to get here if the user tries to call the __bulitin_*
46 functions directly. We could print some error message in this function,
47 but instead we leave it to the rest of the code to catch this problem in
48 the same way that other __builtin_* functions catch it.
49
50 This does mean an odd error message, but it's consistent with the rest of
51 the builtins. */
52 if (param_num != num_args)
53 return NULL_TREE;
54
55 tree to_return = NULL_TREE;
56 /* Take the functions return type since that's the same type as the arguments
57 this function needs (the types of the builtin function all come from the
58 machine mode of the RTL pattern, and they're all the same and calculated
59 in the same way). */
60 tree pattern_type = TREE_TYPE (TREE_TYPE (fndecl));
61
62 unsigned i;
63 /* Hard coding the number of parameters we don't want to cast at the end of
64 the builtin. This is the easiest approach for the CDE intrinsics, and
65 introducing a parameter to store in the builtins.def macros seems overkill
66 when they're only relevant here. */
67 unsigned end_args = arm_cde_end_args (fndecl);
68 unsigned cast_param_end = param_num - end_args;
69 /* For the vcx1q patterns that don't need any casts. */
70 if (cast_param_end == 1)
71 return NULL_TREE;
72
73 /* In order to check all arguments rather than complaining on the first
74 invalid one we record whether *any* arguments are invalid using this
75 boolean variable. */
76 bool invalid = false;
77 for (i = 1; i < cast_param_end; i++)
78 {
79 tree this_param = (*params)[i];
80 if (TREE_CODE (this_param) == ERROR_MARK)
81 {
82 invalid = true;
83 continue;
84 }
85 tree param_type = TREE_TYPE (this_param);
86
87 /* Return value is cast to type that second argument originally was.
88 All non-constant arguments are cast to the return type calculated from
89 the RTL pattern.
90
91 Set the return type to an unqualified version of the type of the first
92 parameter. The first parameter since that is how the intrinsics are
93 defined -- to always return the same type as the first polymorphic
94 argument. Unqualified version of the type since we don't want passing
95 a constant parameter to mean that the return value of the builtin is
96 also constant. */
97 if (i == 1)
98 to_return = build_qualified_type (param_type, 0 MEM_STAT_INFO);
99
100 /* The only requirement of these intrinsics on the type of the variable
101 is that it's 128 bits wide. All other types are valid and we simply
102 VIEW_CONVERT_EXPR them to the type of the underlying builtin. */
103 tree type_size = TYPE_SIZE (param_type);
104 if (! tree_fits_shwi_p (type_size)
105 || tree_to_shwi (type_size) != 128)
106 {
107 error_at (loc,
108 "argument %u to function %qE is of type %qT which is not "
109 "known to be 128 bits wide",
110 i + 1, fndecl, param_type);
111 invalid = true;
112 continue;
113 }
114
115 /* Only convert the argument if we actually need to. */
116 if (! check_base_type (pattern_type, param_type))
117 (*params)[i] = build1 (VIEW_CONVERT_EXPR, pattern_type, this_param);
118 }
119 if (invalid)
120 return NULL_TREE;
121
122 /* We know it's safe to call this since this builtin is here to implement an
123 ACLE function, and those functions are only for C/C++. */
124 tree call_expr = build_function_call_vec (loc, vNULL, fndecl, params,
125 NULL, fndecl);
126
127 gcc_assert (to_return != NULL_TREE);
128 if (! check_base_type (to_return, pattern_type))
129 return build1 (VIEW_CONVERT_EXPR, to_return, call_expr);
130 return call_expr;
131 }
132
133 /* Implement "#pragma GCC arm". */
134 static void
arm_pragma_arm(cpp_reader *)135 arm_pragma_arm (cpp_reader *)
136 {
137 tree x;
138 if (pragma_lex (&x) != CPP_STRING)
139 {
140 error ("%<#pragma GCC arm%> requires a string parameter");
141 return;
142 }
143
144 const char *name = TREE_STRING_POINTER (x);
145 if (strcmp (name, "arm_mve_types.h") == 0)
146 arm_mve::handle_arm_mve_types_h ();
147 else
148 error ("unknown %<#pragma GCC arm%> option %qs", name);
149 }
150
151 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. This is currently only
152 used for the MVE related builtins for the CDE extension.
153 Here we ensure the type of arguments is such that the size is correct, and
154 then return a tree that describes the same function call but with the
155 relevant types cast as necessary. */
156 tree
arm_resolve_overloaded_builtin(location_t loc,tree fndecl,void * arglist)157 arm_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
158 {
159 if (arm_describe_resolver (fndecl) == arm_cde_resolver)
160 return arm_resolve_cde_builtin (loc, fndecl, arglist);
161 return NULL_TREE;
162 }
163
164 /* Output C specific EABI object attributes. These cannot be done in
165 arm.cc because they require information from the C frontend. */
166
167 static void
arm_output_c_attributes(void)168 arm_output_c_attributes (void)
169 {
170 int wchar_size = (int)(TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT);
171 arm_emit_eabi_attribute ("Tag_ABI_PCS_wchar_t", 18, wchar_size);
172 }
173
174
175 /* Setup so that common code calls arm_output_c_attributes. */
176
177 void
arm_lang_object_attributes_init(void)178 arm_lang_object_attributes_init (void)
179 {
180 arm_lang_output_object_attributes_hook = arm_output_c_attributes;
181 }
182
183 #define builtin_define(TXT) cpp_define (pfile, TXT)
184 #define builtin_assert(TXT) cpp_assert (pfile, TXT)
185
186 /* Define or undefine macros based on the current target. If the user does
187 #pragma GCC target, we need to adjust the macros dynamically. */
188
189 static void
def_or_undef_macro(struct cpp_reader * pfile,const char * name,bool def_p)190 def_or_undef_macro(struct cpp_reader* pfile, const char *name, bool def_p)
191 {
192 if (def_p)
193 cpp_define (pfile, name);
194 else
195 cpp_undef (pfile, name);
196 }
197
198 static void
arm_cpu_builtins(struct cpp_reader * pfile)199 arm_cpu_builtins (struct cpp_reader* pfile)
200 {
201 def_or_undef_macro (pfile, "__ARM_FEATURE_DSP", TARGET_DSP_MULTIPLY);
202 def_or_undef_macro (pfile, "__ARM_FEATURE_QBIT", TARGET_ARM_QBIT);
203 def_or_undef_macro (pfile, "__ARM_FEATURE_SAT", TARGET_ARM_SAT);
204 def_or_undef_macro (pfile, "__ARM_FEATURE_CRYPTO", TARGET_CRYPTO);
205
206 def_or_undef_macro (pfile, "__ARM_FEATURE_UNALIGNED", unaligned_access);
207
208 def_or_undef_macro (pfile, "__ARM_FEATURE_QRDMX", TARGET_NEON_RDMA);
209
210 def_or_undef_macro (pfile, "__ARM_FEATURE_CRC32", TARGET_CRC32);
211 def_or_undef_macro (pfile, "__ARM_FEATURE_DOTPROD", TARGET_DOTPROD);
212 def_or_undef_macro (pfile, "__ARM_FEATURE_COMPLEX", TARGET_COMPLEX);
213 def_or_undef_macro (pfile, "__ARM_32BIT_STATE", TARGET_32BIT);
214
215 cpp_undef (pfile, "__ARM_FEATURE_MVE");
216 if (TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT)
217 {
218 builtin_define_with_int_value ("__ARM_FEATURE_MVE", 3);
219 }
220 else if (TARGET_HAVE_MVE)
221 {
222 builtin_define_with_int_value ("__ARM_FEATURE_MVE", 1);
223 }
224
225 cpp_undef (pfile, "__ARM_FEATURE_CMSE");
226 if (arm_arch8 && !arm_arch_notm)
227 {
228 if (arm_arch_cmse && use_cmse)
229 builtin_define_with_int_value ("__ARM_FEATURE_CMSE", 3);
230 else
231 builtin_define ("__ARM_FEATURE_CMSE");
232 }
233
234 cpp_undef (pfile, "__ARM_FEATURE_LDREX");
235 if (TARGET_ARM_FEATURE_LDREX)
236 builtin_define_with_int_value ("__ARM_FEATURE_LDREX",
237 TARGET_ARM_FEATURE_LDREX);
238
239 def_or_undef_macro (pfile, "__ARM_FEATURE_CLZ",
240 ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB)
241 || TARGET_ARM_ARCH_ISA_THUMB >=2));
242
243 def_or_undef_macro (pfile, "__ARM_FEATURE_NUMERIC_MAXMIN",
244 TARGET_ARM_ARCH >= 8 && TARGET_NEON && TARGET_VFP5);
245
246 def_or_undef_macro (pfile, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD);
247
248 builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
249 flag_short_enums ? 1 : 4);
250 builtin_define_type_sizeof ("__ARM_SIZEOF_WCHAR_T", wchar_type_node);
251
252 cpp_undef (pfile, "__ARM_ARCH_PROFILE");
253 if (TARGET_ARM_ARCH_PROFILE)
254 builtin_define_with_int_value ("__ARM_ARCH_PROFILE",
255 TARGET_ARM_ARCH_PROFILE);
256
257 /* Define __arm__ even when in thumb mode, for
258 consistency with armcc. */
259 builtin_define ("__arm__");
260 if (TARGET_ARM_ARCH)
261 {
262 cpp_undef (pfile, "__ARM_ARCH");
263 builtin_define_with_int_value ("__ARM_ARCH", TARGET_ARM_ARCH);
264 }
265 if (arm_arch_notm)
266 builtin_define ("__ARM_ARCH_ISA_ARM");
267 builtin_define ("__APCS_32__");
268
269 def_or_undef_macro (pfile, "__GCC_ASM_FLAG_OUTPUTS__", !TARGET_THUMB1);
270
271 def_or_undef_macro (pfile, "__thumb__", TARGET_THUMB);
272 def_or_undef_macro (pfile, "__thumb2__", TARGET_THUMB2);
273 if (TARGET_BIG_END)
274 def_or_undef_macro (pfile, "__THUMBEB__", TARGET_THUMB);
275 else
276 def_or_undef_macro (pfile, "__THUMBEL__", TARGET_THUMB);
277
278 cpp_undef (pfile, "__ARM_ARCH_ISA_THUMB");
279 if (TARGET_ARM_ARCH_ISA_THUMB)
280 builtin_define_with_int_value ("__ARM_ARCH_ISA_THUMB",
281 TARGET_ARM_ARCH_ISA_THUMB);
282
283 if (TARGET_BIG_END)
284 {
285 builtin_define ("__ARMEB__");
286 builtin_define ("__ARM_BIG_ENDIAN");
287 }
288 else
289 {
290 builtin_define ("__ARMEL__");
291 }
292
293 if (TARGET_SOFT_FLOAT)
294 builtin_define ("__SOFTFP__");
295
296 builtin_define ("__VFP_FP__");
297
298 cpp_undef (pfile, "__ARM_FP");
299 if (TARGET_ARM_FP)
300 builtin_define_with_int_value ("__ARM_FP", TARGET_ARM_FP);
301
302 def_or_undef_macro (pfile, "__ARM_FP16_FORMAT_IEEE",
303 arm_fp16_format == ARM_FP16_FORMAT_IEEE);
304 def_or_undef_macro (pfile, "__ARM_FP16_FORMAT_ALTERNATIVE",
305 arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE);
306 def_or_undef_macro (pfile, "__ARM_FP16_ARGS",
307 arm_fp16_format != ARM_FP16_FORMAT_NONE);
308
309 def_or_undef_macro (pfile, "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC",
310 TARGET_VFP_FP16INST);
311 def_or_undef_macro (pfile, "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC",
312 TARGET_NEON_FP16INST);
313 def_or_undef_macro (pfile, "__ARM_FEATURE_FP16_FML", TARGET_FP16FML);
314
315 def_or_undef_macro (pfile, "__ARM_FEATURE_FMA", TARGET_FMA);
316 def_or_undef_macro (pfile, "__ARM_NEON__", TARGET_NEON);
317 def_or_undef_macro (pfile, "__ARM_NEON", TARGET_NEON);
318
319 cpp_undef (pfile, "__ARM_NEON_FP");
320 if (TARGET_NEON_FP)
321 builtin_define_with_int_value ("__ARM_NEON_FP", TARGET_NEON_FP);
322
323 /* Add a define for interworking. Needed when building libgcc.a. */
324 if (arm_cpp_interwork)
325 builtin_define ("__THUMB_INTERWORK__");
326
327 builtin_define (arm_arch_name);
328 if (arm_arch_xscale)
329 builtin_define ("__XSCALE__");
330 if (arm_arch_iwmmxt)
331 {
332 builtin_define ("__IWMMXT__");
333 builtin_define ("__ARM_WMMX");
334 }
335 if (arm_arch_iwmmxt2)
336 builtin_define ("__IWMMXT2__");
337 /* ARMv6KZ was originally identified as the misspelled __ARM_ARCH_6ZK__. To
338 preserve the existing behavior, the misspelled feature macro must still be
339 defined. */
340 if (arm_arch6kz)
341 builtin_define ("__ARM_ARCH_6ZK__");
342 if (TARGET_AAPCS_BASED)
343 {
344 if (arm_pcs_default == ARM_PCS_AAPCS_VFP)
345 builtin_define ("__ARM_PCS_VFP");
346 else if (arm_pcs_default == ARM_PCS_AAPCS)
347 builtin_define ("__ARM_PCS");
348 builtin_define ("__ARM_EABI__");
349 }
350
351 def_or_undef_macro (pfile, "__FDPIC__", TARGET_FDPIC);
352
353 def_or_undef_macro (pfile, "__ARM_ARCH_EXT_IDIV__", TARGET_IDIV);
354 def_or_undef_macro (pfile, "__ARM_FEATURE_IDIV", TARGET_IDIV);
355
356 def_or_undef_macro (pfile, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified);
357
358 cpp_undef (pfile, "__ARM_FEATURE_COPROC");
359 if (TARGET_32BIT && arm_arch4 && !(arm_arch8 && arm_arch_notm))
360 {
361 int coproc_level = 0x1;
362
363 if (arm_arch5t)
364 coproc_level |= 0x2;
365 if (arm_arch5te)
366 coproc_level |= 0x4;
367 if (arm_arch6)
368 coproc_level |= 0x8;
369
370 builtin_define_with_int_value ("__ARM_FEATURE_COPROC", coproc_level);
371 }
372
373 def_or_undef_macro (pfile, "__ARM_FEATURE_CDE", TARGET_CDE);
374 cpp_undef (pfile, "__ARM_FEATURE_CDE_COPROC");
375 if (TARGET_CDE)
376 builtin_define_with_int_value ("__ARM_FEATURE_CDE_COPROC",
377 arm_arch_cde_coproc);
378
379 def_or_undef_macro (pfile, "__ARM_FEATURE_MATMUL_INT8", TARGET_I8MM);
380 def_or_undef_macro (pfile, "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC",
381 TARGET_BF16_FP);
382 def_or_undef_macro (pfile, "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC",
383 TARGET_BF16_SIMD);
384 def_or_undef_macro (pfile, "__ARM_BF16_FORMAT_ALTERNATIVE",
385 TARGET_BF16_FP || TARGET_BF16_SIMD);
386 }
387
388 void
arm_cpu_cpp_builtins(struct cpp_reader * pfile)389 arm_cpu_cpp_builtins (struct cpp_reader * pfile)
390 {
391 builtin_assert ("cpu=arm");
392 builtin_assert ("machine=arm");
393
394 arm_cpu_builtins (pfile);
395 }
396
397 /* Hook to validate the current #pragma GCC target and set the arch custom
398 mode state. If ARGS is NULL, then POP_TARGET is used to reset
399 the options. */
400
401 static bool
arm_pragma_target_parse(tree args,tree pop_target)402 arm_pragma_target_parse (tree args, tree pop_target)
403 {
404 tree prev_tree = target_option_current_node;
405 tree cur_tree;
406 struct cl_target_option *prev_opt;
407 struct cl_target_option *cur_opt;
408
409 if (! args)
410 {
411 cur_tree = ((pop_target) ? pop_target : target_option_default_node);
412 cl_target_option_restore (&global_options, &global_options_set,
413 TREE_TARGET_OPTION (cur_tree));
414 }
415 else
416 {
417 cur_tree = arm_valid_target_attribute_tree (args, &global_options,
418 &global_options_set);
419 if (cur_tree == NULL_TREE)
420 {
421 cl_target_option_restore (&global_options, &global_options_set,
422 TREE_TARGET_OPTION (prev_tree));
423 return false;
424 }
425
426 /* handle_pragma_pop_options and handle_pragma_reset_options will set
427 target_option_current_node, but not handle_pragma_target. */
428 target_option_current_node = cur_tree;
429 arm_configure_build_target (&arm_active_target,
430 TREE_TARGET_OPTION (cur_tree), false);
431 arm_option_reconfigure_globals ();
432 }
433
434 /* Update macros if target_node changes. The global state will be restored
435 by arm_set_current_function. */
436 prev_opt = TREE_TARGET_OPTION (prev_tree);
437 cur_opt = TREE_TARGET_OPTION (cur_tree);
438
439 gcc_assert (prev_opt);
440 gcc_assert (cur_opt);
441
442 if (cur_opt != prev_opt)
443 {
444 /* For the definitions, ensure all newly defined macros are considered
445 as used for -Wunused-macros. There is no point warning about the
446 compiler predefined macros. */
447 cpp_options *cpp_opts = cpp_get_options (parse_in);
448 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
449
450 cpp_opts->warn_unused_macros = 0;
451
452 /* Update macros. */
453 gcc_assert (cur_opt->x_target_flags == target_flags);
454
455 /* Don't warn for macros that have context sensitive values depending on
456 other attributes.
457 See warn_of_redefinition, reset after cpp_create_definition. */
458 tree acond_macro = get_identifier ("__ARM_NEON_FP");
459 C_CPP_HASHNODE (acond_macro)->flags |= NODE_CONDITIONAL ;
460
461 acond_macro = get_identifier ("__ARM_FP");
462 C_CPP_HASHNODE (acond_macro)->flags |= NODE_CONDITIONAL;
463
464 acond_macro = get_identifier ("__ARM_FEATURE_LDREX");
465 C_CPP_HASHNODE (acond_macro)->flags |= NODE_CONDITIONAL;
466
467 cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
468 arm_cpu_builtins (parse_in);
469 cpp_stop_forcing_token_locations (parse_in);
470
471 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
472
473 /* Make sure that target_reinit is called for next function, since
474 TREE_TARGET_OPTION might change with the #pragma even if there is
475 no target attribute attached to the function. */
476 arm_reset_previous_fndecl ();
477
478 /* If going to the default mode, we restore the initial states.
479 if cur_tree is a new target, states will be saved/restored on a per
480 function basis in arm_set_current_function. */
481 if (cur_tree == target_option_default_node)
482 save_restore_target_globals (cur_tree);
483 }
484
485 return true;
486 }
487
488 /* Register target pragmas. We need to add the hook for parsing #pragma GCC
489 option here rather than in arm.cc since it will pull in various preprocessor
490 functions, and those are not present in languages like fortran without a
491 preprocessor. */
492
493 void
arm_register_target_pragmas(void)494 arm_register_target_pragmas (void)
495 {
496 /* Update pragma hook to allow parsing #pragma GCC target. */
497 targetm.target_option.pragma_parse = arm_pragma_target_parse;
498 targetm.resolve_overloaded_builtin = arm_resolve_overloaded_builtin;
499
500 c_register_pragma ("GCC", "arm", arm_pragma_arm);
501
502 #ifdef REGISTER_SUBTARGET_PRAGMAS
503 REGISTER_SUBTARGET_PRAGMAS ();
504 #endif
505 }
506