1 /* RISC-V-specific code for C family languages.
2 Copyright (C) 2011-2024 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)
38 riscv_ext_version_value (unsigned major
, unsigned minor
)
40 return (major
* 1000000) + (minor
* 1000);
43 /* Implement TARGET_CPU_CPP_BUILTINS. */
46 riscv_cpu_cpp_builtins (cpp_reader
*pfile
)
48 builtin_define ("__riscv");
50 if (TARGET_RVC
|| TARGET_ZCA
)
51 builtin_define ("__riscv_compressed");
54 builtin_define (TARGET_64BIT
? "__riscv_64e" : "__riscv_32e");
57 builtin_define ("__riscv_atomic");
60 builtin_define ("__riscv_mul");
62 builtin_define ("__riscv_div");
63 if (TARGET_DIV
&& TARGET_MUL
)
64 builtin_define ("__riscv_muldiv");
66 builtin_define_with_int_value ("__riscv_xlen", UNITS_PER_WORD
* 8);
67 if (TARGET_HARD_FLOAT
)
68 builtin_define_with_int_value ("__riscv_flen", UNITS_PER_FP_REG
* 8);
70 if ((TARGET_HARD_FLOAT
|| TARGET_ZFINX
) && TARGET_FDIV
)
72 builtin_define ("__riscv_fdiv");
73 builtin_define ("__riscv_fsqrt");
80 builtin_define ("__riscv_abi_rve");
85 builtin_define ("__riscv_float_abi_soft");
90 builtin_define ("__riscv_float_abi_single");
95 builtin_define ("__riscv_float_abi_double");
102 builtin_define ("__riscv_cmodel_medlow");
106 builtin_define ("__riscv_cmodel_large");
111 builtin_define ("__riscv_cmodel_medany");
116 if (riscv_user_wants_strict_align
)
117 builtin_define_with_int_value ("__riscv_misaligned_avoid", 1);
118 else if (riscv_slow_unaligned_access_p
)
119 builtin_define_with_int_value ("__riscv_misaligned_slow", 1);
121 builtin_define_with_int_value ("__riscv_misaligned_fast", 1);
123 if (TARGET_MIN_VLEN
!= 0)
124 builtin_define_with_int_value ("__riscv_v_min_vlen", TARGET_MIN_VLEN
);
126 if (TARGET_VECTOR_ELEN_64
)
127 builtin_define_with_int_value ("__riscv_v_elen", 64);
128 else if (TARGET_VECTOR_ELEN_32
)
129 builtin_define_with_int_value ("__riscv_v_elen", 32);
131 if (TARGET_VECTOR_ELEN_FP_64
)
132 builtin_define_with_int_value ("__riscv_v_elen_fp", 64);
133 else if (TARGET_VECTOR_ELEN_FP_32
)
134 builtin_define_with_int_value ("__riscv_v_elen_fp", 32);
135 else if (TARGET_MIN_VLEN
!= 0)
136 builtin_define_with_int_value ("__riscv_v_elen_fp", 0);
140 builtin_define ("__riscv_vector");
141 builtin_define_with_int_value ("__riscv_v_intrinsic",
142 riscv_ext_version_value (0, 11));
145 /* Define architecture extension test macros. */
146 builtin_define_with_int_value ("__riscv_arch_test", 1);
148 const riscv_subset_list
*subset_list
= riscv_current_subset_list ();
152 size_t max_ext_len
= 0;
154 /* Figure out the max length of extension name for reserving buffer. */
155 for (const riscv_subset_t
*subset
= subset_list
->begin ();
156 subset
!= subset_list
->end ();
157 subset
= subset
->next
)
158 max_ext_len
= MAX (max_ext_len
, subset
->name
.length ());
160 char *buf
= (char *)alloca (max_ext_len
+ 10 /* For __riscv_ and '\0'. */);
162 for (const riscv_subset_t
*subset
= subset_list
->begin ();
163 subset
!= subset_list
->end ();
164 subset
= subset
->next
)
166 int version_value
= riscv_ext_version_value (subset
->major_version
,
167 subset
->minor_version
);
168 /* Special rule for zicsr and zifencei, it's used for ISA spec 2.2 or
170 if ((subset
->name
== "zicsr" || subset
->name
== "zifencei")
171 && version_value
== 0)
172 version_value
= riscv_ext_version_value (2, 0);
174 sprintf (buf
, "__riscv_%s", subset
->name
.c_str ());
175 builtin_define_with_int_value (buf
, version_value
);
179 /* Implement "#pragma riscv intrinsic". */
182 riscv_pragma_intrinsic (cpp_reader
*)
186 if (pragma_lex (&x
) != CPP_STRING
)
188 error ("%<#pragma riscv intrinsic%> requires a string parameter");
192 const char *name
= TREE_STRING_POINTER (x
);
194 if (strcmp (name
, "vector") == 0)
198 error ("%<#pragma riscv intrinsic%> option %qs needs 'V' extension "
203 riscv_vector::handle_pragma_vector ();
206 error ("unknown %<#pragma riscv intrinsic%> option %qs", name
);
209 /* Implement TARGET_CHECK_BUILTIN_CALL. */
211 riscv_check_builtin_call (location_t loc
, vec
<location_t
> arg_loc
, tree fndecl
,
212 tree
, unsigned int nargs
, tree
*args
)
214 unsigned int code
= DECL_MD_FUNCTION_CODE (fndecl
);
215 unsigned int subcode
= code
>> RISCV_BUILTIN_SHIFT
;
216 switch (code
& RISCV_BUILTIN_CLASS
)
218 case RISCV_BUILTIN_GENERAL
:
221 case RISCV_BUILTIN_VECTOR
:
222 return riscv_vector::check_builtin_call (loc
, arg_loc
, subcode
,
223 fndecl
, nargs
, args
);
228 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
230 riscv_resolve_overloaded_builtin (unsigned int uncast_location
, tree fndecl
,
231 void *uncast_arglist
)
233 vec
<tree
, va_gc
> empty
= {};
234 location_t loc
= (location_t
) uncast_location
;
235 vec
<tree
, va_gc
> *arglist
= (vec
<tree
, va_gc
> *) uncast_arglist
;
236 unsigned int code
= DECL_MD_FUNCTION_CODE (fndecl
);
237 unsigned int subcode
= code
>> RISCV_BUILTIN_SHIFT
;
238 tree new_fndecl
= NULL_TREE
;
243 switch (code
& RISCV_BUILTIN_CLASS
)
245 case RISCV_BUILTIN_GENERAL
:
247 case RISCV_BUILTIN_VECTOR
:
248 new_fndecl
= riscv_vector::resolve_overloaded_builtin (subcode
, arglist
);
254 if (new_fndecl
== NULL_TREE
)
257 return build_function_call_vec (loc
, vNULL
, new_fndecl
, arglist
, NULL
,
261 /* Implement REGISTER_TARGET_PRAGMAS. */
264 riscv_register_pragmas (void)
266 targetm
.resolve_overloaded_builtin
= riscv_resolve_overloaded_builtin
;
267 targetm
.check_builtin_call
= riscv_check_builtin_call
;
268 c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic
);