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