1/* jit-builtins.cc -- Handling of builtin functions during JIT-compilation.
2   Copyright (C) 2014-2022 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
23#include "target.h"
24#include "jit-playback.h"
25#include "stringpool.h"
26
27#include "jit-builtins.h"
28
29namespace gcc {
30
31namespace jit {
32
33const char *const prefix = "__builtin_";
34const size_t prefix_len = strlen (prefix);
35
36/* Create "builtin_data", a const table of the data within builtins.def.  */
37struct builtin_data
38{
39  const char *name;
40  enum built_in_class fnclass;
41  enum jit_builtin_type type;
42  bool both_p;
43  bool fallback_p;
44  enum built_in_attribute attr;
45  bool implicit_p;
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
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},
59static const struct builtin_data builtin_data[] =
60{
61#include "builtins.def"
62};
63
64/* Helper function for find_builtin_by_name.  */
65
66static bool
67matches_builtin (const char *in_name,
68		 const struct builtin_data& bd)
69{
70  const bool debug = 0;
71
72  /* Ignore entries with a NULL name.  */
73  if (!bd.name)
74    return false;
75
76  if (debug)
77    fprintf (stderr, "seen builtin: %s\n", bd.name);
78
79  if (strcmp (bd.name, in_name) == 0)
80    return true;
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.  */
87      gcc_assert (strncmp (bd.name, prefix, prefix_len) == 0);
88      if (debug)
89	fprintf (stderr, "testing without prefix as: %s\n",
90		 bd.name + prefix_len);
91      if (strcmp (bd.name + prefix_len, in_name) == 0)
92	return true;
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
102static bool
103find_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
131/* Constructor for gcc::jit::builtins_manager.  */
132
133builtins_manager::builtins_manager (recording::context *ctxt)
134  : m_ctxt (ctxt)
135{
136  memset (m_types, 0, sizeof (m_types));
137  memset (m_builtin_functions, 0, sizeof (m_builtin_functions));
138  memset (m_attributes, 0, sizeof (m_attributes));
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
145recording::function *
146builtins_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
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
162recording::function *
163builtins_manager::get_builtin_function_by_id (enum built_in_function builtin_id)
164{
165  gcc_assert (builtin_id > BUILT_IN_NONE);
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    {
172      recording::function *fn = make_builtin_function (builtin_id);
173      if (fn)
174	{
175	  m_builtin_functions[builtin_id] = fn;
176	  m_ctxt->record (fn);
177	}
178    }
179
180  return m_builtin_functions[builtin_id];
181}
182
183/* Create the recording::function for a given builtin function, by ID.  */
184
185recording::function *
186builtins_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;
190  recording::type *t = get_type (type_id);
191  if (!t)
192    return NULL;
193  recording::function_type *func_type = t->as_a_function_type ();
194  if (!func_type)
195    return NULL;
196
197  vec<recording::type *> param_types = func_type->get_param_types ();
198  recording::param **params = new recording::param *[param_types.length ()];
199
200  int i;
201  recording::type *param_type;
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 ();
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);
221  delete[] params;
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
233  /* builtins.cc:expand_builtin_cexpi can optimize the various
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
245  return result;
246}
247
248/* Build an array of type names for use by get_string_for_type_id.  */
249
250static 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
320static const char *
321get_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
327/* Get the recording::type for a given type of builtin function,
328   by ID, creating it if it doesn't already exist.  */
329
330recording::type *
331builtins_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
340recording::type *
341builtins_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) \
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);
371#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
372			    ARG6)					\
373      case ENUM: return make_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, \
374				      ARG4, ARG5, ARG6);
375#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
376			    ARG6, ARG7)					\
377      case ENUM: return make_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, \
378				      ARG4, ARG5, ARG6, ARG7);
379#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
380			    ARG6, ARG7, ARG8)				\
381      case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \
382				      ARG4, ARG5, ARG6, ARG7, ARG8);
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);
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) \
406      case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, \
407				      ARG4);
408#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
409      case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, \
410				      ARG4, ARG5);
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);
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);
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
425#undef DEF_FUNCTION_TYPE_0
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
432#undef DEF_FUNCTION_TYPE_7
433#undef DEF_FUNCTION_TYPE_8
434#undef DEF_FUNCTION_TYPE_9
435#undef DEF_FUNCTION_TYPE_10
436#undef DEF_FUNCTION_TYPE_11
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
443#undef DEF_FUNCTION_TYPE_VAR_6
444#undef DEF_FUNCTION_TYPE_VAR_7
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
457recording::type*
458builtins_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,
465			 "unimplemented primitive type for builtin (type: %s)",
466			 get_string_for_type_id (type_id));
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);
478    // case BT_INTMAX:
479    // case BT_UINTMAX:
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);
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_UINT128: return m_ctxt->get_int_type (16, false);
487    // case BT_WORD:
488    // case BT_UNWINDWORD:
489    case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT);
490    case BT_DOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE);
491    case BT_LONGDOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_DOUBLE);
492    // case BT_FLOAT16:
493    // case BT_FLOAT32:
494    // case BT_FLOAT64:
495    // case BT_FLOAT128:
496    // case BT_FLOAT32X:
497    // case BT_FLOAT64X:
498    // case BT_FLOAT128X:
499    case BT_COMPLEX_FLOAT:
500      return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_FLOAT);
501    case BT_COMPLEX_DOUBLE:
502      return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_DOUBLE);
503    case BT_COMPLEX_LONGDOUBLE:
504      return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
505    case BT_PTR: return m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR);
506    case BT_FILEPTR: return m_ctxt->get_type (GCC_JIT_TYPE_FILE_PTR);
507    // case BT_CONST_TM_PTR:
508    // case BT_FENV_T_PTR:
509    // case BT_CONST_FENV_T_PTR:
510    // case BT_FEXCEPT_T_PTR:
511    // case BT_CONST_FEXCEPT_T_PTR:
512    case BT_CONST_PTR:
513      return m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_const ()->get_pointer ();
514    case BT_VOLATILE_PTR:
515      return (m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_volatile ()
516	      ->get_pointer ());
517    case BT_CONST_VOLATILE_PTR:
518      return (m_ctxt->get_type (GCC_JIT_TYPE_VOID)->get_const ()
519	      ->get_volatile ()->get_pointer ());
520    // case BT_PTRMODE:
521    case BT_INT_PTR:
522      return m_ctxt->get_type (GCC_JIT_TYPE_INT)->get_pointer ();
523    case BT_FLOAT_PTR:
524      return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT)->get_pointer ();
525    case BT_DOUBLE_PTR:
526      return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_pointer ();
527    case BT_CONST_DOUBLE_PTR:
528      return (m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_const ()
529	      ->get_pointer ());
530    // case BT_LONGDOUBLE_PTR:
531    // case BT_PID:
532    case BT_SIZE:
533      return m_ctxt->get_type (GCC_JIT_TYPE_SIZE_T);
534    case BT_CONST_SIZE:
535      return m_ctxt->get_type (GCC_JIT_TYPE_SIZE_T)->get_const ();
536    // case BT_SSIZE:
537    // case BT_WINT:
538    // case BT_STRING:
539    case BT_CONST_STRING: return m_ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR);
540    // case BT_DFLOAT32:
541    // case BT_DFLOAT64:
542    // case BT_DFLOAT128:
543    // case BT_VALIST_REF:
544    // case BT_VALIST_ARG:
545    case BT_I1: return m_ctxt->get_int_type (1, true);
546    case BT_I2: return m_ctxt->get_int_type (2, true);
547    case BT_I4: return m_ctxt->get_int_type (4, true);
548    case BT_I8: return m_ctxt->get_int_type (8, true);
549    case BT_I16: return m_ctxt->get_int_type (16, true);
550    // case BT_PTR_CONST_STRING:
551    }
552}
553
554/* Create the recording::function_type for a given function type
555   signature.  */
556
557recording::function_type *
558builtins_manager::make_fn_type (enum jit_builtin_type,
559				enum jit_builtin_type return_type_id,
560				bool is_variadic,
561				int num_args, ...)
562{
563  va_list list;
564  int i;
565  recording::type **param_types = new recording::type *[num_args];
566  recording::type *return_type = NULL;
567  recording::function_type *result = NULL;
568
569  va_start (list, num_args);
570  for (i = 0; i < num_args; ++i)
571    {
572      enum jit_builtin_type arg_type_id =
573	(enum jit_builtin_type) va_arg (list, int);
574      param_types[i] = get_type (arg_type_id);
575      if (!param_types[i])
576	goto error;
577    }
578  va_end (list);
579
580  return_type = get_type (return_type_id);
581  if (!return_type)
582    goto error;
583
584  result = m_ctxt->new_function_type (return_type,
585				      num_args,
586				      param_types,
587				      is_variadic);
588
589 error:
590  delete[] param_types;
591  return result;
592}
593
594/* Handler for DEF_POINTER_TYPE within builtins_manager::make_type.  */
595
596recording::type *
597builtins_manager::make_ptr_type (enum jit_builtin_type,
598				 enum jit_builtin_type other_type_id)
599{
600  recording::type *base_type = get_type (other_type_id);
601  return base_type->get_pointer ();
602}
603
604/* Ensure that builtins that could be needed during optimization
605   get created ahead of time.  */
606
607void
608builtins_manager::ensure_optimization_builtins_exist ()
609{
610  /* build_common_builtin_nodes does most of this, but not all.
611     We can't loop through all of the builtin_data array, we don't
612     support all types yet.  */
613  (void)get_builtin_function_by_id (BUILT_IN_TRAP);
614}
615
616/* Playback support.  */
617
618/* A builtins_manager is associated with a recording::context
619   and might be reused for multiple compiles on various
620   playback::contexts, perhaps with different options.
621
622   Purge any playback state.  Currently this is just the table of
623   attributes.  */
624
625void
626builtins_manager::finish_playback (void)
627{
628  memset (m_attributes, 0, sizeof (m_attributes));
629}
630
631/* Get the enum built_in_class for BUILTIN_ID.  */
632
633enum built_in_class
634builtins_manager::get_class (enum built_in_function builtin_id)
635{
636  return builtin_data[builtin_id].fnclass;
637}
638
639/* Is BUILTIN_ID implicit?  */
640
641bool
642builtins_manager::implicit_p (enum built_in_function builtin_id)
643{
644  return builtin_data[builtin_id].implicit_p;
645}
646
647/* Get any attributes (in tree form) for the function declaration
648   for BUILTIN_ID.
649
650   These are created on-demand, and cached within the m_attributes
651   array, until finish_playback.  */
652
653tree
654builtins_manager::get_attrs_tree (enum built_in_function builtin_id)
655{
656  enum built_in_attribute attr = builtin_data[builtin_id].attr;
657  return get_attrs_tree (attr);
658}
659
660/* As above, but for an enum built_in_attribute.  */
661
662tree
663builtins_manager::get_attrs_tree (enum built_in_attribute attr)
664{
665  gcc_assert (attr < ATTR_LAST);
666  if (!m_attributes [attr])
667    m_attributes [attr] = make_attrs_tree (attr);
668  return m_attributes [attr];
669}
670
671/* Handle a cache-miss within the m_attributes array by
672   generating the attributes for enum built_in_attribute
673   in tree form.  */
674
675tree
676builtins_manager::make_attrs_tree (enum built_in_attribute attr)
677{
678  switch (attr)
679    {
680      /* Generate cases from builtin-attrs.def.  */
681#define DEF_ATTR_NULL_TREE(ENUM)				\
682      case ENUM: return NULL_TREE;
683#define DEF_ATTR_INT(ENUM, VALUE)				\
684      case ENUM: return build_int_cst (integer_type_node, VALUE);
685#define DEF_ATTR_STRING(ENUM, VALUE)				\
686      case ENUM: return build_string (strlen (VALUE), VALUE);
687#define DEF_ATTR_IDENT(ENUM, STRING)				\
688      case ENUM: return get_identifier (STRING);
689#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)	\
690      case ENUM: return tree_cons (get_attrs_tree (PURPOSE),	\
691				   get_attrs_tree (VALUE),	\
692				   get_attrs_tree (CHAIN));
693#include "builtin-attrs.def"
694#undef DEF_ATTR_NULL_TREE
695#undef DEF_ATTR_INT
696#undef DEF_ATTR_IDENT
697#undef DEF_ATTR_TREE_LIST
698
699    default:
700      /* We somehow got a value not covered by the autogenerated
701	 cases.  */
702      gcc_unreachable ();
703      return NULL;
704    }
705}
706
707} // namespace jit
708} // namespace gcc
709