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 5829 : BuiltinsContext::get ()
29 : {
30 5829 : static BuiltinsContext instance;
31 5829 : return instance;
32 : }
33 :
34 : bool
35 8561 : BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
36 : {
37 8561 : auto *to_search = &name;
38 :
39 8561 : auto it = rust_intrinsic_to_gcc_builtin.find (name);
40 8561 : if (it != rust_intrinsic_to_gcc_builtin.end ())
41 308 : to_search = &it->second;
42 :
43 8561 : return lookup_gcc_builtin (*to_search, builtin);
44 : }
45 :
46 1364 : 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 687456 : BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
55 : bool is_variadic, size_t n, ...)
56 : {
57 687456 : va_list list;
58 687456 : va_start (list, n);
59 :
60 687456 : auto args = std::vector<tree> ();
61 :
62 2211044 : 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 1523588 : auto arg_idx = va_arg (list, int);
67 1523588 : auto arg_type = builtin_types[arg_idx];
68 :
69 1523588 : args.emplace_back (arg_type);
70 : }
71 :
72 687456 : auto return_type = builtin_types[ret_idx];
73 687456 : if (return_type == error_mark_node)
74 : {
75 : // Mark the builtin as not available.
76 17732 : builtin_types[def_idx] = error_mark_node;
77 17732 : va_end (list);
78 17732 : return;
79 : }
80 :
81 669724 : auto fn_type = NULL_TREE;
82 669724 : if (is_variadic)
83 40920 : fn_type = build_varargs_function_type_array (return_type, n, args.data ());
84 : else
85 628804 : fn_type = build_function_type_array (return_type, n, args.data ());
86 :
87 669724 : builtin_types[def_idx] = fn_type;
88 669724 : va_end (list);
89 687456 : }
90 :
91 : // Taken directly from the D frontend
92 : static void
93 1364 : build_c_type_nodes (void)
94 : {
95 1364 : string_type_node = build_pointer_type (char_type_node);
96 1364 : const_string_type_node = build_pointer_type (
97 : build_qualified_type (char_type_node, TYPE_QUAL_CONST));
98 :
99 1364 : 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 1364 : else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
105 : {
106 1364 : intmax_type_node = long_integer_type_node;
107 1364 : 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 1364 : signed_size_type_node = signed_type_for (size_type_node);
118 1364 : wint_type_node = unsigned_type_node;
119 1364 : pid_type_node = integer_type_node;
120 1364 : }
121 :
122 : /**
123 : * Define all builtin types in the `builtin_types` array
124 : */
125 : void
126 1364 : BuiltinsContext::define_builtin_types ()
127 : {
128 : // This is taken directly from the D frontend's handling of builtins
129 1364 : auto va_list_ref_type_node = build_reference_type (va_list_type_node);
130 1364 : auto va_list_arg_type_node = va_list_type_node;
131 :
132 1364 : build_c_type_nodes ();
133 :
134 1364 : auto builtin_type_for_size = [] (int size, bool unsignedp) {
135 6820 : tree type = lang_hooks.types.type_for_size (size, unsignedp);
136 6820 : 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 1364 : builtin_types[Type::BT_LAST] = NULL_TREE;
217 1364 : }
218 :
219 : /**
220 : * Define all builtin attributes in the `builtin_types` array
221 : */
222 : void
223 1364 : BuiltinsContext::define_builtin_attributes ()
224 :
225 : {
226 1364 : 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 1364 : }
246 :
247 : /**
248 : * Define all builtin functions during the first initialization of the
249 : * `BuiltinsContext`.
250 : */
251 : void
252 1364 : BuiltinsContext::define_builtins ()
253 : {
254 1364 : auto *built_in_attributes = builtin_attributes;
255 2044636 : 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 2043272 : if (fn_type == error_mark_node)
259 2043272 : return;
260 :
261 1932788 : static auto to_skip = strlen ("__builtin_");
262 :
263 1932788 : auto libname = fn_name + to_skip;
264 2500212 : auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
265 1932788 : fallback ? libname : NULL, attributes);
266 :
267 1932788 : set_builtin_decl (fn_code, decl, implicit);
268 :
269 1932788 : builtin_functions.insert ({std::string (fn_name), decl});
270 1364 : };
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 1364 : }
280 :
281 : /**
282 : * Register direct mappings between Rust functions and GCC builtins
283 : */
284 : void
285 1364 : BuiltinsContext::register_rust_mappings ()
286 : {
287 1364 : 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 61380 : };
355 1364 : }
356 :
357 : void
358 1364 : BuiltinsContext::setup ()
359 : {
360 1364 : define_builtin_types ();
361 1364 : define_builtin_attributes ();
362 1364 : define_builtins ();
363 :
364 1364 : register_rust_mappings ();
365 1364 : }
366 :
367 : bool
368 8561 : BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
369 : {
370 8561 : auto it = builtin_functions.find (name);
371 8561 : if (it == builtin_functions.end ())
372 : return false;
373 :
374 6372 : *builtin = it->second;
375 6372 : return true;
376 : }
377 :
378 : } // namespace Compile
379 : } // namespace Rust
|