1 /* Target-specific code for C family languages. 2 Copyright (C) 2015-2020 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 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 66 builtin_define_with_int_value ("__ARM_ARCH_PROFILE", 'A'); 67 builtin_define ("__ARM_FEATURE_CLZ"); 68 builtin_define ("__ARM_FEATURE_IDIV"); 69 builtin_define ("__ARM_FEATURE_UNALIGNED"); 70 builtin_define ("__ARM_PCS_AAPCS64"); 71 builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8); 72 73 builtin_define ("__GCC_ASM_FLAG_OUTPUTS__"); 74 } 75 76 /* Undefine/redefine macros that depend on the current backend state and may 77 need to change when a target pragma modifies the backend state. */ 78 79 static void 80 aarch64_update_cpp_builtins (cpp_reader *pfile) 81 { 82 aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile); 83 84 builtin_define_with_int_value ("__ARM_ARCH", aarch64_architecture_version); 85 86 builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM", 87 flag_short_enums ? 1 : 4); 88 aarch64_def_or_undef (TARGET_BIG_END, "__AARCH64EB__", pfile); 89 aarch64_def_or_undef (TARGET_BIG_END, "__ARM_BIG_ENDIAN", pfile); 90 aarch64_def_or_undef (!TARGET_BIG_END, "__AARCH64EL__", pfile); 91 92 aarch64_def_or_undef (TARGET_FLOAT, "__ARM_FEATURE_FMA", pfile); 93 94 if (TARGET_FLOAT || TARGET_SIMD) 95 { 96 builtin_define_with_int_value ("__ARM_FP", 0x0E); 97 builtin_define ("__ARM_FP16_FORMAT_IEEE"); 98 builtin_define ("__ARM_FP16_ARGS"); 99 } 100 else 101 cpp_undef (pfile, "__ARM_FP"); 102 103 aarch64_def_or_undef (TARGET_FP_F16INST, 104 "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", pfile); 105 aarch64_def_or_undef (TARGET_SIMD_F16INST, 106 "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", pfile); 107 108 aarch64_def_or_undef (TARGET_SIMD, "__ARM_FEATURE_NUMERIC_MAXMIN", pfile); 109 aarch64_def_or_undef (TARGET_SIMD, "__ARM_NEON", pfile); 110 111 112 aarch64_def_or_undef (TARGET_CRC32, "__ARM_FEATURE_CRC32", pfile); 113 aarch64_def_or_undef (TARGET_DOTPROD, "__ARM_FEATURE_DOTPROD", pfile); 114 aarch64_def_or_undef (TARGET_COMPLEX, "__ARM_FEATURE_COMPLEX", pfile); 115 aarch64_def_or_undef (TARGET_JSCVT, "__ARM_FEATURE_JCVT", pfile); 116 117 cpp_undef (pfile, "__AARCH64_CMODEL_TINY__"); 118 cpp_undef (pfile, "__AARCH64_CMODEL_SMALL__"); 119 cpp_undef (pfile, "__AARCH64_CMODEL_LARGE__"); 120 121 switch (aarch64_cmodel) 122 { 123 case AARCH64_CMODEL_TINY: 124 case AARCH64_CMODEL_TINY_PIC: 125 builtin_define ("__AARCH64_CMODEL_TINY__"); 126 break; 127 case AARCH64_CMODEL_SMALL: 128 case AARCH64_CMODEL_SMALL_PIC: 129 builtin_define ("__AARCH64_CMODEL_SMALL__"); 130 break; 131 case AARCH64_CMODEL_LARGE: 132 builtin_define ("__AARCH64_CMODEL_LARGE__"); 133 break; 134 default: 135 break; 136 } 137 138 aarch64_def_or_undef (TARGET_ILP32, "_ILP32", pfile); 139 aarch64_def_or_undef (TARGET_ILP32, "__ILP32__", pfile); 140 141 aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile); 142 aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile); 143 aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE", pfile); 144 cpp_undef (pfile, "__ARM_FEATURE_SVE_BITS"); 145 if (TARGET_SVE) 146 { 147 int bits; 148 if (!BITS_PER_SVE_VECTOR.is_constant (&bits)) 149 bits = 0; 150 builtin_define_with_int_value ("__ARM_FEATURE_SVE_BITS", bits); 151 } 152 aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE_VECTOR_OPERATORS", 153 pfile); 154 aarch64_def_or_undef (TARGET_SVE_I8MM, 155 "__ARM_FEATURE_SVE_MATMUL_INT8", pfile); 156 aarch64_def_or_undef (TARGET_SVE_F32MM, 157 "__ARM_FEATURE_SVE_MATMUL_FP32", pfile); 158 aarch64_def_or_undef (TARGET_SVE_F64MM, 159 "__ARM_FEATURE_SVE_MATMUL_FP64", pfile); 160 aarch64_def_or_undef (TARGET_SVE2, "__ARM_FEATURE_SVE2", pfile); 161 aarch64_def_or_undef (TARGET_SVE2_AES, "__ARM_FEATURE_SVE2_AES", pfile); 162 aarch64_def_or_undef (TARGET_SVE2_BITPERM, 163 "__ARM_FEATURE_SVE2_BITPERM", pfile); 164 aarch64_def_or_undef (TARGET_SVE2_SHA3, "__ARM_FEATURE_SVE2_SHA3", pfile); 165 aarch64_def_or_undef (TARGET_SVE2_SM4, "__ARM_FEATURE_SVE2_SM4", pfile); 166 167 aarch64_def_or_undef (TARGET_LSE, "__ARM_FEATURE_ATOMICS", pfile); 168 aarch64_def_or_undef (TARGET_AES, "__ARM_FEATURE_AES", pfile); 169 aarch64_def_or_undef (TARGET_SHA2, "__ARM_FEATURE_SHA2", pfile); 170 aarch64_def_or_undef (TARGET_SHA3, "__ARM_FEATURE_SHA3", pfile); 171 aarch64_def_or_undef (TARGET_SHA3, "__ARM_FEATURE_SHA512", pfile); 172 aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM3", pfile); 173 aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM4", pfile); 174 aarch64_def_or_undef (TARGET_F16FML, "__ARM_FEATURE_FP16_FML", pfile); 175 176 aarch64_def_or_undef (TARGET_FRINT, "__ARM_FEATURE_FRINT", pfile); 177 aarch64_def_or_undef (TARGET_TME, "__ARM_FEATURE_TME", pfile); 178 aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile); 179 aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile); 180 181 aarch64_def_or_undef (aarch64_bti_enabled (), 182 "__ARM_FEATURE_BTI_DEFAULT", pfile); 183 184 cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT"); 185 if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE) 186 { 187 int v = 0; 188 if (aarch64_ra_sign_key == AARCH64_KEY_A) 189 v |= 1; 190 if (aarch64_ra_sign_key == AARCH64_KEY_B) 191 v |= 2; 192 if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL) 193 v |= 4; 194 builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v); 195 } 196 197 aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile); 198 aarch64_def_or_undef (TARGET_BF16_SIMD, 199 "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile); 200 aarch64_def_or_undef (TARGET_BF16_FP, 201 "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); 202 203 /* Not for ACLE, but required to keep "float.h" correct if we switch 204 target between implementations that do or do not support ARMv8.2-A 205 16-bit floating-point extensions. */ 206 cpp_undef (pfile, "__FLT_EVAL_METHOD__"); 207 builtin_define_with_int_value ("__FLT_EVAL_METHOD__", 208 c_flt_eval_method (true)); 209 cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__"); 210 builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__", 211 c_flt_eval_method (false)); 212 } 213 214 /* Implement TARGET_CPU_CPP_BUILTINS. */ 215 216 void 217 aarch64_cpu_cpp_builtins (cpp_reader *pfile) 218 { 219 aarch64_define_unconditional_macros (pfile); 220 aarch64_update_cpp_builtins (pfile); 221 } 222 223 /* Hook to validate the current #pragma GCC target and set the state, and 224 update the macros based on what was changed. If ARGS is NULL, then 225 POP_TARGET is used to reset the options. */ 226 227 static bool 228 aarch64_pragma_target_parse (tree args, tree pop_target) 229 { 230 /* If args is not NULL then process it and setup the target-specific 231 information that it specifies. */ 232 if (args) 233 { 234 if (!aarch64_process_target_attr (args)) 235 return false; 236 237 aarch64_override_options_internal (&global_options); 238 } 239 240 /* args is NULL, restore to the state described in pop_target. */ 241 else 242 { 243 pop_target = pop_target ? pop_target : target_option_default_node; 244 cl_target_option_restore (&global_options, 245 TREE_TARGET_OPTION (pop_target)); 246 } 247 248 target_option_current_node 249 = build_target_option_node (&global_options); 250 251 aarch64_reset_previous_fndecl (); 252 /* For the definitions, ensure all newly defined macros are considered 253 as used for -Wunused-macros. There is no point warning about the 254 compiler predefined macros. */ 255 cpp_options *cpp_opts = cpp_get_options (parse_in); 256 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros; 257 cpp_opts->warn_unused_macros = 0; 258 259 aarch64_update_cpp_builtins (parse_in); 260 261 cpp_opts->warn_unused_macros = saved_warn_unused_macros; 262 263 /* If we're popping or reseting make sure to update the globals so that 264 the optab availability predicates get recomputed. */ 265 if (pop_target) 266 aarch64_save_restore_target_globals (pop_target); 267 268 /* Initialize SIMD builtins if we haven't already. 269 Set current_target_pragma to NULL for the duration so that 270 the builtin initialization code doesn't try to tag the functions 271 being built with the attributes specified by any current pragma, thus 272 going into an infinite recursion. */ 273 if (TARGET_SIMD) 274 { 275 tree saved_current_target_pragma = current_target_pragma; 276 current_target_pragma = NULL; 277 aarch64_init_simd_builtins (); 278 current_target_pragma = saved_current_target_pragma; 279 } 280 281 return true; 282 } 283 284 /* Implement "#pragma GCC aarch64". */ 285 static void 286 aarch64_pragma_aarch64 (cpp_reader *) 287 { 288 tree x; 289 if (pragma_lex (&x) != CPP_STRING) 290 { 291 error ("%<#pragma GCC aarch64%> requires a string parameter"); 292 return; 293 } 294 295 const char *name = TREE_STRING_POINTER (x); 296 if (strcmp (name, "arm_sve.h") == 0) 297 aarch64_sve::handle_arm_sve_h (); 298 else 299 error ("unknown %<#pragma GCC aarch64%> option %qs", name); 300 } 301 302 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */ 303 static tree 304 aarch64_resolve_overloaded_builtin (unsigned int uncast_location, 305 tree fndecl, void *uncast_arglist) 306 { 307 vec<tree, va_gc> empty = {}; 308 location_t location = (location_t) uncast_location; 309 vec<tree, va_gc> *arglist = (uncast_arglist 310 ? (vec<tree, va_gc> *) uncast_arglist 311 : &empty); 312 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 313 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 314 tree new_fndecl; 315 switch (code & AARCH64_BUILTIN_CLASS) 316 { 317 case AARCH64_BUILTIN_GENERAL: 318 return aarch64_resolve_overloaded_builtin_general (location, fndecl, 319 uncast_arglist); 320 case AARCH64_BUILTIN_SVE: 321 new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode, 322 arglist); 323 break; 324 } 325 if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node) 326 return new_fndecl; 327 return build_function_call_vec (location, vNULL, new_fndecl, arglist, 328 NULL, fndecl); 329 } 330 331 /* Implement TARGET_CHECK_BUILTIN_CALL. */ 332 static bool 333 aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc, 334 tree fndecl, tree orig_fndecl, 335 unsigned int nargs, tree *args) 336 { 337 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 338 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 339 switch (code & AARCH64_BUILTIN_CLASS) 340 { 341 case AARCH64_BUILTIN_GENERAL: 342 return true; 343 344 case AARCH64_BUILTIN_SVE: 345 return aarch64_sve::check_builtin_call (loc, arg_loc, subcode, 346 orig_fndecl, nargs, args); 347 } 348 gcc_unreachable (); 349 } 350 351 /* Implement REGISTER_TARGET_PRAGMAS. */ 352 353 void 354 aarch64_register_pragmas (void) 355 { 356 /* Update pragma hook to allow parsing #pragma GCC target. */ 357 targetm.target_option.pragma_parse = aarch64_pragma_target_parse; 358 359 targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin; 360 targetm.check_builtin_call = aarch64_check_builtin_call; 361 362 c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64); 363 } 364