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