1 /* jit-builtins.c -- Handling of builtin functions during JIT-compilation.
2 Copyright (C) 2014 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
22 #include "coretypes.h"
27 #include "jit-common.h"
28 #include "jit-builtins.h"
29 #include "jit-recording.h"
37 const char *const prefix
= "__builtin_";
38 const size_t prefix_len
= strlen (prefix
);
40 /* Create "builtin_data", a const table of the data within builtins.def. */
44 enum jit_builtin_type type
;
48 const char *get_asm_name () const
50 if (both_p
&& fallback_p
)
51 return name
+ prefix_len
;
57 #define DEF_BUILTIN(X, NAME, C, TYPE, LT, BOTH_P, FALLBACK_P, NA, AT, IM, COND)\
58 {NAME, TYPE, BOTH_P, FALLBACK_P},
59 static const struct builtin_data builtin_data
[] =
61 #include "builtins.def"
65 /* Helper function for find_builtin_by_name. */
68 matches_builtin (const char *in_name
,
69 const struct builtin_data
& bd
)
75 fprintf (stderr
, "seen builtin: %s\n", bd
.name
);
77 if (0 == strcmp (bd
.name
, in_name
))
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. */
87 gcc_assert (0 == strncmp (bd
.name
, prefix
, prefix_len
));
89 fprintf (stderr
, "testing without prefix as: %s\n",
90 bd
.name
+ prefix_len
);
91 if (0 == strcmp (bd
.name
+ prefix_len
, in_name
))
100 /* Locate the built-in function that matches name IN_NAME,
101 writing the result to OUT_ID and returning true if found,
102 or returning false if not found. */
105 find_builtin_by_name (const char *in_name
,
106 enum built_in_function
*out_id
)
108 /* Locate builtin. This currently works by performing repeated
109 strcmp against every possible candidate, which is likely to
112 We start at index 1 to skip the initial entry (BUILT_IN_NONE), which
114 for (unsigned int i
= 1;
115 i
< sizeof (builtin_data
) / sizeof (builtin_data
[0]);
118 const struct builtin_data
& bd
= builtin_data
[i
];
119 if (matches_builtin (in_name
, bd
))
122 *out_id
= static_cast<enum built_in_function
> (i
);
131 // class builtins_manager
133 /* Constructor for gcc::jit::recording::builtins_manager. */
135 builtins_manager::builtins_manager (context
*ctxt
)
138 memset (m_types
, 0, sizeof (m_types
));
139 memset (m_builtin_functions
, 0, sizeof (m_builtin_functions
));
142 /* Locate a builtin function by name.
143 Create a recording::function of the appropriate type, reusing them
144 if they've already been seen. */
147 builtins_manager::get_builtin_function (const char *name
)
149 enum built_in_function builtin_id
;
150 if (!find_builtin_by_name (name
, &builtin_id
))
152 m_ctxt
->add_error (NULL
, "builtin \"%s\" not found", name
);
156 gcc_assert (builtin_id
>= 0);
157 gcc_assert (builtin_id
< END_BUILTINS
);
159 /* Lazily build the functions, caching them so that repeated calls for
160 the same id on a context give back the same object. */
161 if (!m_builtin_functions
[builtin_id
])
163 m_builtin_functions
[builtin_id
] = make_builtin_function (builtin_id
);
164 m_ctxt
->record (m_builtin_functions
[builtin_id
]);
167 return m_builtin_functions
[builtin_id
];
170 /* Create the recording::function for a given builtin function, by ID. */
173 builtins_manager::make_builtin_function (enum built_in_function builtin_id
)
175 const struct builtin_data
& bd
= builtin_data
[builtin_id
];
176 enum jit_builtin_type type_id
= bd
.type
;
177 function_type
*func_type
= get_type (type_id
)->as_a_function_type ();
181 vec
<type
*> param_types
= func_type
->get_param_types ();
182 recording::param
**params
= new recording::param
*[param_types
.length ()];
186 FOR_EACH_VEC_ELT (param_types
, i
, param_type
)
189 snprintf (buf
, 16, "arg%d", i
);
190 params
[i
] = m_ctxt
->new_param (NULL
,
194 const char *asm_name
= bd
.get_asm_name ();
196 new function (m_ctxt
,
198 GCC_JIT_FUNCTION_IMPORTED
, // FIXME
199 func_type
->get_return_type (),
200 m_ctxt
->new_string (asm_name
),
201 param_types
.length (),
203 func_type
->is_variadic (),
209 /* Get the recording::type for a given type of builtin function,
210 by ID, creating it if it doesn't already exist. */
213 builtins_manager::get_type (enum jit_builtin_type type_id
)
215 if (!m_types
[type_id
])
216 m_types
[type_id
] = make_type (type_id
);
217 return m_types
[type_id
];
220 /* Create the recording::type for a given type of builtin function. */
223 builtins_manager::make_type (enum jit_builtin_type type_id
)
225 /* Use builtin-types.def to construct a switch statement, with each
226 case deferring to one of the methods below:
227 - DEF_PRIMITIVE_TYPE is handled as a call to make_primitive_type.
228 - the various DEF_FUNCTION_TYPE_n are handled by variadic calls
230 - similarly for DEF_FUNCTION_TYPE_VAR_n, but setting the
231 "is_variadic" argument.
232 - DEF_POINTER_TYPE is handled by make_ptr_type.
233 That should handle everything, but just in case we also suppy a
234 gcc_unreachable default clause. */
237 #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
238 case ENUM: return make_primitive_type (ENUM);
239 #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
240 case ENUM: return make_fn_type (ENUM, RETURN, 0, 0);
241 #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
242 case ENUM: return make_fn_type (ENUM, RETURN, 0, 1, ARG1);
243 #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
244 case ENUM: return make_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
245 #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
246 case ENUM: return make_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
247 #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
248 case ENUM: return make_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
249 #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
250 case ENUM: return make_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
251 #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
253 case ENUM: return make_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
254 #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
256 case ENUM: return make_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
257 #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
259 case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
261 #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
262 case ENUM: return make_fn_type (ENUM, RETURN, 1, 0);
263 #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
264 case ENUM: return make_fn_type (ENUM, RETURN, 1, 1, ARG1);
265 #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
266 case ENUM: return make_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
267 #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
268 case ENUM: return make_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
269 #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
270 case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
271 #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
272 case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
273 #define DEF_POINTER_TYPE(ENUM, TYPE) \
274 case ENUM: return make_ptr_type (ENUM, TYPE);
276 #include "builtin-types.def"
278 #undef DEF_PRIMITIVE_TYPE
279 #undef DEF_FUNCTION_TYPE_1
280 #undef DEF_FUNCTION_TYPE_2
281 #undef DEF_FUNCTION_TYPE_3
282 #undef DEF_FUNCTION_TYPE_4
283 #undef DEF_FUNCTION_TYPE_5
284 #undef DEF_FUNCTION_TYPE_6
285 #undef DEF_FUNCTION_TYPE_VAR_0
286 #undef DEF_FUNCTION_TYPE_VAR_1
287 #undef DEF_FUNCTION_TYPE_VAR_2
288 #undef DEF_FUNCTION_TYPE_VAR_3
289 #undef DEF_FUNCTION_TYPE_VAR_4
290 #undef DEF_FUNCTION_TYPE_VAR_5
291 #undef DEF_POINTER_TYPE
298 /* Create the recording::type for a given primitive type within the
301 Only some types are currently supported. */
304 builtins_manager::make_primitive_type (enum jit_builtin_type type_id
)
309 // only some of these types are implemented so far:
310 m_ctxt
->add_error (NULL
,
311 "unimplemented primitive type for builtin: %d", type_id
);
314 case BT_VOID
: return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
315 case BT_BOOL
: return m_ctxt
->get_type (GCC_JIT_TYPE_BOOL
);
316 case BT_INT
: return m_ctxt
->get_type (GCC_JIT_TYPE_INT
);
317 case BT_UINT
: return m_ctxt
->get_type (GCC_JIT_TYPE_UNSIGNED_INT
);
318 case BT_LONG
: return m_ctxt
->get_type (GCC_JIT_TYPE_LONG
);
319 case BT_ULONG
: return m_ctxt
->get_type (GCC_JIT_TYPE_UNSIGNED_LONG
);
320 case BT_LONGLONG
: return m_ctxt
->get_type (GCC_JIT_TYPE_LONG_LONG
);
322 return m_ctxt
->get_type (GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
327 case BT_UINT16
: return m_ctxt
->get_int_type (2, false);
328 case BT_UINT32
: return m_ctxt
->get_int_type (4, false);
329 case BT_UINT64
: return m_ctxt
->get_int_type (8, false);
331 // case BT_UNWINDWORD:
332 case BT_FLOAT
: return m_ctxt
->get_type (GCC_JIT_TYPE_FLOAT
);
333 case BT_DOUBLE
: return m_ctxt
->get_type (GCC_JIT_TYPE_DOUBLE
);
334 case BT_LONGDOUBLE
: return m_ctxt
->get_type (GCC_JIT_TYPE_LONG_DOUBLE
);
335 // case BT_COMPLEX_FLOAT:
336 // case BT_COMPLEX_DOUBLE:
337 // case BT_COMPLEX_LONGDOUBLE:
338 case BT_PTR
: return m_ctxt
->get_type (GCC_JIT_TYPE_VOID_PTR
);
339 case BT_FILEPTR
: return m_ctxt
->get_type (GCC_JIT_TYPE_FILE_PTR
);
341 // case BT_VOLATILE_PTR:
342 // case BT_CONST_VOLATILE_PTR:
345 // case BT_FLOAT_PTR:
346 // case BT_DOUBLE_PTR:
347 // case BT_CONST_DOUBLE_PTR:
348 // case BT_LONGDOUBLE_PTR:
354 case BT_CONST_STRING
: return m_ctxt
->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR
);
357 // case BT_DFLOAT128:
358 // case BT_DFLOAT32_PTR:
359 // case BT_DFLOAT64_PTR:
360 // case BT_DFLOAT128_PTR:
361 // case BT_VALIST_REF:
362 // case BT_VALIST_ARG:
371 /* Create the recording::function_type for a given function type
375 builtins_manager::make_fn_type (enum jit_builtin_type
,
376 enum jit_builtin_type return_type_id
,
382 type
**param_types
= new type
*[num_args
];
383 type
*return_type
= NULL
;
384 function_type
*result
= NULL
;
386 va_start (list
, num_args
);
387 for (i
= 0; i
< num_args
; ++i
)
389 enum jit_builtin_type arg_type_id
=
390 (enum jit_builtin_type
) va_arg (list
, int);
391 param_types
[i
] = get_type (arg_type_id
);
397 return_type
= get_type (return_type_id
);
401 result
= m_ctxt
->new_function_type (return_type
,
407 delete[] param_types
;
411 /* Handler for DEF_POINTER_TYPE within builtins_manager::make_type. */
414 builtins_manager::make_ptr_type (enum jit_builtin_type
,
415 enum jit_builtin_type other_type_id
)
417 type
*base_type
= get_type (other_type_id
);
418 return base_type
->get_pointer ();
421 } // namespace recording