]>
Commit | Line | Data |
---|---|---|
e53b6e56 | 1 | /* jit-builtins.cc -- Handling of builtin functions during JIT-compilation. |
a945c346 | 2 | Copyright (C) 2014-2024 Free Software Foundation, Inc. |
35485da9 DM |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
35485da9 | 23 | #include "target.h" |
2adfab87 | 24 | #include "jit-playback.h" |
eeafb319 | 25 | #include "stringpool.h" |
35485da9 | 26 | |
35485da9 | 27 | #include "jit-builtins.h" |
35485da9 DM |
28 | |
29 | namespace gcc { | |
30 | ||
31 | namespace jit { | |
32 | ||
35485da9 DM |
33 | const char *const prefix = "__builtin_"; |
34 | const size_t prefix_len = strlen (prefix); | |
35 | ||
36 | /* Create "builtin_data", a const table of the data within builtins.def. */ | |
37 | struct builtin_data | |
38 | { | |
39 | const char *name; | |
eeafb319 | 40 | enum built_in_class fnclass; |
35485da9 DM |
41 | enum jit_builtin_type type; |
42 | bool both_p; | |
43 | bool fallback_p; | |
eeafb319 DM |
44 | enum built_in_attribute attr; |
45 | bool implicit_p; | |
35485da9 DM |
46 | |
47 | const char *get_asm_name () const | |
48 | { | |
49 | if (both_p && fallback_p) | |
50 | return name + prefix_len; | |
51 | else | |
52 | return name; | |
53 | } | |
54 | }; | |
55 | ||
eeafb319 DM |
56 | #define DEF_BUILTIN(X, NAME, CLASS, TYPE, LT, BOTH_P, FALLBACK_P, \ |
57 | NONANSI_P, ATTRS, IMPLICIT, COND) \ | |
58 | {NAME, CLASS, TYPE, BOTH_P, FALLBACK_P, ATTRS, IMPLICIT}, | |
35485da9 DM |
59 | static const struct builtin_data builtin_data[] = |
60 | { | |
61 | #include "builtins.def" | |
62 | }; | |
35485da9 DM |
63 | |
64 | /* Helper function for find_builtin_by_name. */ | |
65 | ||
66 | static bool | |
67 | matches_builtin (const char *in_name, | |
68 | const struct builtin_data& bd) | |
69 | { | |
70 | const bool debug = 0; | |
595ced60 DM |
71 | |
72 | /* Ignore entries with a NULL name. */ | |
73 | if (!bd.name) | |
74 | return false; | |
35485da9 DM |
75 | |
76 | if (debug) | |
77 | fprintf (stderr, "seen builtin: %s\n", bd.name); | |
78 | ||
01512446 JJ |
79 | if (strcmp (bd.name, in_name) == 0) |
80 | return true; | |
35485da9 DM |
81 | |
82 | if (bd.both_p) | |
83 | { | |
84 | /* Then the macros in builtins.def gave a "__builtin_" | |
85 | prefix to bd.name, but we should also recognize the form | |
86 | without the prefix. */ | |
01512446 | 87 | gcc_assert (strncmp (bd.name, prefix, prefix_len) == 0); |
35485da9 DM |
88 | if (debug) |
89 | fprintf (stderr, "testing without prefix as: %s\n", | |
90 | bd.name + prefix_len); | |
01512446 JJ |
91 | if (strcmp (bd.name + prefix_len, in_name) == 0) |
92 | return true; | |
35485da9 DM |
93 | } |
94 | ||
95 | return false; | |
96 | } | |
97 | ||
98 | /* Locate the built-in function that matches name IN_NAME, | |
99 | writing the result to OUT_ID and returning true if found, | |
100 | or returning false if not found. */ | |
101 | ||
102 | static bool | |
103 | find_builtin_by_name (const char *in_name, | |
104 | enum built_in_function *out_id) | |
105 | { | |
106 | /* Locate builtin. This currently works by performing repeated | |
107 | strcmp against every possible candidate, which is likely to | |
108 | inefficient. | |
109 | ||
110 | We start at index 1 to skip the initial entry (BUILT_IN_NONE), which | |
111 | has a NULL name. */ | |
ca32b29e | 112 | for (unsigned int i = 1; i < ARRAY_SIZE (builtin_data); i++) |
35485da9 DM |
113 | { |
114 | const struct builtin_data& bd = builtin_data[i]; | |
115 | if (matches_builtin (in_name, bd)) | |
116 | { | |
117 | /* Found a match. */ | |
118 | *out_id = static_cast<enum built_in_function> (i); | |
119 | return true; | |
120 | } | |
121 | } | |
122 | ||
123 | /* Not found. */ | |
124 | return false; | |
125 | } | |
126 | ||
127 | // class builtins_manager | |
128 | ||
eeafb319 | 129 | /* Constructor for gcc::jit::builtins_manager. */ |
35485da9 | 130 | |
eeafb319 | 131 | builtins_manager::builtins_manager (recording::context *ctxt) |
35485da9 DM |
132 | : m_ctxt (ctxt) |
133 | { | |
134 | memset (m_types, 0, sizeof (m_types)); | |
135 | memset (m_builtin_functions, 0, sizeof (m_builtin_functions)); | |
eeafb319 | 136 | memset (m_attributes, 0, sizeof (m_attributes)); |
35485da9 DM |
137 | } |
138 | ||
139 | /* Locate a builtin function by name. | |
140 | Create a recording::function of the appropriate type, reusing them | |
141 | if they've already been seen. */ | |
142 | ||
eeafb319 | 143 | recording::function * |
35485da9 DM |
144 | builtins_manager::get_builtin_function (const char *name) |
145 | { | |
146 | enum built_in_function builtin_id; | |
147 | if (!find_builtin_by_name (name, &builtin_id)) | |
148 | { | |
149 | m_ctxt->add_error (NULL, "builtin \"%s\" not found", name); | |
150 | return NULL; | |
151 | } | |
152 | ||
eeafb319 DM |
153 | return get_builtin_function_by_id (builtin_id); |
154 | } | |
155 | ||
156 | /* Locate a builtin function by id. | |
157 | Create a recording::function of the appropriate type, reusing them | |
158 | if they've already been seen. */ | |
159 | ||
160 | recording::function * | |
161 | builtins_manager::get_builtin_function_by_id (enum built_in_function builtin_id) | |
162 | { | |
b258e263 | 163 | gcc_assert (builtin_id > BUILT_IN_NONE); |
35485da9 DM |
164 | gcc_assert (builtin_id < END_BUILTINS); |
165 | ||
166 | /* Lazily build the functions, caching them so that repeated calls for | |
167 | the same id on a context give back the same object. */ | |
168 | if (!m_builtin_functions[builtin_id]) | |
169 | { | |
eeafb319 | 170 | recording::function *fn = make_builtin_function (builtin_id); |
23844fd7 DM |
171 | if (fn) |
172 | { | |
173 | m_builtin_functions[builtin_id] = fn; | |
174 | m_ctxt->record (fn); | |
175 | } | |
35485da9 DM |
176 | } |
177 | ||
178 | return m_builtin_functions[builtin_id]; | |
179 | } | |
180 | ||
181 | /* Create the recording::function for a given builtin function, by ID. */ | |
182 | ||
eeafb319 | 183 | recording::function * |
35485da9 DM |
184 | builtins_manager::make_builtin_function (enum built_in_function builtin_id) |
185 | { | |
186 | const struct builtin_data& bd = builtin_data[builtin_id]; | |
187 | enum jit_builtin_type type_id = bd.type; | |
eeafb319 | 188 | recording::type *t = get_type (type_id); |
23844fd7 DM |
189 | if (!t) |
190 | return NULL; | |
eeafb319 | 191 | recording::function_type *func_type = t->as_a_function_type (); |
35485da9 DM |
192 | if (!func_type) |
193 | return NULL; | |
194 | ||
eeafb319 | 195 | vec<recording::type *> param_types = func_type->get_param_types (); |
35485da9 DM |
196 | recording::param **params = new recording::param *[param_types.length ()]; |
197 | ||
198 | int i; | |
eeafb319 | 199 | recording::type *param_type; |
35485da9 DM |
200 | FOR_EACH_VEC_ELT (param_types, i, param_type) |
201 | { | |
202 | char buf[16]; | |
203 | snprintf (buf, 16, "arg%d", i); | |
204 | params[i] = m_ctxt->new_param (NULL, | |
205 | param_type, | |
206 | buf); | |
207 | } | |
208 | const char *asm_name = bd.get_asm_name (); | |
eeafb319 DM |
209 | recording::function *result = |
210 | new recording::function (m_ctxt, | |
211 | NULL, | |
212 | GCC_JIT_FUNCTION_IMPORTED, // FIXME | |
213 | func_type->get_return_type (), | |
214 | m_ctxt->new_string (asm_name), | |
215 | param_types.length (), | |
216 | params, | |
217 | func_type->is_variadic (), | |
218 | builtin_id); | |
35485da9 | 219 | delete[] params; |
eeafb319 DM |
220 | |
221 | /* PR/64020 - If the client code is using builtin cos or sin, | |
222 | tree-ssa-math-opt.c's execute_cse_sincos_1 may attempt | |
223 | to optimize them to use __builtin_cexpi; for this, | |
224 | BUILT_IN_CEXPI needs to exist. | |
225 | ||
226 | Hence query the cache for BUILT_IN_CEXPI to ensure it gets | |
227 | built. */ | |
228 | if (builtin_id == BUILT_IN_COS || builtin_id == BUILT_IN_SIN) | |
229 | (void)get_builtin_function_by_id (BUILT_IN_CEXPI); | |
230 | ||
e53b6e56 | 231 | /* builtins.cc:expand_builtin_cexpi can optimize the various |
eeafb319 DM |
232 | CEXP builtins to SINCOS builtins, and hence we may require |
233 | SINCOS builtins latter. | |
234 | ||
235 | Ensure the appropriate SINCOS builtin exists. */ | |
236 | if (builtin_id == BUILT_IN_CEXPIF) | |
237 | (void)get_builtin_function_by_id (BUILT_IN_SINCOSF); | |
238 | else if (builtin_id == BUILT_IN_CEXPI) | |
239 | (void)get_builtin_function_by_id (BUILT_IN_SINCOS); | |
240 | else if (builtin_id == BUILT_IN_CEXPIL) | |
241 | (void)get_builtin_function_by_id (BUILT_IN_SINCOSL); | |
242 | ||
35485da9 DM |
243 | return result; |
244 | } | |
245 | ||
bf40f0ba DM |
246 | /* Build an array of type names for use by get_string_for_type_id. */ |
247 | ||
248 | static const char * const type_names[] = { | |
249 | #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) #ENUM, | |
250 | #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) #ENUM, | |
251 | #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) #ENUM, | |
252 | #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) #ENUM, | |
253 | #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) #ENUM, | |
254 | #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) #ENUM, | |
255 | #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) #ENUM, | |
256 | #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
257 | ARG6) \ | |
258 | #ENUM, | |
259 | #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
260 | ARG6, ARG7) \ | |
261 | #ENUM, | |
262 | #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
263 | ARG6, ARG7, ARG8) \ | |
264 | #ENUM, | |
265 | #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
266 | ARG6, ARG7, ARG8, ARG9) \ | |
267 | #ENUM, | |
268 | #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
269 | ARG6, ARG7, ARG8, ARG9, ARG10) \ | |
270 | #ENUM, | |
271 | #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
272 | ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \ | |
273 | #ENUM, | |
274 | #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) #ENUM, | |
275 | #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) #ENUM, | |
276 | #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) #ENUM, | |
277 | #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) #ENUM, | |
278 | #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) #ENUM, | |
279 | #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ | |
280 | #ENUM, | |
281 | #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
282 | ARG6) \ | |
283 | #ENUM, | |
284 | #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
285 | ARG6, ARG7) \ | |
286 | #ENUM, | |
287 | #define DEF_POINTER_TYPE(ENUM, TYPE) #ENUM, | |
288 | ||
289 | #include "builtin-types.def" | |
290 | ||
291 | #undef DEF_PRIMITIVE_TYPE | |
292 | #undef DEF_FUNCTION_TYPE_0 | |
293 | #undef DEF_FUNCTION_TYPE_1 | |
294 | #undef DEF_FUNCTION_TYPE_2 | |
295 | #undef DEF_FUNCTION_TYPE_3 | |
296 | #undef DEF_FUNCTION_TYPE_4 | |
297 | #undef DEF_FUNCTION_TYPE_5 | |
298 | #undef DEF_FUNCTION_TYPE_6 | |
299 | #undef DEF_FUNCTION_TYPE_7 | |
300 | #undef DEF_FUNCTION_TYPE_8 | |
301 | #undef DEF_FUNCTION_TYPE_9 | |
302 | #undef DEF_FUNCTION_TYPE_10 | |
303 | #undef DEF_FUNCTION_TYPE_11 | |
304 | #undef DEF_FUNCTION_TYPE_VAR_0 | |
305 | #undef DEF_FUNCTION_TYPE_VAR_1 | |
306 | #undef DEF_FUNCTION_TYPE_VAR_2 | |
307 | #undef DEF_FUNCTION_TYPE_VAR_3 | |
308 | #undef DEF_FUNCTION_TYPE_VAR_4 | |
309 | #undef DEF_FUNCTION_TYPE_VAR_5 | |
310 | #undef DEF_FUNCTION_TYPE_VAR_6 | |
311 | #undef DEF_FUNCTION_TYPE_VAR_7 | |
312 | #undef DEF_POINTER_TYPE | |
313 | }; | |
314 | ||
315 | /* Get a string for TYPE_ID suitable for use in logs and error messages | |
316 | (e.g. "BT_PID"). */ | |
317 | ||
318 | static const char * | |
319 | get_string_for_type_id (enum jit_builtin_type type_id) | |
320 | { | |
ca32b29e | 321 | gcc_assert (type_id < ARRAY_SIZE (type_names)); |
bf40f0ba DM |
322 | return type_names[type_id]; |
323 | } | |
324 | ||
35485da9 DM |
325 | /* Get the recording::type for a given type of builtin function, |
326 | by ID, creating it if it doesn't already exist. */ | |
327 | ||
eeafb319 | 328 | recording::type * |
35485da9 DM |
329 | builtins_manager::get_type (enum jit_builtin_type type_id) |
330 | { | |
331 | if (!m_types[type_id]) | |
332 | m_types[type_id] = make_type (type_id); | |
333 | return m_types[type_id]; | |
334 | } | |
335 | ||
336 | /* Create the recording::type for a given type of builtin function. */ | |
337 | ||
eeafb319 | 338 | recording::type * |
35485da9 DM |
339 | builtins_manager::make_type (enum jit_builtin_type type_id) |
340 | { | |
341 | /* Use builtin-types.def to construct a switch statement, with each | |
342 | case deferring to one of the methods below: | |
343 | - DEF_PRIMITIVE_TYPE is handled as a call to make_primitive_type. | |
344 | - the various DEF_FUNCTION_TYPE_n are handled by variadic calls | |
345 | to make_fn_type. | |
346 | - similarly for DEF_FUNCTION_TYPE_VAR_n, but setting the | |
347 | "is_variadic" argument. | |
348 | - DEF_POINTER_TYPE is handled by make_ptr_type. | |
349 | That should handle everything, but just in case we also suppy a | |
350 | gcc_unreachable default clause. */ | |
351 | switch (type_id) | |
352 | { | |
353 | #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ | |
354 | case ENUM: return make_primitive_type (ENUM); | |
355 | #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ | |
356 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 0); | |
357 | #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ | |
358 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 1, ARG1); | |
359 | #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ | |
360 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2); | |
361 | #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ | |
362 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3); | |
363 | #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ | |
56a9f6bc TS |
364 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, \ |
365 | ARG4); | |
366 | #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ | |
367 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, \ | |
368 | ARG4, ARG5); | |
35485da9 DM |
369 | #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
370 | ARG6) \ | |
56a9f6bc TS |
371 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, \ |
372 | ARG4, ARG5, ARG6); | |
35485da9 DM |
373 | #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
374 | ARG6, ARG7) \ | |
56a9f6bc TS |
375 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, \ |
376 | ARG4, ARG5, ARG6, ARG7); | |
35485da9 DM |
377 | #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
378 | ARG6, ARG7, ARG8) \ | |
56a9f6bc TS |
379 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \ |
380 | ARG4, ARG5, ARG6, ARG7, ARG8); | |
d9a6bd32 JJ |
381 | #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
382 | ARG6, ARG7, ARG8, ARG9) \ | |
383 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, \ | |
384 | ARG4, ARG5, ARG6, ARG7, ARG8, ARG9); | |
385 | #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
386 | ARG6, ARG7, ARG8, ARG9, ARG10) \ | |
387 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, \ | |
388 | ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ | |
389 | ARG10); | |
390 | #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ | |
391 | ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \ | |
392 | case ENUM: return make_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, \ | |
393 | ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ | |
394 | ARG10, ARG11); | |
35485da9 DM |
395 | #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ |
396 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 0); | |
397 | #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ | |
398 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 1, ARG1); | |
399 | #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ | |
400 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2); | |
401 | #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ | |
402 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3); | |
403 | #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ | |
56a9f6bc TS |
404 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, \ |
405 | ARG4); | |
35485da9 | 406 | #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ |
56a9f6bc TS |
407 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, \ |
408 | ARG4, ARG5); | |
20a44562 MK |
409 | #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
410 | ARG6) \ | |
411 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, \ | |
412 | ARG4, ARG5, ARG6); | |
56a9f6bc TS |
413 | #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ |
414 | ARG6, ARG7) \ | |
415 | case ENUM: return make_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, \ | |
416 | ARG4, ARG5, ARG6, ARG7); | |
35485da9 DM |
417 | #define DEF_POINTER_TYPE(ENUM, TYPE) \ |
418 | case ENUM: return make_ptr_type (ENUM, TYPE); | |
419 | ||
420 | #include "builtin-types.def" | |
421 | ||
422 | #undef DEF_PRIMITIVE_TYPE | |
eeafb319 | 423 | #undef DEF_FUNCTION_TYPE_0 |
35485da9 DM |
424 | #undef DEF_FUNCTION_TYPE_1 |
425 | #undef DEF_FUNCTION_TYPE_2 | |
426 | #undef DEF_FUNCTION_TYPE_3 | |
427 | #undef DEF_FUNCTION_TYPE_4 | |
428 | #undef DEF_FUNCTION_TYPE_5 | |
429 | #undef DEF_FUNCTION_TYPE_6 | |
eeafb319 DM |
430 | #undef DEF_FUNCTION_TYPE_7 |
431 | #undef DEF_FUNCTION_TYPE_8 | |
d9a6bd32 JJ |
432 | #undef DEF_FUNCTION_TYPE_9 |
433 | #undef DEF_FUNCTION_TYPE_10 | |
434 | #undef DEF_FUNCTION_TYPE_11 | |
35485da9 DM |
435 | #undef DEF_FUNCTION_TYPE_VAR_0 |
436 | #undef DEF_FUNCTION_TYPE_VAR_1 | |
437 | #undef DEF_FUNCTION_TYPE_VAR_2 | |
438 | #undef DEF_FUNCTION_TYPE_VAR_3 | |
439 | #undef DEF_FUNCTION_TYPE_VAR_4 | |
440 | #undef DEF_FUNCTION_TYPE_VAR_5 | |
20a44562 | 441 | #undef DEF_FUNCTION_TYPE_VAR_6 |
56a9f6bc | 442 | #undef DEF_FUNCTION_TYPE_VAR_7 |
35485da9 DM |
443 | #undef DEF_POINTER_TYPE |
444 | ||
445 | default: | |
446 | gcc_unreachable (); | |
447 | } | |
448 | } | |
449 | ||
450 | /* Create the recording::type for a given primitive type within the | |
451 | builtin system. | |
452 | ||
453 | Only some types are currently supported. */ | |
454 | ||
eeafb319 | 455 | recording::type* |
35485da9 DM |
456 | builtins_manager::make_primitive_type (enum jit_builtin_type type_id) |
457 | { | |
458 | switch (type_id) | |
459 | { | |
460 | default: | |
461 | // only some of these types are implemented so far: | |
462 | m_ctxt->add_error (NULL, | |
bf40f0ba DM |
463 | "unimplemented primitive type for builtin (type: %s)", |
464 | get_string_for_type_id (type_id)); | |
35485da9 DM |
465 | return NULL; |
466 | ||
467 | case BT_VOID: return m_ctxt->get_type (GCC_JIT_TYPE_VOID); | |
468 | case BT_BOOL: return m_ctxt->get_type (GCC_JIT_TYPE_BOOL); | |
469 | case BT_INT: return m_ctxt->get_type (GCC_JIT_TYPE_INT); | |
470 | case BT_UINT: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_INT); | |
471 | case BT_LONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG); | |
472 | case BT_ULONG: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG); | |
473 | case BT_LONGLONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_LONG); | |
474 | case BT_ULONGLONG: | |
475 | return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG_LONG); | |
35485da9 DM |
476 | // case BT_INTMAX: |
477 | // case BT_UINTMAX: | |
bf40f0ba DM |
478 | case BT_INT8: return m_ctxt->get_int_type (1, true); |
479 | case BT_INT16: return m_ctxt->get_int_type (2, true); | |
480 | case BT_UINT8: return m_ctxt->get_int_type (1, false); | |
35485da9 DM |
481 | case BT_UINT16: return m_ctxt->get_int_type (2, false); |
482 | case BT_UINT32: return m_ctxt->get_int_type (4, false); | |
483 | case BT_UINT64: return m_ctxt->get_int_type (8, false); | |
af80ea97 | 484 | case BT_UINT128: return m_ctxt->get_int_type (16, false); |
35485da9 DM |
485 | // case BT_WORD: |
486 | // case BT_UNWINDWORD: | |
487 | case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT); | |
488 | case BT_DOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE); | |
489 | case BT_LONGDOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_DOUBLE); | |
bf40f0ba DM |
490 | // case BT_FLOAT16: |
491 | // case BT_FLOAT32: | |
492 | // case BT_FLOAT64: | |
493 | // case BT_FLOAT128: | |
494 | // case BT_FLOAT32X: | |
495 | // case BT_FLOAT64X: | |
496 | // case BT_FLOAT128X: | |
eeafb319 DM |
497 | case BT_COMPLEX_FLOAT: |
498 | return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_FLOAT); | |
499 | case BT_COMPLEX_DOUBLE: | |
500 | return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_DOUBLE); | |
501 | case BT_COMPLEX_LONGDOUBLE: | |
502 | return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE); | |
35485da9 DM |
503 | case BT_PTR: return m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR); |
504 | case BT_FILEPTR: return m_ctxt->get_type (GCC_JIT_TYPE_FILE_PTR); | |
bf40f0ba DM |
505 | // case BT_CONST_TM_PTR: |
506 | // case BT_FENV_T_PTR: | |
507 | // case BT_CONST_FENV_T_PTR: | |
508 | // case BT_FEXCEPT_T_PTR: | |
509 | // case BT_CONST_FEXCEPT_T_PTR: | |
510 | case BT_CONST_PTR: | |
511 | return m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_const ()->get_pointer (); | |
512 | case BT_VOLATILE_PTR: | |
513 | return (m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_volatile () | |
514 | ->get_pointer ()); | |
6d36cc21 DM |
515 | case BT_CONST_VOLATILE_PTR: |
516 | return (m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_const () | |
517 | ->get_volatile ()->get_pointer ()); | |
35485da9 | 518 | // case BT_PTRMODE: |
bf40f0ba DM |
519 | case BT_INT_PTR: |
520 | return m_ctxt->get_type (GCC_JIT_TYPE_INT)->get_pointer (); | |
521 | case BT_FLOAT_PTR: | |
522 | return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT)->get_pointer (); | |
eeafb319 DM |
523 | case BT_DOUBLE_PTR: |
524 | return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_pointer (); | |
bf40f0ba DM |
525 | case BT_CONST_DOUBLE_PTR: |
526 | return (m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_const () | |
527 | ->get_pointer ()); | |
35485da9 DM |
528 | // case BT_LONGDOUBLE_PTR: |
529 | // case BT_PID: | |
bf40f0ba DM |
530 | case BT_SIZE: |
531 | return m_ctxt->get_type (GCC_JIT_TYPE_SIZE_T); | |
532 | case BT_CONST_SIZE: | |
533 | return m_ctxt->get_type (GCC_JIT_TYPE_SIZE_T)->get_const (); | |
35485da9 DM |
534 | // case BT_SSIZE: |
535 | // case BT_WINT: | |
536 | // case BT_STRING: | |
537 | case BT_CONST_STRING: return m_ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR); | |
538 | // case BT_DFLOAT32: | |
539 | // case BT_DFLOAT64: | |
540 | // case BT_DFLOAT128: | |
35485da9 DM |
541 | // case BT_VALIST_REF: |
542 | // case BT_VALIST_ARG: | |
611fdb0f AB |
543 | case BT_I1: return m_ctxt->get_int_type (1, true); |
544 | case BT_I2: return m_ctxt->get_int_type (2, true); | |
545 | case BT_I4: return m_ctxt->get_int_type (4, true); | |
546 | case BT_I8: return m_ctxt->get_int_type (8, true); | |
547 | case BT_I16: return m_ctxt->get_int_type (16, true); | |
bf40f0ba | 548 | // case BT_PTR_CONST_STRING: |
35485da9 DM |
549 | } |
550 | } | |
551 | ||
552 | /* Create the recording::function_type for a given function type | |
553 | signature. */ | |
554 | ||
eeafb319 | 555 | recording::function_type * |
35485da9 DM |
556 | builtins_manager::make_fn_type (enum jit_builtin_type, |
557 | enum jit_builtin_type return_type_id, | |
558 | bool is_variadic, | |
559 | int num_args, ...) | |
560 | { | |
561 | va_list list; | |
562 | int i; | |
eeafb319 DM |
563 | recording::type **param_types = new recording::type *[num_args]; |
564 | recording::type *return_type = NULL; | |
565 | recording::function_type *result = NULL; | |
35485da9 DM |
566 | |
567 | va_start (list, num_args); | |
568 | for (i = 0; i < num_args; ++i) | |
569 | { | |
570 | enum jit_builtin_type arg_type_id = | |
571 | (enum jit_builtin_type) va_arg (list, int); | |
572 | param_types[i] = get_type (arg_type_id); | |
573 | if (!param_types[i]) | |
574 | goto error; | |
575 | } | |
576 | va_end (list); | |
577 | ||
578 | return_type = get_type (return_type_id); | |
579 | if (!return_type) | |
580 | goto error; | |
581 | ||
c8d19a69 DM |
582 | result = m_ctxt->new_function_type (return_type, |
583 | num_args, | |
584 | param_types, | |
585 | is_variadic); | |
35485da9 DM |
586 | |
587 | error: | |
588 | delete[] param_types; | |
589 | return result; | |
590 | } | |
591 | ||
592 | /* Handler for DEF_POINTER_TYPE within builtins_manager::make_type. */ | |
593 | ||
eeafb319 | 594 | recording::type * |
35485da9 DM |
595 | builtins_manager::make_ptr_type (enum jit_builtin_type, |
596 | enum jit_builtin_type other_type_id) | |
597 | { | |
eeafb319 | 598 | recording::type *base_type = get_type (other_type_id); |
35485da9 DM |
599 | return base_type->get_pointer (); |
600 | } | |
601 | ||
b258e263 DM |
602 | /* Ensure that builtins that could be needed during optimization |
603 | get created ahead of time. */ | |
604 | ||
605 | void | |
606 | builtins_manager::ensure_optimization_builtins_exist () | |
607 | { | |
608 | /* build_common_builtin_nodes does most of this, but not all. | |
609 | We can't loop through all of the builtin_data array, we don't | |
610 | support all types yet. */ | |
611 | (void)get_builtin_function_by_id (BUILT_IN_TRAP); | |
612 | } | |
613 | ||
eeafb319 DM |
614 | /* Playback support. */ |
615 | ||
616 | /* A builtins_manager is associated with a recording::context | |
617 | and might be reused for multiple compiles on various | |
618 | playback::contexts, perhaps with different options. | |
619 | ||
620 | Purge any playback state. Currently this is just the table of | |
621 | attributes. */ | |
622 | ||
623 | void | |
624 | builtins_manager::finish_playback (void) | |
625 | { | |
626 | memset (m_attributes, 0, sizeof (m_attributes)); | |
627 | } | |
628 | ||
629 | /* Get the enum built_in_class for BUILTIN_ID. */ | |
630 | ||
631 | enum built_in_class | |
632 | builtins_manager::get_class (enum built_in_function builtin_id) | |
633 | { | |
634 | return builtin_data[builtin_id].fnclass; | |
635 | } | |
636 | ||
637 | /* Is BUILTIN_ID implicit? */ | |
638 | ||
639 | bool | |
640 | builtins_manager::implicit_p (enum built_in_function builtin_id) | |
641 | { | |
642 | return builtin_data[builtin_id].implicit_p; | |
643 | } | |
644 | ||
645 | /* Get any attributes (in tree form) for the function declaration | |
646 | for BUILTIN_ID. | |
647 | ||
648 | These are created on-demand, and cached within the m_attributes | |
649 | array, until finish_playback. */ | |
650 | ||
651 | tree | |
652 | builtins_manager::get_attrs_tree (enum built_in_function builtin_id) | |
653 | { | |
654 | enum built_in_attribute attr = builtin_data[builtin_id].attr; | |
655 | return get_attrs_tree (attr); | |
656 | } | |
657 | ||
658 | /* As above, but for an enum built_in_attribute. */ | |
659 | ||
660 | tree | |
661 | builtins_manager::get_attrs_tree (enum built_in_attribute attr) | |
662 | { | |
663 | gcc_assert (attr < ATTR_LAST); | |
664 | if (!m_attributes [attr]) | |
665 | m_attributes [attr] = make_attrs_tree (attr); | |
666 | return m_attributes [attr]; | |
667 | } | |
668 | ||
669 | /* Handle a cache-miss within the m_attributes array by | |
670 | generating the attributes for enum built_in_attribute | |
671 | in tree form. */ | |
672 | ||
673 | tree | |
674 | builtins_manager::make_attrs_tree (enum built_in_attribute attr) | |
675 | { | |
676 | switch (attr) | |
677 | { | |
678 | /* Generate cases from builtin-attrs.def. */ | |
679 | #define DEF_ATTR_NULL_TREE(ENUM) \ | |
680 | case ENUM: return NULL_TREE; | |
681 | #define DEF_ATTR_INT(ENUM, VALUE) \ | |
682 | case ENUM: return build_int_cst (integer_type_node, VALUE); | |
683 | #define DEF_ATTR_STRING(ENUM, VALUE) \ | |
684 | case ENUM: return build_string (strlen (VALUE), VALUE); | |
685 | #define DEF_ATTR_IDENT(ENUM, STRING) \ | |
686 | case ENUM: return get_identifier (STRING); | |
687 | #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \ | |
688 | case ENUM: return tree_cons (get_attrs_tree (PURPOSE), \ | |
689 | get_attrs_tree (VALUE), \ | |
690 | get_attrs_tree (CHAIN)); | |
691 | #include "builtin-attrs.def" | |
692 | #undef DEF_ATTR_NULL_TREE | |
693 | #undef DEF_ATTR_INT | |
694 | #undef DEF_ATTR_IDENT | |
695 | #undef DEF_ATTR_TREE_LIST | |
696 | ||
697 | default: | |
698 | /* We somehow got a value not covered by the autogenerated | |
699 | cases. */ | |
700 | gcc_unreachable (); | |
701 | return NULL; | |
702 | } | |
703 | } | |
704 | ||
35485da9 DM |
705 | } // namespace jit |
706 | } // namespace gcc |