1 /* RISC-V-specific code for C family languages.
2 Copyright (C) 2011-2025 Free Software Foundation, Inc.
3 Contributed by Andrew Waterman (andrew@sifive.com).
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define IN_TARGET_CODE 1
23 #define INCLUDE_STRING
26 #include "coretypes.h"
28 #include "c-family/c-common.h"
30 #include "c-family/c-pragma.h"
33 #include "riscv-subset.h"
35 #define builtin_define(TXT) cpp_define (pfile, TXT)
37 struct pragma_intrinsic_flags
39 int intrinsic_target_flags
;
41 int intrinsic_riscv_vector_elen_flags
;
42 int intrinsic_riscv_zvl_flags
;
43 int intrinsic_riscv_zvb_subext
;
44 int intrinsic_riscv_zvk_subext
;
48 riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags
*flags
)
50 flags
->intrinsic_target_flags
= target_flags
;
51 flags
->intrinsic_riscv_vector_elen_flags
= riscv_vector_elen_flags
;
52 flags
->intrinsic_riscv_zvl_flags
= riscv_zvl_flags
;
53 flags
->intrinsic_riscv_zvb_subext
= riscv_zvb_subext
;
54 flags
->intrinsic_riscv_zvk_subext
= riscv_zvk_subext
;
56 target_flags
= target_flags
59 riscv_zvl_flags
= riscv_zvl_flags
69 riscv_vector_elen_flags
= riscv_vector_elen_flags
72 | MASK_VECTOR_ELEN_FP_16
73 | MASK_VECTOR_ELEN_FP_32
74 | MASK_VECTOR_ELEN_FP_64
;
76 riscv_zvb_subext
= riscv_zvb_subext
81 riscv_zvk_subext
= riscv_zvk_subext
98 riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags
*flags
)
100 target_flags
= flags
->intrinsic_target_flags
;
102 riscv_vector_elen_flags
= flags
->intrinsic_riscv_vector_elen_flags
;
103 riscv_zvl_flags
= flags
->intrinsic_riscv_zvl_flags
;
104 riscv_zvb_subext
= flags
->intrinsic_riscv_zvb_subext
;
105 riscv_zvk_subext
= flags
->intrinsic_riscv_zvk_subext
;
109 riscv_ext_version_value (unsigned major
, unsigned minor
)
111 return (major
* RISCV_MAJOR_VERSION_BASE
)
112 + (minor
* RISCV_MINOR_VERSION_BASE
);
115 /* Implement TARGET_CPU_CPP_BUILTINS. */
118 riscv_cpu_cpp_builtins (cpp_reader
*pfile
)
120 builtin_define ("__riscv");
122 if (TARGET_RVC
|| TARGET_ZCA
)
123 builtin_define ("__riscv_compressed");
126 builtin_define (TARGET_64BIT
? "__riscv_64e" : "__riscv_32e");
129 builtin_define ("__riscv_atomic");
132 builtin_define ("__riscv_mul");
134 builtin_define ("__riscv_div");
135 if (TARGET_DIV
&& TARGET_MUL
)
136 builtin_define ("__riscv_muldiv");
138 builtin_define_with_int_value ("__riscv_xlen", UNITS_PER_WORD
* 8);
139 if (TARGET_HARD_FLOAT
)
140 builtin_define_with_int_value ("__riscv_flen", UNITS_PER_FP_REG
* 8);
142 if ((TARGET_HARD_FLOAT
|| TARGET_ZFINX
) && TARGET_FDIV
)
144 builtin_define ("__riscv_fdiv");
145 builtin_define ("__riscv_fsqrt");
152 builtin_define ("__riscv_abi_rve");
157 builtin_define ("__riscv_float_abi_soft");
162 builtin_define ("__riscv_float_abi_single");
167 builtin_define ("__riscv_float_abi_double");
171 switch (riscv_cmodel
)
174 builtin_define ("__riscv_cmodel_medlow");
178 builtin_define ("__riscv_cmodel_large");
183 builtin_define ("__riscv_cmodel_medany");
187 if (riscv_user_wants_strict_align
)
188 builtin_define_with_int_value ("__riscv_misaligned_avoid", 1);
189 else if (riscv_slow_unaligned_access_p
)
190 builtin_define_with_int_value ("__riscv_misaligned_slow", 1);
192 builtin_define_with_int_value ("__riscv_misaligned_fast", 1);
194 if (TARGET_MIN_VLEN
!= 0)
195 builtin_define_with_int_value ("__riscv_v_min_vlen", TARGET_MIN_VLEN
);
197 if (TARGET_VECTOR_ELEN_64
)
198 builtin_define_with_int_value ("__riscv_v_elen", 64);
199 else if (TARGET_VECTOR_ELEN_32
)
200 builtin_define_with_int_value ("__riscv_v_elen", 32);
202 if (TARGET_VECTOR_ELEN_FP_64
)
203 builtin_define_with_int_value ("__riscv_v_elen_fp", 64);
204 else if (TARGET_VECTOR_ELEN_FP_32
)
205 builtin_define_with_int_value ("__riscv_v_elen_fp", 32);
206 else if (TARGET_MIN_VLEN
!= 0)
207 builtin_define_with_int_value ("__riscv_v_elen_fp", 0);
211 builtin_define ("__riscv_vector");
212 builtin_define_with_int_value ("__riscv_v_intrinsic",
213 riscv_ext_version_value (0, 12));
215 if (rvv_vector_bits
== RVV_VECTOR_BITS_ZVL
)
216 builtin_define_with_int_value ("__riscv_v_fixed_vlen", TARGET_MIN_VLEN
);
219 if (TARGET_XTHEADVECTOR
)
220 builtin_define_with_int_value ("__riscv_th_v_intrinsic",
221 riscv_ext_version_value (0, 11));
223 /* Define architecture extension test macros. */
224 builtin_define_with_int_value ("__riscv_arch_test", 1);
226 if (TARGET_ZICFISS
&& ((flag_cf_protection
& CF_RETURN
) == CF_RETURN
))
227 builtin_define ("__riscv_shadow_stack");
229 if (TARGET_ZICFILP
&& ((flag_cf_protection
& CF_BRANCH
) == CF_BRANCH
))
231 builtin_define ("__riscv_landing_pad");
232 builtin_define ("__riscv_landing_pad_unlabeled");
235 const riscv_subset_list
*subset_list
= riscv_cmdline_subset_list ();
239 size_t max_ext_len
= 0;
241 /* Figure out the max length of extension name for reserving buffer. */
242 for (const riscv_subset_t
*subset
= subset_list
->begin ();
243 subset
!= subset_list
->end ();
244 subset
= subset
->next
)
245 max_ext_len
= MAX (max_ext_len
, subset
->name
.length ());
247 char *buf
= (char *)alloca (max_ext_len
+ 10 /* For __riscv_ and '\0'. */);
249 for (const riscv_subset_t
*subset
= subset_list
->begin ();
250 subset
!= subset_list
->end ();
251 subset
= subset
->next
)
253 int version_value
= riscv_ext_version_value (subset
->major_version
,
254 subset
->minor_version
);
255 /* Special rule for zicsr and zifencei, it's used for ISA spec 2.2 or
257 if ((subset
->name
== "zicsr" || subset
->name
== "zifencei")
258 && version_value
== 0)
259 version_value
= riscv_ext_version_value (2, 0);
261 sprintf (buf
, "__riscv_%s", subset
->name
.c_str ());
262 builtin_define_with_int_value (buf
, version_value
);
266 /* Implement "#pragma riscv intrinsic". */
269 riscv_pragma_intrinsic (cpp_reader
*)
273 if (pragma_lex (&x
) != CPP_STRING
)
275 error ("%<#pragma riscv intrinsic%> requires a string parameter");
279 const char *name
= TREE_STRING_POINTER (x
);
281 if (strcmp (name
, "vector") == 0
282 || strcmp (name
, "xtheadvector") == 0)
284 struct pragma_intrinsic_flags backup_flags
;
286 riscv_pragma_intrinsic_flags_pollute (&backup_flags
);
288 riscv_option_override ();
289 init_adjust_machine_modes ();
290 riscv_vector::reinit_builtins ();
291 riscv_vector::handle_pragma_vector ();
293 riscv_pragma_intrinsic_flags_restore (&backup_flags
);
295 /* Re-initialize after the flags are restored. */
296 riscv_option_override ();
297 init_adjust_machine_modes ();
300 error ("unknown %<#pragma riscv intrinsic%> option %qs", name
);
303 /* Implement TARGET_CHECK_BUILTIN_CALL. */
305 riscv_check_builtin_call (location_t loc
, vec
<location_t
> arg_loc
, tree fndecl
,
306 tree
, unsigned int nargs
, tree
*args
, bool)
308 unsigned int code
= DECL_MD_FUNCTION_CODE (fndecl
);
309 unsigned int subcode
= code
>> RISCV_BUILTIN_SHIFT
;
310 switch (code
& RISCV_BUILTIN_CLASS
)
312 case RISCV_BUILTIN_GENERAL
:
315 case RISCV_BUILTIN_VECTOR
:
316 return riscv_vector::check_builtin_call (loc
, arg_loc
, subcode
,
317 fndecl
, nargs
, args
);
322 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
324 riscv_resolve_overloaded_builtin (location_t loc
, tree fndecl
,
325 void *uncast_arglist
, bool)
327 vec
<tree
, va_gc
> empty
= {};
328 vec
<tree
, va_gc
> *arglist
= (vec
<tree
, va_gc
> *) uncast_arglist
;
329 unsigned int code
= DECL_MD_FUNCTION_CODE (fndecl
);
330 unsigned int subcode
= code
>> RISCV_BUILTIN_SHIFT
;
331 tree new_fndecl
= NULL_TREE
;
336 switch (code
& RISCV_BUILTIN_CLASS
)
338 case RISCV_BUILTIN_GENERAL
:
340 case RISCV_BUILTIN_VECTOR
:
341 new_fndecl
= riscv_vector::resolve_overloaded_builtin (loc
, subcode
,
348 if (new_fndecl
== NULL_TREE
)
351 return build_function_call_vec (loc
, vNULL
, new_fndecl
, arglist
, NULL
,
355 /* Implement REGISTER_TARGET_PRAGMAS. */
358 riscv_register_pragmas (void)
360 targetm
.resolve_overloaded_builtin
= riscv_resolve_overloaded_builtin
;
361 targetm
.check_builtin_call
= riscv_check_builtin_call
;
362 c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic
);