1 // This file is part of GCC.
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
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
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/>.
17 #include "rust-diagnostics.h"
18 #include "rust-system.h"
19 #include "rust-builtins.h"
22 #include "stringpool.h"
28 BuiltinsContext::get ()
30 static BuiltinsContext instance
;
35 BuiltinsContext::lookup_simple_builtin (const std::string
&name
, tree
*builtin
)
37 auto *to_search
= &name
;
39 auto it
= rust_intrinsic_to_gcc_builtin
.find (name
);
40 if (it
!= rust_intrinsic_to_gcc_builtin
.end ())
41 to_search
= &it
->second
;
43 return lookup_gcc_builtin (*to_search
, builtin
);
46 BuiltinsContext::BuiltinsContext () { setup (); }
49 * Define a function type according to `builtin-types.def`
51 * *Heavily* inspired by the D frontend's `def_fn_type` function
54 BuiltinsContext::define_function_type (Type def_idx
, Type ret_idx
,
55 bool is_variadic
, size_t n
, ...)
60 auto args
= std::vector
<tree
> ();
62 for (size_t i
= 0; i
< n
; i
++)
64 // The argument is an enum Type, but it's promoted to int when passed
66 auto arg_idx
= va_arg (list
, int);
67 auto arg_type
= builtin_types
[arg_idx
];
69 args
.emplace_back (arg_type
);
72 auto return_type
= builtin_types
[ret_idx
];
73 if (return_type
== error_mark_node
)
75 // Mark the builtin as not available.
76 builtin_types
[def_idx
] = error_mark_node
;
81 auto fn_type
= NULL_TREE
;
83 fn_type
= build_varargs_function_type_array (return_type
, n
, args
.data ());
85 fn_type
= build_function_type_array (return_type
, n
, args
.data ());
87 builtin_types
[def_idx
] = fn_type
;
91 // Taken directly from the D frontend
93 build_c_type_nodes (void)
95 string_type_node
= build_pointer_type (char_type_node
);
96 const_string_type_node
= build_pointer_type (
97 build_qualified_type (char_type_node
, TYPE_QUAL_CONST
));
99 if (strcmp (UINTMAX_TYPE
, "unsigned int") == 0)
101 intmax_type_node
= integer_type_node
;
102 uintmax_type_node
= unsigned_type_node
;
104 else if (strcmp (UINTMAX_TYPE
, "long unsigned int") == 0)
106 intmax_type_node
= long_integer_type_node
;
107 uintmax_type_node
= long_unsigned_type_node
;
109 else if (strcmp (UINTMAX_TYPE
, "long long unsigned int") == 0)
111 intmax_type_node
= long_long_integer_type_node
;
112 uintmax_type_node
= long_long_unsigned_type_node
;
117 signed_size_type_node
= signed_type_for (size_type_node
);
118 wint_type_node
= unsigned_type_node
;
119 pid_type_node
= integer_type_node
;
123 * Define all builtin types in the `builtin_types` array
126 BuiltinsContext::define_builtin_types ()
128 // This is taken directly from the D frontend's handling of builtins
129 auto va_list_ref_type_node
= build_reference_type (va_list_type_node
);
130 auto va_list_arg_type_node
= va_list_type_node
;
132 build_c_type_nodes ();
134 auto builtin_type_for_size
= [] (int size
, bool unsignedp
) {
135 tree type
= lang_hooks
.types
.type_for_size (size
, unsignedp
);
136 return type
? type
: error_mark_node
;
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, \
162 define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8, \
164 #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
166 define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8, \
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, \
186 define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8, \
188 #define DEF_POINTER_TYPE(ENUM, TYPE) \
189 builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
191 #include "builtin-types.def"
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
216 builtin_types
[Type::BT_LAST
] = NULL_TREE
;
220 * Define all builtin attributes in the `builtin_types` array
223 BuiltinsContext::define_builtin_attributes ()
226 auto *built_in_attributes
= builtin_attributes
;
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
242 #undef DEF_ATTR_STRING
243 #undef DEF_ATTR_IDENT
244 #undef DEF_ATTR_TREE_LIST
248 * Define all builtin functions during the first initialization of the
252 BuiltinsContext::define_builtins ()
254 auto *built_in_attributes
= builtin_attributes
;
255 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 if (fn_type
== error_mark_node
)
261 static auto to_skip
= strlen ("__builtin_");
263 auto libname
= fn_name
+ to_skip
;
264 auto decl
= add_builtin_function (fn_name
, fn_type
, fn_code
, fn_class
,
265 fallback
? libname
: NULL
, attributes
);
267 set_builtin_decl (fn_code
, decl
, implicit
);
269 builtin_functions
.insert ({std::string (fn_name
), decl
});
272 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
273 NONANSI_P, ATTRS, IMPLICIT, COND) \
275 build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
276 built_in_attributes[ATTRS], IMPLICIT);
277 #include "builtins.def"
282 * Register direct mappings between Rust functions and GCC builtins
285 BuiltinsContext::register_rust_mappings ()
287 rust_intrinsic_to_gcc_builtin
= {
288 {"unreachable", "__builtin_unreachable"},
289 {"abort", "__builtin_abort"},
292 {"sqrtf32", "__builtin_sqrtf"},
293 {"sqrtf64", "__builtin_sqrt"},
295 {"sinf32", "__builtin_sinf"},
296 {"sinf64", "__builtin_sin"},
298 {"cosf32", "__builtin_cosf"},
299 {"cosf64", "__builtin_cos"},
301 {"powf32", "__builtin_powf"},
302 {"powf64", "__builtin_pow"},
304 {"powif32", "__builtin_powif"},
305 {"powif64", "__builtin_powi"},
307 {"expf32", "__builtin_expf"},
308 {"expf64", "__builtin_exp"},
310 {"exp2f32", "__builtin_exp2f"},
311 {"exp2f64", "__builtin_exp2"},
313 {"logf32", "__builtin_logf"},
314 {"logf64", "__builtin_log"},
316 {"log10f32", "__builtin_log10f"},
317 {"log10f64", "__builtin_log10"},
319 {"log2f32", "__builtin_log2f"},
320 {"log2f64", "__builtin_log2"},
322 {"fmaf32", "__builtin_fmaf"},
323 {"fmaf64", "__builtin_fma"},
325 {"fabsf32", "__builtin_fabsf"},
326 {"fabsf64", "__builtin_fabs"},
328 {"minnumf32", "__builtin_fminf"},
329 {"minnumf64", "__builtin_fmin"},
331 {"maxnumf32", "__builtin_fmaxf"},
332 {"maxnumf64", "__builtin_fmax"},
334 {"copysignf32", "__builtin_copysignf"},
335 {"copysignf64", "__builtin_copysign"},
337 {"floorf32", "__builtin_floorf"},
338 {"floorf64", "__builtin_floor"},
340 {"ceilf32", "__builtin_ceilf"},
341 {"ceilf64", "__builtin_ceil"},
343 {"truncf32", "__builtin_truncf"},
344 {"truncf64", "__builtin_trunc"},
346 {"rintf32", "__builtin_rintf"},
347 {"rintf64", "__builtin_rint"},
349 {"nearbyintf32", "__builtin_nearbyintf"},
350 {"nearbyintf64", "__builtin_nearbyint"},
352 {"roundf32", "__builtin_roundf"},
353 {"roundf64", "__builtin_round"},
358 BuiltinsContext::setup ()
360 define_builtin_types ();
361 define_builtin_attributes ();
364 register_rust_mappings ();
368 BuiltinsContext::lookup_gcc_builtin (const std::string
&name
, tree
*builtin
)
370 auto it
= builtin_functions
.find (name
);
371 if (it
== builtin_functions
.end ())
374 *builtin
= it
->second
;
378 } // namespace Compile