]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/riscv/riscv-c.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / config / riscv / riscv-c.cc
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).
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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.
16
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/>. */
20
21 #define IN_TARGET_CODE 1
22
23 #define INCLUDE_STRING
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "c-family/c-common.h"
29 #include "cpplib.h"
30 #include "c-family/c-pragma.h"
31 #include "target.h"
32 #include "tm_p.h"
33 #include "riscv-subset.h"
34
35 #define builtin_define(TXT) cpp_define (pfile, TXT)
36
37 static int
38 riscv_ext_version_value (unsigned major, unsigned minor)
39 {
40 return (major * 1000000) + (minor * 1000);
41 }
42
43 /* Implement TARGET_CPU_CPP_BUILTINS. */
44
45 void
46 riscv_cpu_cpp_builtins (cpp_reader *pfile)
47 {
48 builtin_define ("__riscv");
49
50 if (TARGET_RVC || TARGET_ZCA)
51 builtin_define ("__riscv_compressed");
52
53 if (TARGET_RVE)
54 builtin_define (TARGET_64BIT ? "__riscv_64e" : "__riscv_32e");
55
56 if (TARGET_ATOMIC)
57 builtin_define ("__riscv_atomic");
58
59 if (TARGET_MUL)
60 builtin_define ("__riscv_mul");
61 if (TARGET_DIV)
62 builtin_define ("__riscv_div");
63 if (TARGET_DIV && TARGET_MUL)
64 builtin_define ("__riscv_muldiv");
65
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);
69
70 if ((TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV)
71 {
72 builtin_define ("__riscv_fdiv");
73 builtin_define ("__riscv_fsqrt");
74 }
75
76 switch (riscv_abi)
77 {
78 case ABI_ILP32E:
79 case ABI_LP64E:
80 builtin_define ("__riscv_abi_rve");
81 gcc_fallthrough ();
82
83 case ABI_ILP32:
84 case ABI_LP64:
85 builtin_define ("__riscv_float_abi_soft");
86 break;
87
88 case ABI_ILP32F:
89 case ABI_LP64F:
90 builtin_define ("__riscv_float_abi_single");
91 break;
92
93 case ABI_ILP32D:
94 case ABI_LP64D:
95 builtin_define ("__riscv_float_abi_double");
96 break;
97 }
98
99 switch (riscv_cmodel)
100 {
101 case CM_MEDLOW:
102 builtin_define ("__riscv_cmodel_medlow");
103 break;
104
105 case CM_LARGE:
106 builtin_define ("__riscv_cmodel_large");
107 break;
108
109 case CM_PIC:
110 case CM_MEDANY:
111 builtin_define ("__riscv_cmodel_medany");
112 break;
113
114 }
115
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);
120 else
121 builtin_define_with_int_value ("__riscv_misaligned_fast", 1);
122
123 if (TARGET_MIN_VLEN != 0)
124 builtin_define_with_int_value ("__riscv_v_min_vlen", TARGET_MIN_VLEN);
125
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);
130
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);
137
138 if (TARGET_MIN_VLEN)
139 {
140 builtin_define ("__riscv_vector");
141 builtin_define_with_int_value ("__riscv_v_intrinsic",
142 riscv_ext_version_value (0, 11));
143 }
144
145 /* Define architecture extension test macros. */
146 builtin_define_with_int_value ("__riscv_arch_test", 1);
147
148 const riscv_subset_list *subset_list = riscv_current_subset_list ();
149 if (!subset_list)
150 return;
151
152 size_t max_ext_len = 0;
153
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 ());
159
160 char *buf = (char *)alloca (max_ext_len + 10 /* For __riscv_ and '\0'. */);
161
162 for (const riscv_subset_t *subset = subset_list->begin ();
163 subset != subset_list->end ();
164 subset = subset->next)
165 {
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
169 earlier. */
170 if ((subset->name == "zicsr" || subset->name == "zifencei")
171 && version_value == 0)
172 version_value = riscv_ext_version_value (2, 0);
173
174 sprintf (buf, "__riscv_%s", subset->name.c_str ());
175 builtin_define_with_int_value (buf, version_value);
176 }
177 }
178
179 /* Implement "#pragma riscv intrinsic". */
180
181 static void
182 riscv_pragma_intrinsic (cpp_reader *)
183 {
184 tree x;
185
186 if (pragma_lex (&x) != CPP_STRING)
187 {
188 error ("%<#pragma riscv intrinsic%> requires a string parameter");
189 return;
190 }
191
192 const char *name = TREE_STRING_POINTER (x);
193
194 if (strcmp (name, "vector") == 0)
195 {
196 if (!TARGET_VECTOR)
197 {
198 error ("%<#pragma riscv intrinsic%> option %qs needs 'V' extension "
199 "enabled",
200 name);
201 return;
202 }
203 riscv_vector::handle_pragma_vector ();
204 }
205 else
206 error ("unknown %<#pragma riscv intrinsic%> option %qs", name);
207 }
208
209 /* Implement TARGET_CHECK_BUILTIN_CALL. */
210 static bool
211 riscv_check_builtin_call (location_t loc, vec<location_t> arg_loc, tree fndecl,
212 tree, unsigned int nargs, tree *args)
213 {
214 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
215 unsigned int subcode = code >> RISCV_BUILTIN_SHIFT;
216 switch (code & RISCV_BUILTIN_CLASS)
217 {
218 case RISCV_BUILTIN_GENERAL:
219 return true;
220
221 case RISCV_BUILTIN_VECTOR:
222 return riscv_vector::check_builtin_call (loc, arg_loc, subcode,
223 fndecl, nargs, args);
224 }
225 gcc_unreachable ();
226 }
227
228 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
229 static tree
230 riscv_resolve_overloaded_builtin (unsigned int uncast_location, tree fndecl,
231 void *uncast_arglist)
232 {
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;
239
240 if (!arglist)
241 arglist = &empty;
242
243 switch (code & RISCV_BUILTIN_CLASS)
244 {
245 case RISCV_BUILTIN_GENERAL:
246 break;
247 case RISCV_BUILTIN_VECTOR:
248 new_fndecl = riscv_vector::resolve_overloaded_builtin (subcode, arglist);
249 break;
250 default:
251 gcc_unreachable ();
252 }
253
254 if (new_fndecl == NULL_TREE)
255 return new_fndecl;
256
257 return build_function_call_vec (loc, vNULL, new_fndecl, arglist, NULL,
258 fndecl);
259 }
260
261 /* Implement REGISTER_TARGET_PRAGMAS. */
262
263 void
264 riscv_register_pragmas (void)
265 {
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);
269 }