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
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", '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
aarch64_update_cpp_builtins(cpp_reader * pfile)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   aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile);
203 
204   /* Not for ACLE, but required to keep "float.h" correct if we switch
205      target between implementations that do or do not support ARMv8.2-A
206      16-bit floating-point extensions.  */
207   cpp_undef (pfile, "__FLT_EVAL_METHOD__");
208   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
209 				 c_flt_eval_method (true));
210   cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
211   builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
212 				 c_flt_eval_method (false));
213 }
214 
215 /* Implement TARGET_CPU_CPP_BUILTINS.  */
216 
217 void
aarch64_cpu_cpp_builtins(cpp_reader * pfile)218 aarch64_cpu_cpp_builtins (cpp_reader *pfile)
219 {
220   aarch64_define_unconditional_macros (pfile);
221   aarch64_update_cpp_builtins (pfile);
222 }
223 
224 /* Hook to validate the current #pragma GCC target and set the state, and
225    update the macros based on what was changed.  If ARGS is NULL, then
226    POP_TARGET is used to reset the options.  */
227 
228 static bool
aarch64_pragma_target_parse(tree args,tree pop_target)229 aarch64_pragma_target_parse (tree args, tree pop_target)
230 {
231   /* If args is not NULL then process it and setup the target-specific
232      information that it specifies.  */
233   if (args)
234     {
235       if (!aarch64_process_target_attr (args))
236 	return false;
237 
238       aarch64_override_options_internal (&global_options);
239     }
240 
241   /* args is NULL, restore to the state described in pop_target.  */
242   else
243     {
244       pop_target = pop_target ? pop_target : target_option_default_node;
245       cl_target_option_restore (&global_options,
246 				TREE_TARGET_OPTION (pop_target));
247     }
248 
249   target_option_current_node
250     = build_target_option_node (&global_options);
251 
252   aarch64_reset_previous_fndecl ();
253   /* For the definitions, ensure all newly defined macros are considered
254      as used for -Wunused-macros.  There is no point warning about the
255      compiler predefined macros.  */
256   cpp_options *cpp_opts = cpp_get_options (parse_in);
257   unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
258   cpp_opts->warn_unused_macros = 0;
259 
260   aarch64_update_cpp_builtins (parse_in);
261 
262   cpp_opts->warn_unused_macros = saved_warn_unused_macros;
263 
264   /* If we're popping or reseting make sure to update the globals so that
265      the optab availability predicates get recomputed.  */
266   if (pop_target)
267     aarch64_save_restore_target_globals (pop_target);
268 
269   /* Initialize SIMD builtins if we haven't already.
270      Set current_target_pragma to NULL for the duration so that
271      the builtin initialization code doesn't try to tag the functions
272      being built with the attributes specified by any current pragma, thus
273      going into an infinite recursion.  */
274   if (TARGET_SIMD)
275     {
276       tree saved_current_target_pragma = current_target_pragma;
277       current_target_pragma = NULL;
278       aarch64_init_simd_builtins ();
279       current_target_pragma = saved_current_target_pragma;
280     }
281 
282   return true;
283 }
284 
285 /* Implement "#pragma GCC aarch64".  */
286 static void
aarch64_pragma_aarch64(cpp_reader *)287 aarch64_pragma_aarch64 (cpp_reader *)
288 {
289   tree x;
290   if (pragma_lex (&x) != CPP_STRING)
291     {
292       error ("%<#pragma GCC aarch64%> requires a string parameter");
293       return;
294     }
295 
296   const char *name = TREE_STRING_POINTER (x);
297   if (strcmp (name, "arm_sve.h") == 0)
298     aarch64_sve::handle_arm_sve_h ();
299   else
300     error ("unknown %<#pragma GCC aarch64%> option %qs", name);
301 }
302 
303 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN.  */
304 static tree
aarch64_resolve_overloaded_builtin(unsigned int uncast_location,tree fndecl,void * uncast_arglist)305 aarch64_resolve_overloaded_builtin (unsigned int uncast_location,
306 				    tree fndecl, void *uncast_arglist)
307 {
308   vec<tree, va_gc> empty = {};
309   location_t location = (location_t) uncast_location;
310   vec<tree, va_gc> *arglist = (uncast_arglist
311 			       ? (vec<tree, va_gc> *) uncast_arglist
312 			       : &empty);
313   unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
314   unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
315   tree new_fndecl;
316   switch (code & AARCH64_BUILTIN_CLASS)
317     {
318     case AARCH64_BUILTIN_GENERAL:
319       return aarch64_resolve_overloaded_builtin_general (location, fndecl,
320 							 uncast_arglist);
321     case AARCH64_BUILTIN_SVE:
322       new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode,
323 							    arglist);
324       break;
325     }
326   if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node)
327     return new_fndecl;
328   return build_function_call_vec (location, vNULL, new_fndecl, arglist,
329 				  NULL, fndecl);
330 }
331 
332 /* Implement TARGET_CHECK_BUILTIN_CALL.  */
333 static bool
aarch64_check_builtin_call(location_t loc,vec<location_t> arg_loc,tree fndecl,tree orig_fndecl,unsigned int nargs,tree * args)334 aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc,
335 			    tree fndecl, tree orig_fndecl,
336 			    unsigned int nargs, tree *args)
337 {
338   unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
339   unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
340   switch (code & AARCH64_BUILTIN_CLASS)
341     {
342     case AARCH64_BUILTIN_GENERAL:
343       return true;
344 
345     case AARCH64_BUILTIN_SVE:
346       return aarch64_sve::check_builtin_call (loc, arg_loc, subcode,
347 					      orig_fndecl, nargs, args);
348     }
349   gcc_unreachable ();
350 }
351 
352 /* Implement REGISTER_TARGET_PRAGMAS.  */
353 
354 void
aarch64_register_pragmas(void)355 aarch64_register_pragmas (void)
356 {
357   /* Update pragma hook to allow parsing #pragma GCC target.  */
358   targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
359 
360   targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin;
361   targetm.check_builtin_call = aarch64_check_builtin_call;
362 
363   c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64);
364 }
365