1 /* Copyright (C) 2007-2025 Free Software Foundation, Inc.
3 This file is part of GCC.
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
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
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/>. */
19 #define IN_TARGET_CODE 1
23 #include "coretypes.h"
25 #include "c-family/c-common.h"
28 #include "c-family/c-pragma.h"
29 #include "stringpool.h"
30 #include "arm-builtins.h"
31 #include "arm-protos.h"
34 arm_resolve_cde_builtin (location_t loc
, tree fndecl
, void *arglist
)
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.
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.
50 This does mean an odd error message, but it's consistent with the rest of
52 if (param_num
!= num_args
)
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
60 tree pattern_type
= TREE_TYPE (TREE_TYPE (fndecl
));
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)
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
77 for (i
= 1; i
< cast_param_end
; i
++)
79 tree this_param
= (*params
)[i
];
80 if (TREE_CODE (this_param
) == ERROR_MARK
)
85 tree param_type
= TREE_TYPE (this_param
);
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
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
98 to_return
= build_qualified_type (param_type
, 0 MEM_STAT_INFO
);
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)
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
);
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
);
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
,
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
);
133 /* Implement "#pragma GCC arm". */
135 arm_pragma_arm (cpp_reader
*)
138 if (pragma_lex (&x
) != CPP_STRING
)
140 error ("%<#pragma GCC arm%> requires a string parameter");
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 if (strcmp (name
, "arm_mve.h") == 0)
149 if (pragma_lex (&x
) == CPP_NAME
)
151 if (strcmp (IDENTIFIER_POINTER (x
), "true") == 0)
152 arm_mve::handle_arm_mve_h (true);
153 else if (strcmp (IDENTIFIER_POINTER (x
), "false") == 0)
154 arm_mve::handle_arm_mve_h (false);
156 error ("%<#pragma GCC arm \"arm_mve.h\"%> requires a boolean parameter");
160 error ("unknown %<#pragma GCC arm%> option %qs", name
);
163 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
165 arm_resolve_overloaded_builtin (location_t loc
, tree fndecl
,
166 void *uncast_arglist
, bool)
168 enum resolver_ident resolver
= arm_describe_resolver (fndecl
);
169 if (resolver
== arm_cde_resolver
)
170 return arm_resolve_cde_builtin (loc
, fndecl
, uncast_arglist
);
171 if (resolver
== arm_mve_resolver
)
173 vec
<tree
, va_gc
> empty
= {};
174 vec
<tree
, va_gc
> *arglist
= (uncast_arglist
175 ? (vec
<tree
, va_gc
> *) uncast_arglist
177 unsigned int code
= DECL_MD_FUNCTION_CODE (fndecl
);
178 unsigned int subcode
= code
>> ARM_BUILTIN_SHIFT
;
179 tree new_fndecl
= arm_mve::resolve_overloaded_builtin (loc
, subcode
, arglist
);
180 if (new_fndecl
== NULL_TREE
|| new_fndecl
== error_mark_node
)
182 return build_function_call_vec (loc
, vNULL
, new_fndecl
, arglist
,
188 /* Output C specific EABI object attributes. These cannot be done in
189 arm.cc because they require information from the C frontend. */
192 arm_output_c_attributes (void)
194 int wchar_size
= (int)(TYPE_PRECISION (wchar_type_node
) / BITS_PER_UNIT
);
195 arm_emit_eabi_attribute ("Tag_ABI_PCS_wchar_t", 18, wchar_size
);
199 /* Setup so that common code calls arm_output_c_attributes. */
202 arm_lang_object_attributes_init (void)
204 arm_lang_output_object_attributes_hook
= arm_output_c_attributes
;
207 #define builtin_define(TXT) cpp_define (pfile, TXT)
208 #define builtin_assert(TXT) cpp_assert (pfile, TXT)
210 /* Define or undefine macros based on the current target. If the user does
211 #pragma GCC target, we need to adjust the macros dynamically. */
214 def_or_undef_macro(struct cpp_reader
* pfile
, const char *name
, bool def_p
)
217 cpp_define (pfile
, name
);
219 cpp_undef (pfile
, name
);
223 arm_cpu_builtins (struct cpp_reader
* pfile
)
225 def_or_undef_macro (pfile
, "__ARM_FEATURE_DSP", TARGET_DSP_MULTIPLY
);
226 def_or_undef_macro (pfile
, "__ARM_FEATURE_QBIT", TARGET_ARM_QBIT
);
227 def_or_undef_macro (pfile
, "__ARM_FEATURE_SAT", TARGET_ARM_SAT
);
228 def_or_undef_macro (pfile
, "__ARM_FEATURE_CRYPTO", TARGET_CRYPTO
);
229 def_or_undef_macro (pfile
, "__ARM_FEATURE_AES", TARGET_CRYPTO
);
230 def_or_undef_macro (pfile
, "__ARM_FEATURE_SHA2", TARGET_CRYPTO
);
232 def_or_undef_macro (pfile
, "__ARM_FEATURE_UNALIGNED", unaligned_access
);
234 def_or_undef_macro (pfile
, "__ARM_FEATURE_QRDMX", TARGET_NEON_RDMA
);
236 def_or_undef_macro (pfile
, "__ARM_FEATURE_CRC32", TARGET_CRC32
);
237 def_or_undef_macro (pfile
, "__ARM_FEATURE_DOTPROD", TARGET_DOTPROD
);
238 def_or_undef_macro (pfile
, "__ARM_FEATURE_COMPLEX", TARGET_COMPLEX
);
239 def_or_undef_macro (pfile
, "__ARM_32BIT_STATE", TARGET_32BIT
);
241 def_or_undef_macro (pfile
, "__ARM_FEATURE_PAUTH", TARGET_HAVE_PACBTI
);
242 def_or_undef_macro (pfile
, "__ARM_FEATURE_BTI", TARGET_HAVE_PACBTI
);
243 def_or_undef_macro (pfile
, "__ARM_FEATURE_BTI_DEFAULT",
244 aarch_enable_bti
== 1);
246 cpp_undef (pfile
, "__ARM_FEATURE_PAC_DEFAULT");
247 if (aarch_ra_sign_scope
!= AARCH_FUNCTION_NONE
)
249 unsigned int pac
= 1;
251 if (aarch_ra_sign_scope
== AARCH_FUNCTION_ALL
)
254 builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", pac
);
257 cpp_undef (pfile
, "__ARM_FEATURE_MVE");
258 if (TARGET_HAVE_MVE
&& TARGET_HAVE_MVE_FLOAT
)
260 builtin_define_with_int_value ("__ARM_FEATURE_MVE", 3);
262 else if (TARGET_HAVE_MVE
)
264 builtin_define_with_int_value ("__ARM_FEATURE_MVE", 1);
267 cpp_undef (pfile
, "__ARM_FEATURE_CMSE");
268 if (arm_arch8
&& !arm_arch_notm
)
270 if (arm_arch_cmse
&& use_cmse
)
271 builtin_define_with_int_value ("__ARM_FEATURE_CMSE", 3);
273 builtin_define ("__ARM_FEATURE_CMSE");
276 cpp_undef (pfile
, "__ARM_FEATURE_LDREX");
277 if (TARGET_ARM_FEATURE_LDREX
)
278 builtin_define_with_int_value ("__ARM_FEATURE_LDREX",
279 TARGET_ARM_FEATURE_LDREX
);
281 /* ACLE says that __ARM_FEATURE_CLZ is defined if the hardware
282 supports it; it's also clear that this doesn't mean the current
283 ISA, so we define this even when compiling for Thumb1 if the
284 target supports CLZ in A32. */
285 def_or_undef_macro (pfile
, "__ARM_FEATURE_CLZ",
286 ((TARGET_ARM_ARCH
>= 5 && arm_arch_notm
)
287 || TARGET_ARM_ARCH_ISA_THUMB
>=2));
289 def_or_undef_macro (pfile
, "__ARM_FEATURE_NUMERIC_MAXMIN",
290 TARGET_ARM_ARCH
>= 8 && TARGET_NEON
&& TARGET_VFP5
);
292 def_or_undef_macro (pfile
, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD
);
294 builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
295 flag_short_enums
? 1 : 4);
296 builtin_define_type_sizeof ("__ARM_SIZEOF_WCHAR_T", wchar_type_node
);
298 cpp_undef (pfile
, "__ARM_ARCH_PROFILE");
299 if (TARGET_ARM_ARCH_PROFILE
)
300 builtin_define_with_int_value ("__ARM_ARCH_PROFILE",
301 TARGET_ARM_ARCH_PROFILE
);
303 /* Define __arm__ even when in thumb mode, for
304 consistency with armcc. */
305 builtin_define ("__arm__");
308 cpp_undef (pfile
, "__ARM_ARCH");
309 builtin_define_with_int_value ("__ARM_ARCH", TARGET_ARM_ARCH
);
312 builtin_define ("__ARM_ARCH_ISA_ARM");
313 builtin_define ("__APCS_32__");
315 def_or_undef_macro (pfile
, "__GCC_ASM_FLAG_OUTPUTS__", !TARGET_THUMB1
);
317 def_or_undef_macro (pfile
, "__thumb__", TARGET_THUMB
);
318 def_or_undef_macro (pfile
, "__thumb2__", TARGET_THUMB2
);
320 def_or_undef_macro (pfile
, "__THUMBEB__", TARGET_THUMB
);
322 def_or_undef_macro (pfile
, "__THUMBEL__", TARGET_THUMB
);
324 cpp_undef (pfile
, "__ARM_ARCH_ISA_THUMB");
325 if (TARGET_ARM_ARCH_ISA_THUMB
)
326 builtin_define_with_int_value ("__ARM_ARCH_ISA_THUMB",
327 TARGET_ARM_ARCH_ISA_THUMB
);
331 builtin_define ("__ARMEB__");
332 builtin_define ("__ARM_BIG_ENDIAN");
336 builtin_define ("__ARMEL__");
339 if (TARGET_SOFT_FLOAT
)
340 builtin_define ("__SOFTFP__");
342 builtin_define ("__VFP_FP__");
344 cpp_undef (pfile
, "__ARM_FP");
346 builtin_define_with_int_value ("__ARM_FP", TARGET_ARM_FP
);
348 def_or_undef_macro (pfile
, "__ARM_FP16_FORMAT_IEEE",
349 arm_fp16_format
== ARM_FP16_FORMAT_IEEE
);
350 def_or_undef_macro (pfile
, "__ARM_FP16_FORMAT_ALTERNATIVE",
351 arm_fp16_format
== ARM_FP16_FORMAT_ALTERNATIVE
);
352 def_or_undef_macro (pfile
, "__ARM_FP16_ARGS",
353 arm_fp16_format
!= ARM_FP16_FORMAT_NONE
);
355 def_or_undef_macro (pfile
, "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC",
356 TARGET_VFP_FP16INST
);
357 def_or_undef_macro (pfile
, "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC",
358 TARGET_NEON_FP16INST
);
359 def_or_undef_macro (pfile
, "__ARM_FEATURE_FP16_FML", TARGET_FP16FML
);
361 def_or_undef_macro (pfile
, "__ARM_FEATURE_FMA", TARGET_FMA
);
362 def_or_undef_macro (pfile
, "__ARM_NEON__", TARGET_NEON
);
363 def_or_undef_macro (pfile
, "__ARM_NEON", TARGET_NEON
);
365 cpp_undef (pfile
, "__ARM_NEON_FP");
367 builtin_define_with_int_value ("__ARM_NEON_FP", TARGET_NEON_FP
);
369 /* Add a define for interworking. Needed when building libgcc.a. */
370 if (arm_cpp_interwork
)
371 builtin_define ("__THUMB_INTERWORK__");
373 builtin_define (arm_arch_name
);
375 builtin_define ("__XSCALE__");
378 builtin_define ("__IWMMXT__");
379 builtin_define ("__ARM_WMMX");
381 if (arm_arch_iwmmxt2
)
382 builtin_define ("__IWMMXT2__");
383 /* ARMv6KZ was originally identified as the misspelled __ARM_ARCH_6ZK__. To
384 preserve the existing behavior, the misspelled feature macro must still be
387 builtin_define ("__ARM_ARCH_6ZK__");
388 if (TARGET_AAPCS_BASED
)
390 if (arm_pcs_default
== ARM_PCS_AAPCS_VFP
)
391 builtin_define ("__ARM_PCS_VFP");
392 else if (arm_pcs_default
== ARM_PCS_AAPCS
)
393 builtin_define ("__ARM_PCS");
394 builtin_define ("__ARM_EABI__");
397 def_or_undef_macro (pfile
, "__FDPIC__", TARGET_FDPIC
);
399 def_or_undef_macro (pfile
, "__ARM_ARCH_EXT_IDIV__", TARGET_IDIV
);
400 def_or_undef_macro (pfile
, "__ARM_FEATURE_IDIV", TARGET_IDIV
);
402 def_or_undef_macro (pfile
, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified
);
404 cpp_undef (pfile
, "__ARM_FEATURE_COPROC");
405 if (TARGET_32BIT
&& arm_arch4
&& !(arm_arch8
&& arm_arch_notm
))
407 int coproc_level
= 0x1;
416 builtin_define_with_int_value ("__ARM_FEATURE_COPROC", coproc_level
);
419 def_or_undef_macro (pfile
, "__ARM_FEATURE_CDE", TARGET_CDE
);
420 cpp_undef (pfile
, "__ARM_FEATURE_CDE_COPROC");
422 builtin_define_with_int_value ("__ARM_FEATURE_CDE_COPROC",
423 arm_arch_cde_coproc
);
425 def_or_undef_macro (pfile
, "__ARM_FEATURE_MATMUL_INT8", TARGET_I8MM
);
426 def_or_undef_macro (pfile
, "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC",
428 def_or_undef_macro (pfile
, "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC",
430 def_or_undef_macro (pfile
, "__ARM_BF16_FORMAT_ALTERNATIVE",
431 TARGET_BF16_FP
|| TARGET_BF16_SIMD
);
435 arm_cpu_cpp_builtins (struct cpp_reader
* pfile
)
437 builtin_assert ("cpu=arm");
438 builtin_assert ("machine=arm");
440 arm_cpu_builtins (pfile
);
443 /* Hook to validate the current #pragma GCC target and set the arch custom
444 mode state. If ARGS is NULL, then POP_TARGET is used to reset
448 arm_pragma_target_parse (tree args
, tree pop_target
)
450 tree prev_tree
= target_option_current_node
;
452 struct cl_target_option
*prev_opt
;
453 struct cl_target_option
*cur_opt
;
457 cur_tree
= ((pop_target
) ? pop_target
: target_option_default_node
);
458 cl_target_option_restore (&global_options
, &global_options_set
,
459 TREE_TARGET_OPTION (cur_tree
));
463 cur_tree
= arm_valid_target_attribute_tree (args
, &global_options
,
464 &global_options_set
);
465 if (cur_tree
== NULL_TREE
)
467 cl_target_option_restore (&global_options
, &global_options_set
,
468 TREE_TARGET_OPTION (prev_tree
));
472 /* handle_pragma_pop_options and handle_pragma_reset_options will set
473 target_option_current_node, but not handle_pragma_target. */
474 target_option_current_node
= cur_tree
;
475 arm_configure_build_target (&arm_active_target
,
476 TREE_TARGET_OPTION (cur_tree
), false);
477 arm_option_reconfigure_globals ();
480 /* Update macros if target_node changes. The global state will be restored
481 by arm_set_current_function. */
482 prev_opt
= TREE_TARGET_OPTION (prev_tree
);
483 cur_opt
= TREE_TARGET_OPTION (cur_tree
);
485 gcc_assert (prev_opt
);
486 gcc_assert (cur_opt
);
488 if (cur_opt
!= prev_opt
)
490 /* For the definitions, ensure all newly defined macros are considered
491 as used for -Wunused-macros. There is no point warning about the
492 compiler predefined macros. */
493 cpp_options
*cpp_opts
= cpp_get_options (parse_in
);
494 unsigned char saved_warn_unused_macros
= cpp_opts
->warn_unused_macros
;
496 cpp_opts
->warn_unused_macros
= 0;
499 gcc_assert (cur_opt
->x_target_flags
== target_flags
);
501 /* Don't warn for macros that have context sensitive values depending on
503 See warn_of_redefinition, reset after cpp_create_definition. */
504 tree acond_macro
= get_identifier ("__ARM_NEON_FP");
505 C_CPP_HASHNODE (acond_macro
)->flags
|= NODE_CONDITIONAL
;
507 acond_macro
= get_identifier ("__ARM_FP");
508 C_CPP_HASHNODE (acond_macro
)->flags
|= NODE_CONDITIONAL
;
510 acond_macro
= get_identifier ("__ARM_FEATURE_LDREX");
511 C_CPP_HASHNODE (acond_macro
)->flags
|= NODE_CONDITIONAL
;
513 cpp_force_token_locations (parse_in
, BUILTINS_LOCATION
);
514 arm_cpu_builtins (parse_in
);
515 cpp_stop_forcing_token_locations (parse_in
);
517 cpp_opts
->warn_unused_macros
= saved_warn_unused_macros
;
519 /* Make sure that target_reinit is called for next function, since
520 TREE_TARGET_OPTION might change with the #pragma even if there is
521 no target attribute attached to the function. */
522 arm_reset_previous_fndecl ();
524 /* If going to the default mode, we restore the initial states.
525 if cur_tree is a new target, states will be saved/restored on a per
526 function basis in arm_set_current_function. */
527 if (cur_tree
== target_option_default_node
)
528 save_restore_target_globals (cur_tree
);
534 /* Register target pragmas. We need to add the hook for parsing #pragma GCC
535 option here rather than in arm.cc since it will pull in various preprocessor
536 functions, and those are not present in languages like fortran without a
540 arm_register_target_pragmas (void)
542 /* Update pragma hook to allow parsing #pragma GCC target. */
543 targetm
.target_option
.pragma_parse
= arm_pragma_target_parse
;
545 targetm
.resolve_overloaded_builtin
= arm_resolve_overloaded_builtin
;
546 targetm
.check_builtin_call
= arm_check_builtin_call
;
548 c_register_pragma ("GCC", "arm", arm_pragma_arm
);
550 #ifdef REGISTER_SUBTARGET_PRAGMAS
551 REGISTER_SUBTARGET_PRAGMAS ();