libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / backend / rust-builtins.cc
blob282ecba70cbf011371236e7c9b6f99e1a326be2b
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
6 // version.
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.
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"
21 #include "target.h"
22 #include "stringpool.h"
24 namespace Rust {
25 namespace Compile {
27 BuiltinsContext &
28 BuiltinsContext::get ()
30 static BuiltinsContext instance;
31 return instance;
34 bool
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 (); }
48 /**
49 * Define a function type according to `builtin-types.def`
51 * *Heavily* inspired by the D frontend's `def_fn_type` function
53 void
54 BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
55 bool is_variadic, size_t n, ...)
57 va_list list;
58 va_start (list, 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
65 // though '...'.
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;
77 va_end (list);
78 return;
81 auto fn_type = NULL_TREE;
82 if (is_variadic)
83 fn_type = build_varargs_function_type_array (return_type, n, args.data ());
84 else
85 fn_type = build_function_type_array (return_type, n, args.data ());
87 builtin_types[def_idx] = fn_type;
88 va_end (list);
91 // Taken directly from the D frontend
92 static void
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;
114 else
115 gcc_unreachable ();
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
125 void
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, \
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]);
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
222 void
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
241 #undef DEF_ATTR_INT
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
249 * `BuiltinsContext`.
251 void
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)
259 return;
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) \
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
282 * Register direct mappings between Rust functions and GCC builtins
284 void
285 BuiltinsContext::register_rust_mappings ()
287 rust_intrinsic_to_gcc_builtin = {
288 {"unreachable", "__builtin_unreachable"},
289 {"abort", "__builtin_abort"},
291 // Math intrinsics
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"},
357 void
358 BuiltinsContext::setup ()
360 define_builtin_types ();
361 define_builtin_attributes ();
362 define_builtins ();
364 register_rust_mappings ();
367 bool
368 BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
370 auto it = builtin_functions.find (name);
371 if (it == builtin_functions.end ())
372 return false;
374 *builtin = it->second;
375 return true;
378 } // namespace Compile
379 } // namespace Rust