15ef59e75Smrg /* jit-builtins.c -- Handling of builtin functions during JIT-compilation.
2*dd083157Smrg    Copyright (C) 2014-2020 Free Software Foundation, Inc.
35ef59e75Smrg 
45ef59e75Smrg This file is part of GCC.
55ef59e75Smrg 
65ef59e75Smrg GCC is free software; you can redistribute it and/or modify it under
75ef59e75Smrg the terms of the GNU General Public License as published by the Free
85ef59e75Smrg Software Foundation; either version 3, or (at your option) any later
95ef59e75Smrg version.
105ef59e75Smrg 
115ef59e75Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
125ef59e75Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
135ef59e75Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
145ef59e75Smrg for more details.
155ef59e75Smrg 
165ef59e75Smrg You should have received a copy of the GNU General Public License
175ef59e75Smrg along with GCC; see the file COPYING3.  If not see
185ef59e75Smrg <http://www.gnu.org/licenses/>.  */
195ef59e75Smrg 
205ef59e75Smrg #include "config.h"
215ef59e75Smrg #include "system.h"
225ef59e75Smrg #include "coretypes.h"
235ef59e75Smrg #include "target.h"
2463aace61Smrg #include "jit-playback.h"
255ef59e75Smrg #include "stringpool.h"
265ef59e75Smrg 
275ef59e75Smrg #include "jit-builtins.h"
285ef59e75Smrg 
295ef59e75Smrg namespace gcc {
305ef59e75Smrg 
315ef59e75Smrg namespace jit {
325ef59e75Smrg 
335ef59e75Smrg const char *const prefix = "__builtin_";
345ef59e75Smrg const size_t prefix_len = strlen (prefix);
355ef59e75Smrg 
365ef59e75Smrg /* Create "builtin_data", a const table of the data within builtins.def.  */
375ef59e75Smrg struct builtin_data
385ef59e75Smrg {
395ef59e75Smrg   const char *name;
405ef59e75Smrg   enum built_in_class fnclass;
415ef59e75Smrg   enum jit_builtin_type type;
425ef59e75Smrg   bool both_p;
435ef59e75Smrg   bool fallback_p;
445ef59e75Smrg   enum built_in_attribute attr;
455ef59e75Smrg   bool implicit_p;
465ef59e75Smrg 
get_asm_namebuiltin_data475ef59e75Smrg   const char *get_asm_name () const
485ef59e75Smrg   {
495ef59e75Smrg     if (both_p && fallback_p)
505ef59e75Smrg       return name + prefix_len;
515ef59e75Smrg     else
525ef59e75Smrg       return name;
535ef59e75Smrg   }
545ef59e75Smrg };
555ef59e75Smrg 
565ef59e75Smrg #define DEF_BUILTIN(X, NAME, CLASS, TYPE, LT, BOTH_P, FALLBACK_P, \
575ef59e75Smrg 		    NONANSI_P, ATTRS, IMPLICIT, COND)		  \
585ef59e75Smrg   {NAME, CLASS, TYPE, BOTH_P, FALLBACK_P, ATTRS, IMPLICIT},
595ef59e75Smrg static const struct builtin_data builtin_data[] =
605ef59e75Smrg {
615ef59e75Smrg #include "builtins.def"
625ef59e75Smrg };
635ef59e75Smrg 
645ef59e75Smrg /* Helper function for find_builtin_by_name.  */
655ef59e75Smrg 
665ef59e75Smrg static bool
matches_builtin(const char * in_name,const struct builtin_data & bd)675ef59e75Smrg matches_builtin (const char *in_name,
685ef59e75Smrg 		 const struct builtin_data& bd)
695ef59e75Smrg {
705ef59e75Smrg   const bool debug = 0;
713903d7f3Smrg 
723903d7f3Smrg   /* Ignore entries with a NULL name.  */
733903d7f3Smrg   if (!bd.name)
743903d7f3Smrg     return false;
755ef59e75Smrg 
765ef59e75Smrg   if (debug)
775ef59e75Smrg     fprintf (stderr, "seen builtin: %s\n", bd.name);
785ef59e75Smrg 
793903d7f3Smrg   if (strcmp (bd.name, in_name) == 0)
805ef59e75Smrg     return true;
815ef59e75Smrg 
825ef59e75Smrg   if (bd.both_p)
835ef59e75Smrg     {
845ef59e75Smrg       /* Then the macros in builtins.def gave a "__builtin_"
855ef59e75Smrg 	 prefix to bd.name, but we should also recognize the form
865ef59e75Smrg 	 without the prefix.  */
873903d7f3Smrg       gcc_assert (strncmp (bd.name, prefix, prefix_len) == 0);
885ef59e75Smrg       if (debug)
895ef59e75Smrg 	fprintf (stderr, "testing without prefix as: %s\n",
905ef59e75Smrg 		 bd.name + prefix_len);
913903d7f3Smrg       if (strcmp (bd.name + prefix_len, in_name) == 0)
925ef59e75Smrg 	return true;
935ef59e75Smrg     }
945ef59e75Smrg 
955ef59e75Smrg   return false;
965ef59e75Smrg }
975ef59e75Smrg 
985ef59e75Smrg /* Locate the built-in function that matches name IN_NAME,
995ef59e75Smrg    writing the result to OUT_ID and returning true if found,
1005ef59e75Smrg    or returning false if not found.  */
1015ef59e75Smrg 
1025ef59e75Smrg static bool
find_builtin_by_name(const char * in_name,enum built_in_function * out_id)1035ef59e75Smrg find_builtin_by_name (const char *in_name,
1045ef59e75Smrg 		      enum built_in_function *out_id)
1055ef59e75Smrg {
1065ef59e75Smrg   /* Locate builtin.  This currently works by performing repeated
1075ef59e75Smrg      strcmp against every possible candidate, which is likely to
1085ef59e75Smrg      inefficient.
1095ef59e75Smrg 
1105ef59e75Smrg      We start at index 1 to skip the initial entry (BUILT_IN_NONE), which
1115ef59e75Smrg      has a NULL name.  */
1125ef59e75Smrg   for (unsigned int i = 1;
1135ef59e75Smrg        i < sizeof (builtin_data) / sizeof (builtin_data[0]);
1145ef59e75Smrg        i++)
1155ef59e75Smrg     {
1165ef59e75Smrg       const struct builtin_data& bd = builtin_data[i];
1175ef59e75Smrg       if (matches_builtin (in_name, bd))
1185ef59e75Smrg 	{
1195ef59e75Smrg 	  /* Found a match.  */
1205ef59e75Smrg 	  *out_id = static_cast<enum built_in_function> (i);
1215ef59e75Smrg 	  return true;
1225ef59e75Smrg 	}
1235ef59e75Smrg     }
1245ef59e75Smrg 
1255ef59e75Smrg   /* Not found.  */
1265ef59e75Smrg   return false;
1275ef59e75Smrg }
1285ef59e75Smrg 
1295ef59e75Smrg // class builtins_manager
1305ef59e75Smrg 
1315ef59e75Smrg /* Constructor for gcc::jit::builtins_manager.  */
1325ef59e75Smrg 
builtins_manager(recording::context * ctxt)1335ef59e75Smrg builtins_manager::builtins_manager (recording::context *ctxt)
1345ef59e75Smrg   : m_ctxt (ctxt)
1355ef59e75Smrg {
1365ef59e75Smrg   memset (m_types, 0, sizeof (m_types));
1375ef59e75Smrg   memset (m_builtin_functions, 0, sizeof (m_builtin_functions));
1385ef59e75Smrg   memset (m_attributes, 0, sizeof (m_attributes));
1395ef59e75Smrg }
1405ef59e75Smrg 
1415ef59e75Smrg /* Locate a builtin function by name.
1425ef59e75Smrg    Create a recording::function of the appropriate type, reusing them
1435ef59e75Smrg    if they've already been seen.  */
1445ef59e75Smrg 
1455ef59e75Smrg recording::function *
get_builtin_function(const char * name)1465ef59e75Smrg builtins_manager::get_builtin_function (const char *name)
1475ef59e75Smrg {
1485ef59e75Smrg   enum built_in_function builtin_id;
1495ef59e75Smrg   if (!find_builtin_by_name (name, &builtin_id))
1505ef59e75Smrg     {
1515ef59e75Smrg       m_ctxt->add_error (NULL, "builtin \"%s\" not found", name);
1525ef59e75Smrg       return NULL;
1535ef59e75Smrg     }
1545ef59e75Smrg 
1555ef59e75Smrg   return get_builtin_function_by_id (builtin_id);
1565ef59e75Smrg }
1575ef59e75Smrg 
1585ef59e75Smrg /* Locate a builtin function by id.
1595ef59e75Smrg    Create a recording::function of the appropriate type, reusing them
1605ef59e75Smrg    if they've already been seen.  */
1615ef59e75Smrg 
1625ef59e75Smrg recording::function *
get_builtin_function_by_id(enum built_in_function builtin_id)1635ef59e75Smrg builtins_manager::get_builtin_function_by_id (enum built_in_function builtin_id)
1645ef59e75Smrg {
1655ef59e75Smrg   gcc_assert (builtin_id >= 0);
1665ef59e75Smrg   gcc_assert (builtin_id < END_BUILTINS);
1675ef59e75Smrg 
1685ef59e75Smrg   /* Lazily build the functions, caching them so that repeated calls for
1695ef59e75Smrg      the same id on a context give back the same object.  */
1705ef59e75Smrg   if (!m_builtin_functions[builtin_id])
1715ef59e75Smrg     {
1725ef59e75Smrg       recording::function *fn = make_builtin_function (builtin_id);
1735ef59e75Smrg       if (fn)
1745ef59e75Smrg 	{
1755ef59e75Smrg 	  m_builtin_functions[builtin_id] = fn;
1765ef59e75Smrg 	  m_ctxt->record (fn);
1775ef59e75Smrg 	}
1785ef59e75Smrg     }
1795ef59e75Smrg 
1805ef59e75Smrg   return m_builtin_functions[builtin_id];
1815ef59e75Smrg }
1825ef59e75Smrg 
1835ef59e75Smrg /* Create the recording::function for a given builtin function, by ID.  */
1845ef59e75Smrg 
1855ef59e75Smrg recording::function *
make_builtin_function(enum built_in_function builtin_id)1865ef59e75Smrg builtins_manager::make_builtin_function (enum built_in_function builtin_id)
1875ef59e75Smrg {
1885ef59e75Smrg   const struct builtin_data& bd = builtin_data[builtin_id];
1895ef59e75Smrg   enum jit_builtin_type type_id = bd.type;
1905ef59e75Smrg   recording::type *t = get_type (type_id);
1915ef59e75Smrg   if (!t)
1925ef59e75Smrg     return NULL;
1935ef59e75Smrg   recording::function_type *func_type = t->as_a_function_type ();
1945ef59e75Smrg   if (!func_type)
1955ef59e75Smrg     return NULL;
1965ef59e75Smrg 
1975ef59e75Smrg   vec<recording::type *> param_types = func_type->get_param_types ();
1985ef59e75Smrg   recording::param **params = new recording::param *[param_types.length ()];
1995ef59e75Smrg 
2005ef59e75Smrg   int i;
2015ef59e75Smrg   recording::type *param_type;
2025ef59e75Smrg   FOR_EACH_VEC_ELT (param_types, i, param_type)
2035ef59e75Smrg     {
2045ef59e75Smrg       char buf[16];
2055ef59e75Smrg       snprintf (buf, 16, "arg%d", i);
2065ef59e75Smrg       params[i] = m_ctxt->new_param (NULL,
2075ef59e75Smrg 				     param_type,
2085ef59e75Smrg 				     buf);
2095ef59e75Smrg     }
2105ef59e75Smrg   const char *asm_name = bd.get_asm_name ();
2115ef59e75Smrg   recording::function *result =
2125ef59e75Smrg     new recording::function (m_ctxt,
2135ef59e75Smrg 			     NULL,
2145ef59e75Smrg 			     GCC_JIT_FUNCTION_IMPORTED, // FIXME
2155ef59e75Smrg 			     func_type->get_return_type (),
2165ef59e75Smrg 			     m_ctxt->new_string (asm_name),
2175ef59e75Smrg 			     param_types.length (),
2185ef59e75Smrg 			     params,
2195ef59e75Smrg 			     func_type->is_variadic (),
2205ef59e75Smrg 			     builtin_id);
2215ef59e75Smrg   delete[] params;
2225ef59e75Smrg 
2235ef59e75Smrg   /* PR/64020 - If the client code is using builtin cos or sin,
2245ef59e75Smrg      tree-ssa-math-opt.c's execute_cse_sincos_1 may attempt
2255ef59e75Smrg      to optimize them to use __builtin_cexpi; for this,
2265ef59e75Smrg      BUILT_IN_CEXPI needs to exist.
2275ef59e75Smrg 
2285ef59e75Smrg      Hence query the cache for BUILT_IN_CEXPI to ensure it gets
2295ef59e75Smrg      built.  */
2305ef59e75Smrg   if (builtin_id == BUILT_IN_COS || builtin_id == BUILT_IN_SIN)
2315ef59e75Smrg     (void)get_builtin_function_by_id (BUILT_IN_CEXPI);
2325ef59e75Smrg 
2335ef59e75Smrg   /* builtins.c:expand_builtin_cexpi can optimize the various
2345ef59e75Smrg      CEXP builtins to SINCOS builtins, and hence we may require
2355ef59e75Smrg      SINCOS builtins latter.
2365ef59e75Smrg 
2375ef59e75Smrg      Ensure the appropriate SINCOS builtin exists.  */
2385ef59e75Smrg   if (builtin_id == BUILT_IN_CEXPIF)
2395ef59e75Smrg     (void)get_builtin_function_by_id (BUILT_IN_SINCOSF);
2405ef59e75Smrg   else if (builtin_id == BUILT_IN_CEXPI)
2415ef59e75Smrg     (void)get_builtin_function_by_id (BUILT_IN_SINCOS);
2425ef59e75Smrg   else if (builtin_id == BUILT_IN_CEXPIL)
2435ef59e75Smrg     (void)get_builtin_function_by_id (BUILT_IN_SINCOSL);
2445ef59e75Smrg 
2455ef59e75Smrg   return result;
2465ef59e75Smrg }
2475ef59e75Smrg 
2485ef59e75Smrg /* Get the recording::type for a given type of builtin function,
2495ef59e75Smrg    by ID, creating it if it doesn't already exist.  */
2505ef59e75Smrg 
2515ef59e75Smrg recording::type *
get_type(enum jit_builtin_type type_id)2525ef59e75Smrg builtins_manager::get_type (enum jit_builtin_type type_id)
2535ef59e75Smrg {
2545ef59e75Smrg   if (!m_types[type_id])
2555ef59e75Smrg     m_types[type_id] = make_type (type_id);
2565ef59e75Smrg   return m_types[type_id];
2575ef59e75Smrg }
2585ef59e75Smrg 
2595ef59e75Smrg /* Create the recording::type for a given type of builtin function.  */
2605ef59e75Smrg 
2615ef59e75Smrg recording::type *
make_type(enum jit_builtin_type type_id)2625ef59e75Smrg builtins_manager::make_type (enum jit_builtin_type type_id)
2635ef59e75Smrg {
2645ef59e75Smrg   /* Use builtin-types.def to construct a switch statement, with each
2655ef59e75Smrg      case deferring to one of the methods below:
2665ef59e75Smrg        - DEF_PRIMITIVE_TYPE is handled as a call to make_primitive_type.
2675ef59e75Smrg        - the various DEF_FUNCTION_TYPE_n are handled by variadic calls
2685ef59e75Smrg 	 to make_fn_type.
2695ef59e75Smrg        - similarly for DEF_FUNCTION_TYPE_VAR_n, but setting the
2705ef59e75Smrg 	"is_variadic" argument.
2715ef59e75Smrg        - DEF_POINTER_TYPE is handled by make_ptr_type.
2725ef59e75Smrg      That should handle everything, but just in case we also suppy a
2735ef59e75Smrg      gcc_unreachable default clause.  */
2745ef59e75Smrg   switch (type_id)
2755ef59e75Smrg     {
2765ef59e75Smrg #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
2775ef59e75Smrg       case ENUM: return make_primitive_type (ENUM);
2785ef59e75Smrg #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
2795ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 0);
2805ef59e75Smrg #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
2815ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 1, ARG1);
2825ef59e75Smrg #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
2835ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
2845ef59e75Smrg #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
2855ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
2865ef59e75Smrg #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
2875ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, \
2885ef59e75Smrg 				      ARG4);
2895ef59e75Smrg #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
2905ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, \
2915ef59e75Smrg 				      ARG4, ARG5);
2925ef59e75Smrg #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
2935ef59e75Smrg 			    ARG6)					\
2945ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, \
2955ef59e75Smrg 				      ARG4, ARG5, ARG6);
2965ef59e75Smrg #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
2975ef59e75Smrg 			    ARG6, ARG7)					\
2985ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, \
2995ef59e75Smrg 				      ARG4, ARG5, ARG6, ARG7);
3005ef59e75Smrg #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
3015ef59e75Smrg 			    ARG6, ARG7, ARG8)				\
3025ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \
3035ef59e75Smrg 				      ARG4, ARG5, ARG6, ARG7, ARG8);
30463aace61Smrg #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
30563aace61Smrg 			    ARG6, ARG7, ARG8, ARG9)			\
30663aace61Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, \
30763aace61Smrg 				      ARG4, ARG5, ARG6, ARG7, ARG8, ARG9);
30863aace61Smrg #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
30963aace61Smrg 			     ARG6, ARG7, ARG8, ARG9, ARG10)		 \
31063aace61Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, \
31163aace61Smrg 				      ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \
31263aace61Smrg 				      ARG10);
31363aace61Smrg #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
31463aace61Smrg 			     ARG6, ARG7, ARG8, ARG9, ARG10, ARG11)	 \
31563aace61Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, \
31663aace61Smrg 				      ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \
31763aace61Smrg 				      ARG10, ARG11);
3185ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
3195ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 0);
3205ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
3215ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 1, ARG1);
3225ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
3235ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
3245ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
3255ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
3265ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
3275ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, \
3285ef59e75Smrg 				      ARG4);
3295ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
3305ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, \
3315ef59e75Smrg 				      ARG4, ARG5);
33263aace61Smrg #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
33363aace61Smrg 				ARG6)					\
33463aace61Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, \
33563aace61Smrg 				      ARG4, ARG5, ARG6);
3365ef59e75Smrg #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
3375ef59e75Smrg 				ARG6, ARG7)				\
3385ef59e75Smrg       case ENUM: return make_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, \
3395ef59e75Smrg 				      ARG4, ARG5, ARG6, ARG7);
3405ef59e75Smrg #define DEF_POINTER_TYPE(ENUM, TYPE) \
3415ef59e75Smrg       case ENUM: return make_ptr_type (ENUM, TYPE);
3425ef59e75Smrg 
3435ef59e75Smrg #include "builtin-types.def"
3445ef59e75Smrg 
3455ef59e75Smrg #undef DEF_PRIMITIVE_TYPE
3465ef59e75Smrg #undef DEF_FUNCTION_TYPE_0
3475ef59e75Smrg #undef DEF_FUNCTION_TYPE_1
3485ef59e75Smrg #undef DEF_FUNCTION_TYPE_2
3495ef59e75Smrg #undef DEF_FUNCTION_TYPE_3
3505ef59e75Smrg #undef DEF_FUNCTION_TYPE_4
3515ef59e75Smrg #undef DEF_FUNCTION_TYPE_5
3525ef59e75Smrg #undef DEF_FUNCTION_TYPE_6
3535ef59e75Smrg #undef DEF_FUNCTION_TYPE_7
3545ef59e75Smrg #undef DEF_FUNCTION_TYPE_8
35563aace61Smrg #undef DEF_FUNCTION_TYPE_9
35663aace61Smrg #undef DEF_FUNCTION_TYPE_10
35763aace61Smrg #undef DEF_FUNCTION_TYPE_11
3585ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_0
3595ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_1
3605ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_2
3615ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_3
3625ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_4
3635ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_5
36463aace61Smrg #undef DEF_FUNCTION_TYPE_VAR_6
3655ef59e75Smrg #undef DEF_FUNCTION_TYPE_VAR_7
3665ef59e75Smrg #undef DEF_POINTER_TYPE
3675ef59e75Smrg 
3685ef59e75Smrg     default:
3695ef59e75Smrg       gcc_unreachable ();
3705ef59e75Smrg     }
3715ef59e75Smrg }
3725ef59e75Smrg 
3735ef59e75Smrg /* Create the recording::type for a given primitive type within the
3745ef59e75Smrg    builtin system.
3755ef59e75Smrg 
3765ef59e75Smrg    Only some types are currently supported.  */
3775ef59e75Smrg 
3785ef59e75Smrg recording::type*
make_primitive_type(enum jit_builtin_type type_id)3795ef59e75Smrg builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
3805ef59e75Smrg {
3815ef59e75Smrg   switch (type_id)
3825ef59e75Smrg     {
3835ef59e75Smrg     default:
3845ef59e75Smrg       // only some of these types are implemented so far:
3855ef59e75Smrg       m_ctxt->add_error (NULL,
3865ef59e75Smrg 			 "unimplemented primitive type for builtin: %d", type_id);
3875ef59e75Smrg       return NULL;
3885ef59e75Smrg 
3895ef59e75Smrg     case BT_VOID: return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
3905ef59e75Smrg     case BT_BOOL: return m_ctxt->get_type (GCC_JIT_TYPE_BOOL);
3915ef59e75Smrg     case BT_INT: return m_ctxt->get_type (GCC_JIT_TYPE_INT);
3925ef59e75Smrg     case BT_UINT: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_INT);
3935ef59e75Smrg     case BT_LONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG);
3945ef59e75Smrg     case BT_ULONG: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG);
3955ef59e75Smrg     case BT_LONGLONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_LONG);
3965ef59e75Smrg     case BT_ULONGLONG:
3975ef59e75Smrg       return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
3985ef59e75Smrg     // case BT_INT128:
3995ef59e75Smrg     // case BT_UINT128:
4005ef59e75Smrg     // case BT_INTMAX:
4015ef59e75Smrg     // case BT_UINTMAX:
4025ef59e75Smrg     case BT_UINT16: return m_ctxt->get_int_type (2, false);
4035ef59e75Smrg     case BT_UINT32: return m_ctxt->get_int_type (4, false);
4045ef59e75Smrg     case BT_UINT64: return m_ctxt->get_int_type (8, false);
4055ef59e75Smrg     // case BT_WORD:
4065ef59e75Smrg     // case BT_UNWINDWORD:
4075ef59e75Smrg     case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT);
4085ef59e75Smrg     case BT_DOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE);
4095ef59e75Smrg     case BT_LONGDOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_DOUBLE);
4105ef59e75Smrg     case BT_COMPLEX_FLOAT:
4115ef59e75Smrg       return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_FLOAT);
4125ef59e75Smrg     case BT_COMPLEX_DOUBLE:
4135ef59e75Smrg       return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_DOUBLE);
4145ef59e75Smrg     case BT_COMPLEX_LONGDOUBLE:
4155ef59e75Smrg       return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
4165ef59e75Smrg     case BT_PTR: return m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR);
4175ef59e75Smrg     case BT_FILEPTR: return m_ctxt->get_type (GCC_JIT_TYPE_FILE_PTR);
4185ef59e75Smrg     // case BT_CONST:
4195ef59e75Smrg     // case BT_VOLATILE_PTR:
4205ef59e75Smrg     // case BT_CONST_VOLATILE_PTR:
4215ef59e75Smrg     // case BT_PTRMODE:
4225ef59e75Smrg     // case BT_INT_PTR:
4235ef59e75Smrg     // case BT_FLOAT_PTR:
4245ef59e75Smrg     case BT_DOUBLE_PTR:
4255ef59e75Smrg       return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_pointer ();
4265ef59e75Smrg     // case BT_CONST_DOUBLE_PTR:
4275ef59e75Smrg     // case BT_LONGDOUBLE_PTR:
4285ef59e75Smrg     // case BT_PID:
4295ef59e75Smrg     // case BT_SIZE:
4305ef59e75Smrg     // case BT_SSIZE:
4315ef59e75Smrg     // case BT_WINT:
4325ef59e75Smrg     // case BT_STRING:
4335ef59e75Smrg     case BT_CONST_STRING: return m_ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR);
4345ef59e75Smrg     // case BT_DFLOAT32:
4355ef59e75Smrg     // case BT_DFLOAT64:
4365ef59e75Smrg     // case BT_DFLOAT128:
4375ef59e75Smrg     // case BT_VALIST_REF:
4385ef59e75Smrg     // case BT_VALIST_ARG:
4395ef59e75Smrg     // case BT_I1:
4405ef59e75Smrg     // case BT_I2:
4415ef59e75Smrg     // case BT_I4:
4425ef59e75Smrg     // case BT_I8:
4435ef59e75Smrg     // case BT_I16:
4445ef59e75Smrg     }
4455ef59e75Smrg }
4465ef59e75Smrg 
4475ef59e75Smrg /* Create the recording::function_type for a given function type
4485ef59e75Smrg    signature.  */
4495ef59e75Smrg 
4505ef59e75Smrg recording::function_type *
make_fn_type(enum jit_builtin_type,enum jit_builtin_type return_type_id,bool is_variadic,int num_args,...)4515ef59e75Smrg builtins_manager::make_fn_type (enum jit_builtin_type,
4525ef59e75Smrg 				enum jit_builtin_type return_type_id,
4535ef59e75Smrg 				bool is_variadic,
4545ef59e75Smrg 				int num_args, ...)
4555ef59e75Smrg {
4565ef59e75Smrg   va_list list;
4575ef59e75Smrg   int i;
4585ef59e75Smrg   recording::type **param_types = new recording::type *[num_args];
4595ef59e75Smrg   recording::type *return_type = NULL;
4605ef59e75Smrg   recording::function_type *result = NULL;
4615ef59e75Smrg 
4625ef59e75Smrg   va_start (list, num_args);
4635ef59e75Smrg   for (i = 0; i < num_args; ++i)
4645ef59e75Smrg     {
4655ef59e75Smrg       enum jit_builtin_type arg_type_id =
4665ef59e75Smrg 	(enum jit_builtin_type) va_arg (list, int);
4675ef59e75Smrg       param_types[i] = get_type (arg_type_id);
4685ef59e75Smrg       if (!param_types[i])
4695ef59e75Smrg 	goto error;
4705ef59e75Smrg     }
4715ef59e75Smrg   va_end (list);
4725ef59e75Smrg 
4735ef59e75Smrg   return_type = get_type (return_type_id);
4745ef59e75Smrg   if (!return_type)
4755ef59e75Smrg     goto error;
4765ef59e75Smrg 
4775ef59e75Smrg   result = m_ctxt->new_function_type (return_type,
4785ef59e75Smrg 				      num_args,
4795ef59e75Smrg 				      param_types,
4805ef59e75Smrg 				      is_variadic);
4815ef59e75Smrg 
4825ef59e75Smrg  error:
4835ef59e75Smrg   delete[] param_types;
4845ef59e75Smrg   return result;
4855ef59e75Smrg }
4865ef59e75Smrg 
4875ef59e75Smrg /* Handler for DEF_POINTER_TYPE within builtins_manager::make_type.  */
4885ef59e75Smrg 
4895ef59e75Smrg recording::type *
make_ptr_type(enum jit_builtin_type,enum jit_builtin_type other_type_id)4905ef59e75Smrg builtins_manager::make_ptr_type (enum jit_builtin_type,
4915ef59e75Smrg 				 enum jit_builtin_type other_type_id)
4925ef59e75Smrg {
4935ef59e75Smrg   recording::type *base_type = get_type (other_type_id);
4945ef59e75Smrg   return base_type->get_pointer ();
4955ef59e75Smrg }
4965ef59e75Smrg 
4975ef59e75Smrg /* Playback support.  */
4985ef59e75Smrg 
4995ef59e75Smrg /* A builtins_manager is associated with a recording::context
5005ef59e75Smrg    and might be reused for multiple compiles on various
5015ef59e75Smrg    playback::contexts, perhaps with different options.
5025ef59e75Smrg 
5035ef59e75Smrg    Purge any playback state.  Currently this is just the table of
5045ef59e75Smrg    attributes.  */
5055ef59e75Smrg 
5065ef59e75Smrg void
finish_playback(void)5075ef59e75Smrg builtins_manager::finish_playback (void)
5085ef59e75Smrg {
5095ef59e75Smrg   memset (m_attributes, 0, sizeof (m_attributes));
5105ef59e75Smrg }
5115ef59e75Smrg 
5125ef59e75Smrg /* Get the enum built_in_class for BUILTIN_ID.  */
5135ef59e75Smrg 
5145ef59e75Smrg enum built_in_class
get_class(enum built_in_function builtin_id)5155ef59e75Smrg builtins_manager::get_class (enum built_in_function builtin_id)
5165ef59e75Smrg {
5175ef59e75Smrg   return builtin_data[builtin_id].fnclass;
5185ef59e75Smrg }
5195ef59e75Smrg 
5205ef59e75Smrg /* Is BUILTIN_ID implicit?  */
5215ef59e75Smrg 
5225ef59e75Smrg bool
implicit_p(enum built_in_function builtin_id)5235ef59e75Smrg builtins_manager::implicit_p (enum built_in_function builtin_id)
5245ef59e75Smrg {
5255ef59e75Smrg   return builtin_data[builtin_id].implicit_p;
5265ef59e75Smrg }
5275ef59e75Smrg 
5285ef59e75Smrg /* Get any attributes (in tree form) for the function declaration
5295ef59e75Smrg    for BUILTIN_ID.
5305ef59e75Smrg 
5315ef59e75Smrg    These are created on-demand, and cached within the m_attributes
5325ef59e75Smrg    array, until finish_playback.  */
5335ef59e75Smrg 
5345ef59e75Smrg tree
get_attrs_tree(enum built_in_function builtin_id)5355ef59e75Smrg builtins_manager::get_attrs_tree (enum built_in_function builtin_id)
5365ef59e75Smrg {
5375ef59e75Smrg   enum built_in_attribute attr = builtin_data[builtin_id].attr;
5385ef59e75Smrg   return get_attrs_tree (attr);
5395ef59e75Smrg }
5405ef59e75Smrg 
5415ef59e75Smrg /* As above, but for an enum built_in_attribute.  */
5425ef59e75Smrg 
5435ef59e75Smrg tree
get_attrs_tree(enum built_in_attribute attr)5445ef59e75Smrg builtins_manager::get_attrs_tree (enum built_in_attribute attr)
5455ef59e75Smrg {
5465ef59e75Smrg   gcc_assert (attr < ATTR_LAST);
5475ef59e75Smrg   if (!m_attributes [attr])
5485ef59e75Smrg     m_attributes [attr] = make_attrs_tree (attr);
5495ef59e75Smrg   return m_attributes [attr];
5505ef59e75Smrg }
5515ef59e75Smrg 
5525ef59e75Smrg /* Handle a cache-miss within the m_attributes array by
5535ef59e75Smrg    generating the attributes for enum built_in_attribute
5545ef59e75Smrg    in tree form.  */
5555ef59e75Smrg 
5565ef59e75Smrg tree
make_attrs_tree(enum built_in_attribute attr)5575ef59e75Smrg builtins_manager::make_attrs_tree (enum built_in_attribute attr)
5585ef59e75Smrg {
5595ef59e75Smrg   switch (attr)
5605ef59e75Smrg     {
5615ef59e75Smrg       /* Generate cases from builtin-attrs.def.  */
5625ef59e75Smrg #define DEF_ATTR_NULL_TREE(ENUM)				\
5635ef59e75Smrg       case ENUM: return NULL_TREE;
5645ef59e75Smrg #define DEF_ATTR_INT(ENUM, VALUE)				\
5655ef59e75Smrg       case ENUM: return build_int_cst (integer_type_node, VALUE);
5665ef59e75Smrg #define DEF_ATTR_STRING(ENUM, VALUE)				\
5675ef59e75Smrg       case ENUM: return build_string (strlen (VALUE), VALUE);
5685ef59e75Smrg #define DEF_ATTR_IDENT(ENUM, STRING)				\
5695ef59e75Smrg       case ENUM: return get_identifier (STRING);
5705ef59e75Smrg #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)	\
5715ef59e75Smrg       case ENUM: return tree_cons (get_attrs_tree (PURPOSE),	\
5725ef59e75Smrg 				   get_attrs_tree (VALUE),	\
5735ef59e75Smrg 				   get_attrs_tree (CHAIN));
5745ef59e75Smrg #include "builtin-attrs.def"
5755ef59e75Smrg #undef DEF_ATTR_NULL_TREE
5765ef59e75Smrg #undef DEF_ATTR_INT
5775ef59e75Smrg #undef DEF_ATTR_IDENT
5785ef59e75Smrg #undef DEF_ATTR_TREE_LIST
5795ef59e75Smrg 
5805ef59e75Smrg     default:
5815ef59e75Smrg       /* We somehow got a value not covered by the autogenerated
5825ef59e75Smrg 	 cases.  */
5835ef59e75Smrg       gcc_unreachable ();
5845ef59e75Smrg       return NULL;
5855ef59e75Smrg     }
5865ef59e75Smrg }
5875ef59e75Smrg 
5885ef59e75Smrg } // namespace jit
5895ef59e75Smrg } // namespace gcc
590