Branch data Line data Source code
1 : : // This file is part of GCC.
2 : :
3 : : // GCC is free software; you can redistribute it and/or modify it under
4 : : // the terms of the GNU General Public License as published by the Free
5 : : // Software Foundation; either version 3, or (at your option) any later
6 : : // version.
7 : :
8 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
9 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 : : // for more details.
12 : :
13 : : // You should have received a copy of the GNU General Public License
14 : : // along with GCC; see the file COPYING3. If not see
15 : : // <http://www.gnu.org/licenses/>.
16 : :
17 : : #include "rust-diagnostics.h"
18 : : #include "rust-system.h"
19 : : #include "rust-builtins.h"
20 : :
21 : : #include "target.h"
22 : : #include "stringpool.h"
23 : :
24 : : namespace Rust {
25 : : namespace Compile {
26 : :
27 : : BuiltinsContext &
28 : 4204 : BuiltinsContext::get ()
29 : : {
30 : 4204 : static BuiltinsContext instance;
31 : 4204 : return instance;
32 : : }
33 : :
34 : : bool
35 : 6119 : BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
36 : : {
37 : 6119 : auto *to_search = &name;
38 : :
39 : 6119 : auto it = rust_intrinsic_to_gcc_builtin.find (name);
40 : 6119 : if (it != rust_intrinsic_to_gcc_builtin.end ())
41 : 308 : to_search = &it->second;
42 : :
43 : 6119 : return lookup_gcc_builtin (*to_search, builtin);
44 : : }
45 : :
46 : 1028 : BuiltinsContext::BuiltinsContext () { setup (); }
47 : :
48 : : /**
49 : : * Define a function type according to `builtin-types.def`
50 : : *
51 : : * *Heavily* inspired by the D frontend's `def_fn_type` function
52 : : */
53 : : void
54 : 517084 : BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
55 : : bool is_variadic, size_t n, ...)
56 : : {
57 : 517084 : va_list list;
58 : 517084 : va_start (list, n);
59 : :
60 : 517084 : auto args = std::vector<tree> ();
61 : :
62 : 1654052 : for (size_t i = 0; i < n; i++)
63 : : {
64 : : // The argument is an enum Type, but it's promoted to int when passed
65 : : // though '...'.
66 : 1136968 : auto arg_idx = va_arg (list, int);
67 : 1136968 : auto arg_type = builtin_types[arg_idx];
68 : :
69 : 1136968 : args.emplace_back (arg_type);
70 : : }
71 : :
72 : 517084 : auto return_type = builtin_types[ret_idx];
73 : 517084 : if (return_type == error_mark_node)
74 : : {
75 : : // Mark the builtin as not available.
76 : 13364 : builtin_types[def_idx] = error_mark_node;
77 : 13364 : va_end (list);
78 : 13364 : return;
79 : : }
80 : :
81 : 503720 : auto fn_type = NULL_TREE;
82 : 503720 : if (is_variadic)
83 : 30840 : fn_type = build_varargs_function_type_array (return_type, n, args.data ());
84 : : else
85 : 472880 : fn_type = build_function_type_array (return_type, n, args.data ());
86 : :
87 : 503720 : builtin_types[def_idx] = fn_type;
88 : 503720 : va_end (list);
89 : 517084 : }
90 : :
91 : : // Taken directly from the D frontend
92 : : static void
93 : 1028 : build_c_type_nodes (void)
94 : : {
95 : 1028 : string_type_node = build_pointer_type (char_type_node);
96 : 1028 : const_string_type_node = build_pointer_type (
97 : : build_qualified_type (char_type_node, TYPE_QUAL_CONST));
98 : :
99 : 1028 : if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
100 : : {
101 : 0 : intmax_type_node = integer_type_node;
102 : 0 : uintmax_type_node = unsigned_type_node;
103 : : }
104 : 1028 : else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
105 : : {
106 : 1028 : intmax_type_node = long_integer_type_node;
107 : 1028 : uintmax_type_node = long_unsigned_type_node;
108 : : }
109 : 0 : else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
110 : : {
111 : 0 : intmax_type_node = long_long_integer_type_node;
112 : 0 : uintmax_type_node = long_long_unsigned_type_node;
113 : : }
114 : : else
115 : 0 : gcc_unreachable ();
116 : :
117 : 1028 : signed_size_type_node = signed_type_for (size_type_node);
118 : 1028 : wint_type_node = unsigned_type_node;
119 : 1028 : pid_type_node = integer_type_node;
120 : 1028 : }
121 : :
122 : : /**
123 : : * Define all builtin types in the `builtin_types` array
124 : : */
125 : : void
126 : 1028 : BuiltinsContext::define_builtin_types ()
127 : : {
128 : : // This is taken directly from the D frontend's handling of builtins
129 : 1028 : auto va_list_ref_type_node = build_reference_type (va_list_type_node);
130 : 1028 : auto va_list_arg_type_node = va_list_type_node;
131 : :
132 : 1028 : build_c_type_nodes ();
133 : :
134 : 1028 : auto builtin_type_for_size = [] (int size, bool unsignedp) {
135 : 5140 : tree type = lang_hooks.types.type_for_size (size, unsignedp);
136 : 5140 : return type ? type : error_mark_node;
137 : : };
138 : :
139 : : #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE;
140 : : #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
141 : : define_function_type (ENUM, RETURN, 0, 0);
142 : : #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1) \
143 : : define_function_type (ENUM, RETURN, 0, 1, A1);
144 : : #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2) \
145 : : define_function_type (ENUM, RETURN, 0, 2, A1, A2);
146 : : #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3) \
147 : : define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3);
148 : : #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4) \
149 : : define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4);
150 : : #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5) \
151 : : define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5);
152 : : #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \
153 : : define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6);
154 : : #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \
155 : : define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7);
156 : : #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8) \
157 : : define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8);
158 : : #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9) \
159 : : define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
160 : : #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
161 : : A10) \
162 : : define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8, \
163 : : A9, A10);
164 : : #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
165 : : A10, A11) \
166 : : define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8, \
167 : : A9, A10, A11);
168 : : #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
169 : : define_function_type (ENUM, RETURN, 1, 0);
170 : : #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1) \
171 : : define_function_type (ENUM, RETURN, 1, 1, A1);
172 : : #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2) \
173 : : define_function_type (ENUM, RETURN, 1, 2, A1, A2);
174 : : #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3) \
175 : : define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3);
176 : : #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4) \
177 : : define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4);
178 : : #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5) \
179 : : define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5);
180 : : #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \
181 : : define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6);
182 : : #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \
183 : : define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7);
184 : : #define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \
185 : : A9, A10, A11) \
186 : : define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8, \
187 : : A9, A10, A11);
188 : : #define DEF_POINTER_TYPE(ENUM, TYPE) \
189 : : builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
190 : :
191 : : #include "builtin-types.def"
192 : :
193 : : #undef DEF_PRIMITIVE_TYPE
194 : : #undef DEF_FUNCTION_TYPE_1
195 : : #undef DEF_FUNCTION_TYPE_2
196 : : #undef DEF_FUNCTION_TYPE_3
197 : : #undef DEF_FUNCTION_TYPE_4
198 : : #undef DEF_FUNCTION_TYPE_5
199 : : #undef DEF_FUNCTION_TYPE_6
200 : : #undef DEF_FUNCTION_TYPE_7
201 : : #undef DEF_FUNCTION_TYPE_8
202 : : #undef DEF_FUNCTION_TYPE_9
203 : : #undef DEF_FUNCTION_TYPE_10
204 : : #undef DEF_FUNCTION_TYPE_11
205 : : #undef DEF_FUNCTION_TYPE_VAR_0
206 : : #undef DEF_FUNCTION_TYPE_VAR_1
207 : : #undef DEF_FUNCTION_TYPE_VAR_2
208 : : #undef DEF_FUNCTION_TYPE_VAR_3
209 : : #undef DEF_FUNCTION_TYPE_VAR_4
210 : : #undef DEF_FUNCTION_TYPE_VAR_5
211 : : #undef DEF_FUNCTION_TYPE_VAR_6
212 : : #undef DEF_FUNCTION_TYPE_VAR_7
213 : : #undef DEF_FUNCTION_TYPE_VAR_11
214 : : #undef DEF_POINTER_TYPE
215 : :
216 : 1028 : builtin_types[Type::BT_LAST] = NULL_TREE;
217 : 1028 : }
218 : :
219 : : /**
220 : : * Define all builtin attributes in the `builtin_types` array
221 : : */
222 : : void
223 : 1028 : BuiltinsContext::define_builtin_attributes ()
224 : :
225 : : {
226 : 1028 : auto *built_in_attributes = builtin_attributes;
227 : :
228 : : #define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE;
229 : : #define DEF_ATTR_INT(ENUM, VALUE) \
230 : : built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE);
231 : : #define DEF_ATTR_STRING(ENUM, VALUE) \
232 : : built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE);
233 : : #define DEF_ATTR_IDENT(ENUM, STRING) \
234 : : built_in_attributes[ENUM] = get_identifier (STRING);
235 : : #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
236 : : built_in_attributes[ENUM] \
237 : : = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE], \
238 : : built_in_attributes[CHAIN]);
239 : : #include "builtin-attrs.def"
240 : : #undef DEF_ATTR_NULL_TREE
241 : : #undef DEF_ATTR_INT
242 : : #undef DEF_ATTR_STRING
243 : : #undef DEF_ATTR_IDENT
244 : : #undef DEF_ATTR_TREE_LIST
245 : 1028 : }
246 : :
247 : : /**
248 : : * Define all builtin functions during the first initialization of the
249 : : * `BuiltinsContext`.
250 : : */
251 : : void
252 : 1028 : BuiltinsContext::define_builtins ()
253 : : {
254 : 1028 : auto *built_in_attributes = builtin_attributes;
255 : 1467984 : auto build_builtin = [this] (built_in_function fn_code, const char *fn_name,
256 : : built_in_class fn_class, tree fn_type, bool both,
257 : : bool fallback, tree attributes, bool implicit) {
258 : 1466956 : if (fn_type == error_mark_node)
259 : 1466956 : return;
260 : :
261 : 1390884 : static auto to_skip = strlen ("__builtin_");
262 : :
263 : 1390884 : auto libname = fn_name + to_skip;
264 : 1817504 : auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
265 : 1390884 : fallback ? libname : NULL, attributes);
266 : :
267 : 1390884 : set_builtin_decl (fn_code, decl, implicit);
268 : :
269 : 1390884 : builtin_functions.insert ({std::string (fn_name), decl});
270 : 1028 : };
271 : :
272 : : #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
273 : : NONANSI_P, ATTRS, IMPLICIT, COND) \
274 : : if (NAME && COND) \
275 : : build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
276 : : built_in_attributes[ATTRS], IMPLICIT);
277 : : #include "builtins.def"
278 : : #undef DEF_BUILTIN
279 : 1028 : }
280 : :
281 : : /**
282 : : * Register direct mappings between Rust functions and GCC builtins
283 : : */
284 : : void
285 : 1028 : BuiltinsContext::register_rust_mappings ()
286 : : {
287 : 47288 : rust_intrinsic_to_gcc_builtin = {
288 : : {"unreachable", "__builtin_unreachable"},
289 : : {"abort", "__builtin_abort"},
290 : :
291 : : // Math intrinsics
292 : : {"sqrtf32", "__builtin_sqrtf"},
293 : : {"sqrtf64", "__builtin_sqrt"},
294 : :
295 : : {"sinf32", "__builtin_sinf"},
296 : : {"sinf64", "__builtin_sin"},
297 : :
298 : : {"cosf32", "__builtin_cosf"},
299 : : {"cosf64", "__builtin_cos"},
300 : :
301 : : {"powf32", "__builtin_powf"},
302 : : {"powf64", "__builtin_pow"},
303 : :
304 : : {"powif32", "__builtin_powif"},
305 : : {"powif64", "__builtin_powi"},
306 : :
307 : : {"expf32", "__builtin_expf"},
308 : : {"expf64", "__builtin_exp"},
309 : :
310 : : {"exp2f32", "__builtin_exp2f"},
311 : : {"exp2f64", "__builtin_exp2"},
312 : :
313 : : {"logf32", "__builtin_logf"},
314 : : {"logf64", "__builtin_log"},
315 : :
316 : : {"log10f32", "__builtin_log10f"},
317 : : {"log10f64", "__builtin_log10"},
318 : :
319 : : {"log2f32", "__builtin_log2f"},
320 : : {"log2f64", "__builtin_log2"},
321 : :
322 : : {"fmaf32", "__builtin_fmaf"},
323 : : {"fmaf64", "__builtin_fma"},
324 : :
325 : : {"fabsf32", "__builtin_fabsf"},
326 : : {"fabsf64", "__builtin_fabs"},
327 : :
328 : : {"minnumf32", "__builtin_fminf"},
329 : : {"minnumf64", "__builtin_fmin"},
330 : :
331 : : {"maxnumf32", "__builtin_fmaxf"},
332 : : {"maxnumf64", "__builtin_fmax"},
333 : :
334 : : {"copysignf32", "__builtin_copysignf"},
335 : : {"copysignf64", "__builtin_copysign"},
336 : :
337 : : {"floorf32", "__builtin_floorf"},
338 : : {"floorf64", "__builtin_floor"},
339 : :
340 : : {"ceilf32", "__builtin_ceilf"},
341 : : {"ceilf64", "__builtin_ceil"},
342 : :
343 : : {"truncf32", "__builtin_truncf"},
344 : : {"truncf64", "__builtin_trunc"},
345 : :
346 : : {"rintf32", "__builtin_rintf"},
347 : : {"rintf64", "__builtin_rint"},
348 : :
349 : : {"nearbyintf32", "__builtin_nearbyintf"},
350 : : {"nearbyintf64", "__builtin_nearbyint"},
351 : :
352 : : {"roundf32", "__builtin_roundf"},
353 : : {"roundf64", "__builtin_round"},
354 : 91492 : };
355 : 1028 : }
356 : :
357 : : void
358 : 1028 : BuiltinsContext::setup ()
359 : : {
360 : 1028 : define_builtin_types ();
361 : 1028 : define_builtin_attributes ();
362 : 1028 : define_builtins ();
363 : :
364 : 1028 : register_rust_mappings ();
365 : 1028 : }
366 : :
367 : : bool
368 : 6119 : BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
369 : : {
370 : 6119 : auto it = builtin_functions.find (name);
371 : 6119 : if (it == builtin_functions.end ())
372 : : return false;
373 : :
374 : 4438 : *builtin = it->second;
375 : 4438 : return true;
376 : : }
377 : :
378 : : } // namespace Compile
379 : : } // namespace Rust
|