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