1 /* jit-builtins.c -- Handling of builtin functions during JIT-compilation. 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 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 29 namespace gcc { 30 31 namespace jit { 32 33 const char *const prefix = "__builtin_"; 34 const size_t prefix_len = strlen (prefix); 35 36 /* Create "builtin_data", a const table of the data within builtins.def. */ 37 struct 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}, 59 static const struct builtin_data builtin_data[] = 60 { 61 #include "builtins.def" 62 }; 63 64 /* Helper function for find_builtin_by_name. */ 65 66 static bool 67 matches_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 102 static bool 103 find_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 133 builtins_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 145 recording::function * 146 builtins_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 162 recording::function * 163 builtins_manager::get_builtin_function_by_id (enum built_in_function builtin_id) 164 { 165 gcc_assert (builtin_id >= 0); 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 185 recording::function * 186 builtins_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.c: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 /* Get the recording::type for a given type of builtin function, 249 by ID, creating it if it doesn't already exist. */ 250 251 recording::type * 252 builtins_manager::get_type (enum jit_builtin_type type_id) 253 { 254 if (!m_types[type_id]) 255 m_types[type_id] = make_type (type_id); 256 return m_types[type_id]; 257 } 258 259 /* Create the recording::type for a given type of builtin function. */ 260 261 recording::type * 262 builtins_manager::make_type (enum jit_builtin_type type_id) 263 { 264 /* Use builtin-types.def to construct a switch statement, with each 265 case deferring to one of the methods below: 266 - DEF_PRIMITIVE_TYPE is handled as a call to make_primitive_type. 267 - the various DEF_FUNCTION_TYPE_n are handled by variadic calls 268 to make_fn_type. 269 - similarly for DEF_FUNCTION_TYPE_VAR_n, but setting the 270 "is_variadic" argument. 271 - DEF_POINTER_TYPE is handled by make_ptr_type. 272 That should handle everything, but just in case we also suppy a 273 gcc_unreachable default clause. */ 274 switch (type_id) 275 { 276 #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ 277 case ENUM: return make_primitive_type (ENUM); 278 #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ 279 case ENUM: return make_fn_type (ENUM, RETURN, 0, 0); 280 #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ 281 case ENUM: return make_fn_type (ENUM, RETURN, 0, 1, ARG1); 282 #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ 283 case ENUM: return make_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2); 284 #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ 285 case ENUM: return make_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3); 286 #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ 287 case ENUM: return make_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, \ 288 ARG4); 289 #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ 290 case ENUM: return make_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, \ 291 ARG4, ARG5); 292 #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 293 ARG6) \ 294 case ENUM: return make_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, \ 295 ARG4, ARG5, ARG6); 296 #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 297 ARG6, ARG7) \ 298 case ENUM: return make_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, \ 299 ARG4, ARG5, ARG6, ARG7); 300 #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 301 ARG6, ARG7, ARG8) \ 302 case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \ 303 ARG4, ARG5, ARG6, ARG7, ARG8); 304 #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 305 ARG6, ARG7, ARG8, ARG9) \ 306 case ENUM: return make_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, \ 307 ARG4, ARG5, ARG6, ARG7, ARG8, ARG9); 308 #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 309 ARG6, ARG7, ARG8, ARG9, ARG10) \ 310 case ENUM: return make_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, \ 311 ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ 312 ARG10); 313 #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 314 ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \ 315 case ENUM: return make_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, \ 316 ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ 317 ARG10, ARG11); 318 #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ 319 case ENUM: return make_fn_type (ENUM, RETURN, 1, 0); 320 #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ 321 case ENUM: return make_fn_type (ENUM, RETURN, 1, 1, ARG1); 322 #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ 323 case ENUM: return make_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2); 324 #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ 325 case ENUM: return make_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3); 326 #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ 327 case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, \ 328 ARG4); 329 #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ 330 case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, \ 331 ARG4, ARG5); 332 #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 333 ARG6) \ 334 case ENUM: return make_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, \ 335 ARG4, ARG5, ARG6); 336 #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ 337 ARG6, ARG7) \ 338 case ENUM: return make_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, \ 339 ARG4, ARG5, ARG6, ARG7); 340 #define DEF_POINTER_TYPE(ENUM, TYPE) \ 341 case ENUM: return make_ptr_type (ENUM, TYPE); 342 343 #include "builtin-types.def" 344 345 #undef DEF_PRIMITIVE_TYPE 346 #undef DEF_FUNCTION_TYPE_0 347 #undef DEF_FUNCTION_TYPE_1 348 #undef DEF_FUNCTION_TYPE_2 349 #undef DEF_FUNCTION_TYPE_3 350 #undef DEF_FUNCTION_TYPE_4 351 #undef DEF_FUNCTION_TYPE_5 352 #undef DEF_FUNCTION_TYPE_6 353 #undef DEF_FUNCTION_TYPE_7 354 #undef DEF_FUNCTION_TYPE_8 355 #undef DEF_FUNCTION_TYPE_9 356 #undef DEF_FUNCTION_TYPE_10 357 #undef DEF_FUNCTION_TYPE_11 358 #undef DEF_FUNCTION_TYPE_VAR_0 359 #undef DEF_FUNCTION_TYPE_VAR_1 360 #undef DEF_FUNCTION_TYPE_VAR_2 361 #undef DEF_FUNCTION_TYPE_VAR_3 362 #undef DEF_FUNCTION_TYPE_VAR_4 363 #undef DEF_FUNCTION_TYPE_VAR_5 364 #undef DEF_FUNCTION_TYPE_VAR_6 365 #undef DEF_FUNCTION_TYPE_VAR_7 366 #undef DEF_POINTER_TYPE 367 368 default: 369 gcc_unreachable (); 370 } 371 } 372 373 /* Create the recording::type for a given primitive type within the 374 builtin system. 375 376 Only some types are currently supported. */ 377 378 recording::type* 379 builtins_manager::make_primitive_type (enum jit_builtin_type type_id) 380 { 381 switch (type_id) 382 { 383 default: 384 // only some of these types are implemented so far: 385 m_ctxt->add_error (NULL, 386 "unimplemented primitive type for builtin: %d", type_id); 387 return NULL; 388 389 case BT_VOID: return m_ctxt->get_type (GCC_JIT_TYPE_VOID); 390 case BT_BOOL: return m_ctxt->get_type (GCC_JIT_TYPE_BOOL); 391 case BT_INT: return m_ctxt->get_type (GCC_JIT_TYPE_INT); 392 case BT_UINT: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_INT); 393 case BT_LONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG); 394 case BT_ULONG: return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG); 395 case BT_LONGLONG: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_LONG); 396 case BT_ULONGLONG: 397 return m_ctxt->get_type (GCC_JIT_TYPE_UNSIGNED_LONG_LONG); 398 // case BT_INT128: 399 // case BT_UINT128: 400 // case BT_INTMAX: 401 // case BT_UINTMAX: 402 case BT_UINT16: return m_ctxt->get_int_type (2, false); 403 case BT_UINT32: return m_ctxt->get_int_type (4, false); 404 case BT_UINT64: return m_ctxt->get_int_type (8, false); 405 // case BT_WORD: 406 // case BT_UNWINDWORD: 407 case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT); 408 case BT_DOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE); 409 case BT_LONGDOUBLE: return m_ctxt->get_type (GCC_JIT_TYPE_LONG_DOUBLE); 410 case BT_COMPLEX_FLOAT: 411 return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_FLOAT); 412 case BT_COMPLEX_DOUBLE: 413 return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_DOUBLE); 414 case BT_COMPLEX_LONGDOUBLE: 415 return m_ctxt->get_type (GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE); 416 case BT_PTR: return m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR); 417 case BT_FILEPTR: return m_ctxt->get_type (GCC_JIT_TYPE_FILE_PTR); 418 // case BT_CONST: 419 // case BT_VOLATILE_PTR: 420 // case BT_CONST_VOLATILE_PTR: 421 // case BT_PTRMODE: 422 // case BT_INT_PTR: 423 // case BT_FLOAT_PTR: 424 case BT_DOUBLE_PTR: 425 return m_ctxt->get_type (GCC_JIT_TYPE_DOUBLE)->get_pointer (); 426 // case BT_CONST_DOUBLE_PTR: 427 // case BT_LONGDOUBLE_PTR: 428 // case BT_PID: 429 // case BT_SIZE: 430 // case BT_SSIZE: 431 // case BT_WINT: 432 // case BT_STRING: 433 case BT_CONST_STRING: return m_ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR); 434 // case BT_DFLOAT32: 435 // case BT_DFLOAT64: 436 // case BT_DFLOAT128: 437 // case BT_VALIST_REF: 438 // case BT_VALIST_ARG: 439 // case BT_I1: 440 // case BT_I2: 441 // case BT_I4: 442 // case BT_I8: 443 // case BT_I16: 444 } 445 } 446 447 /* Create the recording::function_type for a given function type 448 signature. */ 449 450 recording::function_type * 451 builtins_manager::make_fn_type (enum jit_builtin_type, 452 enum jit_builtin_type return_type_id, 453 bool is_variadic, 454 int num_args, ...) 455 { 456 va_list list; 457 int i; 458 recording::type **param_types = new recording::type *[num_args]; 459 recording::type *return_type = NULL; 460 recording::function_type *result = NULL; 461 462 va_start (list, num_args); 463 for (i = 0; i < num_args; ++i) 464 { 465 enum jit_builtin_type arg_type_id = 466 (enum jit_builtin_type) va_arg (list, int); 467 param_types[i] = get_type (arg_type_id); 468 if (!param_types[i]) 469 goto error; 470 } 471 va_end (list); 472 473 return_type = get_type (return_type_id); 474 if (!return_type) 475 goto error; 476 477 result = m_ctxt->new_function_type (return_type, 478 num_args, 479 param_types, 480 is_variadic); 481 482 error: 483 delete[] param_types; 484 return result; 485 } 486 487 /* Handler for DEF_POINTER_TYPE within builtins_manager::make_type. */ 488 489 recording::type * 490 builtins_manager::make_ptr_type (enum jit_builtin_type, 491 enum jit_builtin_type other_type_id) 492 { 493 recording::type *base_type = get_type (other_type_id); 494 return base_type->get_pointer (); 495 } 496 497 /* Playback support. */ 498 499 /* A builtins_manager is associated with a recording::context 500 and might be reused for multiple compiles on various 501 playback::contexts, perhaps with different options. 502 503 Purge any playback state. Currently this is just the table of 504 attributes. */ 505 506 void 507 builtins_manager::finish_playback (void) 508 { 509 memset (m_attributes, 0, sizeof (m_attributes)); 510 } 511 512 /* Get the enum built_in_class for BUILTIN_ID. */ 513 514 enum built_in_class 515 builtins_manager::get_class (enum built_in_function builtin_id) 516 { 517 return builtin_data[builtin_id].fnclass; 518 } 519 520 /* Is BUILTIN_ID implicit? */ 521 522 bool 523 builtins_manager::implicit_p (enum built_in_function builtin_id) 524 { 525 return builtin_data[builtin_id].implicit_p; 526 } 527 528 /* Get any attributes (in tree form) for the function declaration 529 for BUILTIN_ID. 530 531 These are created on-demand, and cached within the m_attributes 532 array, until finish_playback. */ 533 534 tree 535 builtins_manager::get_attrs_tree (enum built_in_function builtin_id) 536 { 537 enum built_in_attribute attr = builtin_data[builtin_id].attr; 538 return get_attrs_tree (attr); 539 } 540 541 /* As above, but for an enum built_in_attribute. */ 542 543 tree 544 builtins_manager::get_attrs_tree (enum built_in_attribute attr) 545 { 546 gcc_assert (attr < ATTR_LAST); 547 if (!m_attributes [attr]) 548 m_attributes [attr] = make_attrs_tree (attr); 549 return m_attributes [attr]; 550 } 551 552 /* Handle a cache-miss within the m_attributes array by 553 generating the attributes for enum built_in_attribute 554 in tree form. */ 555 556 tree 557 builtins_manager::make_attrs_tree (enum built_in_attribute attr) 558 { 559 switch (attr) 560 { 561 /* Generate cases from builtin-attrs.def. */ 562 #define DEF_ATTR_NULL_TREE(ENUM) \ 563 case ENUM: return NULL_TREE; 564 #define DEF_ATTR_INT(ENUM, VALUE) \ 565 case ENUM: return build_int_cst (integer_type_node, VALUE); 566 #define DEF_ATTR_STRING(ENUM, VALUE) \ 567 case ENUM: return build_string (strlen (VALUE), VALUE); 568 #define DEF_ATTR_IDENT(ENUM, STRING) \ 569 case ENUM: return get_identifier (STRING); 570 #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \ 571 case ENUM: return tree_cons (get_attrs_tree (PURPOSE), \ 572 get_attrs_tree (VALUE), \ 573 get_attrs_tree (CHAIN)); 574 #include "builtin-attrs.def" 575 #undef DEF_ATTR_NULL_TREE 576 #undef DEF_ATTR_INT 577 #undef DEF_ATTR_IDENT 578 #undef DEF_ATTR_TREE_LIST 579 580 default: 581 /* We somehow got a value not covered by the autogenerated 582 cases. */ 583 gcc_unreachable (); 584 return NULL; 585 } 586 } 587 588 } // namespace jit 589 } // namespace gcc 590