1/* Generate built-in function initialization and recognition for Power. 2 Copyright (C) 2020-2022 Free Software Foundation, Inc. 3 Contributed by Bill Schmidt, IBM <wschmidt@linux.ibm.com> 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21/* This program generates built-in function initialization and 22 recognition code for Power targets, based on text files that 23 describe the built-in functions and vector overloads: 24 25 rs6000-builtins.def Table of built-in functions 26 rs6000-overload.def Table of overload functions 27 28 Both files group similar functions together in "stanzas," as 29 described below. 30 31 Each stanza in the built-in function file starts with a line 32 identifying the circumstances in which the group of functions is 33 permitted, with the gating predicate in square brackets. For 34 example, this could be 35 36 [altivec] 37 38 or it could be 39 40 [power9] 41 42 The bracketed gating predicate is the only information allowed on 43 the stanza header line, other than whitespace. 44 45 Following the stanza header are two lines for each function: the 46 prototype line and the attributes line. The prototype line has 47 this format, where the square brackets indicate optional 48 information and angle brackets indicate required information: 49 50 [kind] <return-type> <bif-name> (<argument-list>); 51 52 Here [kind] can be one of "const", "pure", or "fpmath"; 53 <return-type> is a legal type for a built-in function result; 54 <bif-name> is the name by which the function can be called; 55 and <argument-list> is a comma-separated list of legal types 56 for built-in function arguments. The argument list may be 57 empty, but the parentheses and semicolon are required. 58 59 The attributes line looks like this: 60 61 <bif-id> <bif-pattern> {<attribute-list>} 62 63 Here <bif-id> is a unique internal identifier for the built-in 64 function that will be used as part of an enumeration of all 65 built-in functions; <bif-pattern> is the define_expand or 66 define_insn that will be invoked when the call is expanded; 67 and <attribute-list> is a comma-separated list of special 68 conditions that apply to the built-in function. The attribute 69 list may be empty, but the braces are required. 70 71 Attributes are strings, such as these: 72 73 init Process as a vec_init function 74 set Process as a vec_set function 75 extract Process as a vec_extract function 76 nosoft Not valid with -msoft-float 77 ldvec Needs special handling for vec_ld semantics 78 stvec Needs special handling for vec_st semantics 79 reve Needs special handling for element reversal 80 pred Needs special handling for comparison predicates 81 htm Needs special handling for transactional memory 82 htmspr HTM function using an SPR 83 htmcr HTM function using a CR 84 mma Needs special handling for MMA instructions 85 quad MMA instruction using a register quad as an input operand 86 pair MMA instruction using a register pair as an input operand 87 mmaint MMA instruction expanding to internal call at GIMPLE time 88 no32bit Not valid for TARGET_32BIT 89 32bit Requires different handling for TARGET_32BIT 90 cpu This is a "cpu_is" or "cpu_supports" builtin 91 ldstmask Altivec mask for load or store 92 lxvrse Needs special handling for load-rightmost, sign-extended 93 lxvrze Needs special handling for load-rightmost, zero-extended 94 endian Needs special handling for endianness 95 ibmld Restrict usage to the case when TFmode is IBM-128 96 ibm128 Restrict usage to the case where __ibm128 is supported or 97 if ibmld 98 99 An example stanza might look like this: 100 101[altivec] 102 const vsc __builtin_altivec_abs_v16qi (vsc); 103 ABS_V16QI absv16qi2 {} 104 const vss __builtin_altivec_abs_v8hi (vss); 105 ABS_V8HI absv8hi2 {} 106 107 Here "vsc" and "vss" are shorthand for "vector signed char" and 108 "vector signed short" to shorten line lengths and improve readability. 109 Note the use of indentation, which is recommended but not required. 110 111 The overload file has more complex stanza headers. Here the stanza 112 represents all functions with the same overloaded function name: 113 114 [<overload-id>, <abi-name>, <builtin-name>[[, <ifdef>]] ] 115 116 Here the single square brackets are part of the syntax, <overload-id> 117 is a unique internal identifier for the overload that will be used as 118 part of an enumeration of all overloaded functions; <abi-name> is the 119 name that will appear as a #define in rs6000-vecdefines.h; 120 <builtin-name> is the name that is overloaded in the back end; and 121 <ifdef> is an optional token used to guard the #define with an #ifdef 122 in rs6000-vecdefines.h. 123 124 Each function entry again has two lines. The first line is again a 125 prototype line (this time without [kind]): 126 127 <return-type> <internal-name> (<argument-list>); 128 129 The second line contains the <bif-id> that this particular instance of 130 the overloaded function maps to. It must match a token that appears in 131 rs6000-builtins.def. Optionally, a second token may appear. If only 132 one token is on the line, it is also used to build the unique identifier 133 for the overloaded function. If a second token is present, the second 134 token is used instead for this purpose. This is necessary in cases 135 where a built-in function accepts more than one type signature. It is 136 common to have a built-in function that, for example, specifies a 137 "vector signed char" argument, but accepts "vector unsigned char" and 138 "vector bool char" as well because only the mode matters. Note that 139 the overload resolution mechanism has always handled these cases by 140 performing fold_convert on vector arguments to hide type mismatches, 141 and it will continue to do so. 142 143 As a concrete example, __builtin_altivec_mtvscr uses an opaque argument 144 type for the source operand. Its built-in function id is MTVSCR. The 145 overloaded function __builtin_vec_mtvscr takes a variety of specific 146 types, but not all vector types. Each of these maps to the same 147 __builtin_altivec_mtvscr built-in function, but the overload ID must 148 be unique, so we must specify the second token as shown here. 149 150 [VEC_MTVSCR, vec_mtvscr, __builtin_vec_mtvscr] 151 void __builtin_vec_mtvscr (vbc); 152 MTVSCR MTVSCR_VBC 153 void __builtin_vec_mtvscr (vsc); 154 MTVSCR MTVSCR_VSC 155 ... 156 157 Blank lines may be used as desired in these files between the lines as 158 defined above; that is, you can introduce as many extra newlines as you 159 like after a required newline, but nowhere else. Lines beginning with 160 a semicolon are also treated as blank lines. */ 161 162#include <stdio.h> 163#include <stdlib.h> 164#include <stdarg.h> 165#include <stdint.h> 166#include <ctype.h> 167#include <string.h> 168#include <assert.h> 169#include <unistd.h> 170#include "rbtree.h" 171 172/* Input and output file descriptors and pathnames. */ 173static FILE *bif_file; 174static FILE *ovld_file; 175static FILE *header_file; 176static FILE *init_file; 177static FILE *defines_file; 178 179static const char *pgm_path; 180static const char *bif_path; 181static const char *ovld_path; 182static const char *header_path; 183static const char *init_path; 184static const char *defines_path; 185 186/* Position information. Note that "pos" is zero-indexed, but users 187 expect one-indexed column information, so representations of "pos" 188 as columns in diagnostic messages must be adjusted. */ 189#define MAXLINES 4 190#define LINELEN 1024 191static char linebuf[LINELEN * MAXLINES]; 192static int line; 193static int pos; 194 195/* Escape-newline support. For readability, we prefer to allow developers 196 to use escape-newline to continue long lines to the next one. We 197 maintain a buffer of "original" lines here, which are concatenated into 198 linebuf, above, and which can be used to convert the virtual line 199 position "line / pos" into actual line and position information. */ 200static char *lines[MAXLINES]; 201static int lastline; 202 203/* Used to determine whether a type can be void (only return types). */ 204enum void_status 205{ 206 VOID_NOTOK, 207 VOID_OK 208}; 209 210/* Stanzas are groupings of built-in functions and overloads by some 211 common feature/attribute. These definitions are for built-in function 212 stanzas. */ 213enum bif_stanza 214{ 215 BSTZ_ALWAYS, 216 BSTZ_P5, 217 BSTZ_P6, 218 BSTZ_P6_64, 219 BSTZ_ALTIVEC, 220 BSTZ_CELL, 221 BSTZ_VSX, 222 BSTZ_P7, 223 BSTZ_P7_64, 224 BSTZ_P8, 225 BSTZ_P8V, 226 BSTZ_P9, 227 BSTZ_P9_64, 228 BSTZ_P9V, 229 BSTZ_IEEE128_HW, 230 BSTZ_DFP, 231 BSTZ_CRYPTO, 232 BSTZ_HTM, 233 BSTZ_P10, 234 BSTZ_P10_64, 235 BSTZ_MMA, 236 NUMBIFSTANZAS 237}; 238 239static bif_stanza curr_bif_stanza; 240 241struct stanza_entry 242{ 243 const char *stanza_name; 244 bif_stanza stanza; 245}; 246 247static stanza_entry stanza_map[NUMBIFSTANZAS] = 248 { 249 { "always", BSTZ_ALWAYS }, 250 { "power5", BSTZ_P5 }, 251 { "power6", BSTZ_P6 }, 252 { "power6-64", BSTZ_P6_64 }, 253 { "altivec", BSTZ_ALTIVEC }, 254 { "cell", BSTZ_CELL }, 255 { "vsx", BSTZ_VSX }, 256 { "power7", BSTZ_P7 }, 257 { "power7-64", BSTZ_P7_64 }, 258 { "power8", BSTZ_P8 }, 259 { "power8-vector", BSTZ_P8V }, 260 { "power9", BSTZ_P9 }, 261 { "power9-64", BSTZ_P9_64 }, 262 { "power9-vector", BSTZ_P9V }, 263 { "ieee128-hw", BSTZ_IEEE128_HW }, 264 { "dfp", BSTZ_DFP }, 265 { "crypto", BSTZ_CRYPTO }, 266 { "htm", BSTZ_HTM }, 267 { "power10", BSTZ_P10 }, 268 { "power10-64", BSTZ_P10_64 }, 269 { "mma", BSTZ_MMA } 270 }; 271 272static const char *enable_string[NUMBIFSTANZAS] = 273 { 274 "ENB_ALWAYS", 275 "ENB_P5", 276 "ENB_P6", 277 "ENB_P6_64", 278 "ENB_ALTIVEC", 279 "ENB_CELL", 280 "ENB_VSX", 281 "ENB_P7", 282 "ENB_P7_64", 283 "ENB_P8", 284 "ENB_P8V", 285 "ENB_P9", 286 "ENB_P9_64", 287 "ENB_P9V", 288 "ENB_IEEE128_HW", 289 "ENB_DFP", 290 "ENB_CRYPTO", 291 "ENB_HTM", 292 "ENB_P10", 293 "ENB_P10_64", 294 "ENB_MMA" 295 }; 296 297/* Function modifiers provide special handling for const, pure, and fpmath 298 functions. These are mutually exclusive, and therefore kept separate 299 from other bif attributes. */ 300enum fnkinds 301{ 302 FNK_NONE, 303 FNK_CONST, 304 FNK_PURE, 305 FNK_FPMATH 306}; 307 308/* Legal base types for an argument or return type. */ 309enum basetype 310{ 311 BT_CHAR, 312 BT_SHORT, 313 BT_INT, 314 BT_LONG, 315 BT_LONGLONG, 316 BT_FLOAT, 317 BT_DOUBLE, 318 BT_LONGDOUBLE, 319 BT_INT128, 320 BT_FLOAT128, 321 BT_BOOL, 322 BT_STRING, 323 BT_DECIMAL32, 324 BT_DECIMAL64, 325 BT_DECIMAL128, 326 BT_IBM128, 327 BT_VPAIR, 328 BT_VQUAD 329}; 330 331/* Ways in which a const int value can be restricted. RES_BITS indicates 332 that the integer is restricted to val1 bits, interpreted as an unsigned 333 number. RES_RANGE indicates that the integer is restricted to values 334 between val1 and val2, inclusive. RES_VAR_RANGE is like RES_RANGE, but 335 the argument may be variable, so it can only be checked if it is constant. 336 RES_VALUES indicates that the integer must have one of the values val1 337 or val2. */ 338enum restriction 339{ 340 RES_NONE, 341 RES_BITS, 342 RES_RANGE, 343 RES_VAR_RANGE, 344 RES_VALUES 345}; 346 347/* Type modifiers for an argument or return type. */ 348struct typeinfo 349{ 350 char isvoid; 351 char isconst; 352 char isvector; 353 char issigned; 354 char isunsigned; 355 char isbool; 356 char ispixel; 357 char ispointer; 358 basetype base; 359 restriction restr; 360 char *val1; 361 char *val2; 362}; 363 364/* A list of argument types. */ 365struct typelist 366{ 367 typeinfo info; 368 typelist *next; 369}; 370 371/* Attributes of a builtin function. */ 372struct attrinfo 373{ 374 bool isinit; 375 bool isset; 376 bool isextract; 377 bool isnosoft; 378 bool isldvec; 379 bool isstvec; 380 bool isreve; 381 bool ispred; 382 bool ishtm; 383 bool ishtmspr; 384 bool ishtmcr; 385 bool ismma; 386 bool isquad; 387 bool ispair; 388 bool ismmaint; 389 bool isno32bit; 390 bool is32bit; 391 bool iscpu; 392 bool isldstmask; 393 bool islxvrse; 394 bool islxvrze; 395 bool isendian; 396 bool isibmld; 397 bool isibm128; 398}; 399 400/* Fields associated with a function prototype (bif or overload). */ 401#define MAXRESTROPNDS 3 402struct prototype 403{ 404 typeinfo rettype; 405 char *bifname; 406 int nargs; 407 typelist *args; 408 int restr_opnd[MAXRESTROPNDS]; 409 restriction restr[MAXRESTROPNDS]; 410 char *restr_val1[MAXRESTROPNDS]; 411 char *restr_val2[MAXRESTROPNDS]; 412}; 413 414/* Data associated with a builtin function, and a table of such data. */ 415#define MAXBIFS 16384 416struct bifdata 417{ 418 int stanza; 419 fnkinds kind; 420 prototype proto; 421 char *idname; 422 char *patname; 423 attrinfo attrs; 424 char *fndecl; 425}; 426 427static bifdata bifs[MAXBIFS]; 428static int num_bifs; 429static int curr_bif; 430 431/* Array used to track the order in which built-ins appeared in the 432 built-in file. We reorder them alphabetically but sometimes need 433 this information. */ 434static int *bif_order; 435static int bif_index = 0; 436 437/* Stanzas are groupings of built-in functions and overloads by some 438 common feature/attribute. These definitions are for overload stanzas. */ 439struct ovld_stanza 440{ 441 char *stanza_id; 442 char *extern_name; 443 char *intern_name; 444 char *ifdef; 445}; 446 447#define MAXOVLDSTANZAS 512 448static ovld_stanza ovld_stanzas[MAXOVLDSTANZAS]; 449static int num_ovld_stanzas; 450static int curr_ovld_stanza; 451 452#define MAXOVLDS 16384 453struct ovlddata 454{ 455 int stanza; 456 prototype proto; 457 char *bif_id_name; 458 char *ovld_id_name; 459 char *fndecl; 460}; 461 462static ovlddata ovlds[MAXOVLDS]; 463static int num_ovlds; 464static int curr_ovld; 465static int max_ovld_args = 0; 466 467/* Return codes for parsing routines. */ 468enum parse_codes 469{ 470 PC_OK, 471 PC_EOFILE, 472 PC_EOSTANZA, 473 PC_PARSEFAIL 474}; 475 476/* The red-black trees for built-in function identifiers, built-in 477 overload identifiers, and function type descriptors. */ 478static rbt_strings bif_rbt; 479static rbt_strings ovld_rbt; 480static rbt_strings fntype_rbt; 481 482/* Another red-black tree containing a mapping from built-in function 483 identifiers to the order in which they were encountered. */ 484static rbt_strings bifo_rbt; 485 486/* Mapping from type tokens to type node names. */ 487struct typemap 488{ 489 const char *key; 490 const char *value; 491}; 492 493/* This table must be kept in alphabetical order, as we use binary 494 search for table lookups in map_token_to_type_node. The table 495 maps tokens from a fntype string to a tree type. For example, 496 in "si_ftype_hi" we would map "si" to "intSI_type_node" and 497 map "hi" to "intHI_type_node". */ 498static typemap type_map[] = 499 { 500 { "bi", "bool_int" }, 501 { "bv16qi", "bool_V16QI" }, 502 { "bv1ti", "bool_V1TI" }, 503 { "bv2di", "bool_V2DI" }, 504 { "bv4si", "bool_V4SI" }, 505 { "bv8hi", "bool_V8HI" }, 506 { "ci", "integer" }, 507 { "dd", "dfloat64" }, 508 { "df", "double" }, 509 { "di", "long_long_integer" }, 510 { "hi", "intHI" }, 511 { "if", "ibm128_float_type_node " 512 "? ibm128_float_type_node " 513 ": long_double" }, 514 { "ld", "long_double" }, 515 { "lg", "long_integer" }, 516 { "pbv16qi", "ptr_bool_V16QI" }, 517 { "pbv1ti", "ptr_bool_V1TI" }, 518 { "pbv2di", "ptr_bool_V2DI" }, 519 { "pbv4si", "ptr_bool_V4SI" }, 520 { "pbv8hi", "ptr_bool_V8HI" }, 521 { "pcvoid", "pcvoid" }, 522 { "pdd", "ptr_dfloat64" }, 523 { "pdf", "ptr_double" }, 524 { "pdi", "ptr_long_long_integer" }, 525 { "phi", "ptr_intHI" }, 526 { "pld", "ptr_long_double" }, 527 { "plg", "ptr_long_integer" }, 528 { "pqi", "ptr_intQI" }, 529 { "psf", "ptr_float" }, 530 { "psi", "ptr_intSI" }, 531 { "ptd", "ptr_dfloat128" }, 532 { "ptf", "ptr_float128" }, 533 { "pti", "ptr_intTI" }, 534 { "pudi", "ptr_long_long_unsigned" }, 535 { "puhi", "ptr_uintHI" }, 536 { "pulg", "ptr_long_unsigned" }, 537 { "puqi", "ptr_uintQI" }, 538 { "pusi", "ptr_uintSI" }, 539 { "puti", "ptr_uintTI" }, 540 { "puv16qi", "ptr_unsigned_V16QI" }, 541 { "puv1ti", "ptr_unsigned_V1TI" }, 542 { "puv2di", "ptr_unsigned_V2DI" }, 543 { "puv4si", "ptr_unsigned_V4SI" }, 544 { "puv8hi", "ptr_unsigned_V8HI" }, 545 { "pv", "ptr" }, 546 { "pv16qi", "ptr_V16QI" }, 547 { "pv1poi", "ptr_vector_pair" }, 548 { "pv1pxi", "ptr_vector_quad" }, 549 { "pv1ti", "ptr_V1TI" }, 550 { "pv2df", "ptr_V2DF" }, 551 { "pv2di", "ptr_V2DI" }, 552 { "pv4sf", "ptr_V4SF" }, 553 { "pv4si", "ptr_V4SI" }, 554 { "pv8hi", "ptr_V8HI" }, 555 { "pvp8hi", "ptr_pixel_V8HI" }, 556 { "qi", "intQI" }, 557 { "sd", "dfloat32" }, 558 { "sf", "float" }, 559 { "si", "intSI" }, 560 { "st", "const_str" }, 561 { "td", "dfloat128" }, 562 { "tf", "float128" }, 563 { "ti", "intTI" }, 564 { "udi", "long_long_unsigned" }, 565 { "uhi", "unsigned_intHI" }, 566 { "ulg", "long_unsigned" }, 567 { "uqi", "unsigned_intQI" }, 568 { "usi", "unsigned_intSI" }, 569 { "uti", "unsigned_intTI" }, 570 { "uv16qi", "unsigned_V16QI" }, 571 { "uv1ti", "unsigned_V1TI" }, 572 { "uv2di", "unsigned_V2DI" }, 573 { "uv4si", "unsigned_V4SI" }, 574 { "uv8hi", "unsigned_V8HI" }, 575 { "v", "void" }, 576 { "v16qi", "V16QI" }, 577 { "v1poi", "vector_pair" }, 578 { "v1pxi", "vector_quad" }, 579 { "v1ti", "V1TI" }, 580 { "v2df", "V2DF" }, 581 { "v2di", "V2DI" }, 582 { "v4sf", "V4SF" }, 583 { "v4si", "V4SI" }, 584 { "v8hi", "V8HI" }, 585 { "vp8hi", "pixel_V8HI" }, 586 }; 587 588/* From a possibly extended line with a virtual position, calculate 589 the current line and character position. */ 590static void 591real_line_pos (int diagpos, int *real_line, int *real_pos) 592{ 593 *real_line = line - lastline; 594 *real_pos = diagpos; 595 596 for (int i = 0; i < MAXLINES; i++) 597 { 598 int len = strlen(lines[i]); 599 if (*real_pos <= len) 600 break; 601 602 (*real_line)++; 603 *real_pos -= len - 2; 604 } 605 606 /* Convert from zero-base to one-base for printing. */ 607 (*real_pos)++; 608} 609 610/* Pointer to a diagnostic function. */ 611static void (*diag) (int, const char *, ...) 612 __attribute__ ((format (printf, 2, 3))); 613 614/* Custom diagnostics. */ 615static void __attribute__ ((format (printf, 2, 3))) 616bif_diag (int diagpos, const char * fmt, ...) 617{ 618 va_list args; 619 int real_line, real_pos; 620 real_line_pos (diagpos, &real_line, &real_pos); 621 fprintf (stderr, "%s:%d:%d: ", bif_path, real_line, real_pos); 622 va_start (args, fmt); 623 vfprintf (stderr, fmt, args); 624 va_end (args); 625} 626 627static void __attribute__ ((format (printf, 2, 3))) 628ovld_diag (int diagpos, const char * fmt, ...) 629{ 630 va_list args; 631 int real_line, real_pos; 632 real_line_pos (diagpos, &real_line, &real_pos); 633 fprintf (stderr, "%s:%d:%d: ", ovld_path, real_line, real_pos); 634 va_start (args, fmt); 635 vfprintf (stderr, fmt, args); 636 va_end (args); 637} 638 639/* Produce a fatal error message. */ 640static void 641fatal (const char *msg) 642{ 643 fprintf (stderr, "FATAL: %s\n", msg); 644 abort (); 645} 646 647/* Pass over whitespace (other than a newline, which terminates the scan). */ 648static void 649consume_whitespace (void) 650{ 651 while (pos < LINELEN && isspace(linebuf[pos]) && linebuf[pos] != '\n') 652 pos++; 653 654 if (pos >= LINELEN) 655 { 656 diag (pos, "line length overrun.\n"); 657 exit (1); 658 } 659 660 return; 661} 662 663/* Get the next nonblank, noncomment line, returning 0 on EOF, 1 otherwise. */ 664static int 665advance_line (FILE *file) 666{ 667 while (1) 668 { 669 /* Read ahead one line and check for EOF. */ 670 if (!fgets (linebuf, sizeof linebuf, file)) 671 return 0; 672 line++; 673 size_t len = strlen (linebuf); 674 675 /* Escape-newline processing. */ 676 lastline = 0; 677 if (len > 1) 678 { 679 strcpy (lines[0], linebuf); 680 while (linebuf[len - 2] == '\\' 681 && linebuf[len - 1] == '\n') 682 { 683 lastline++; 684 if (lastline == MAXLINES) 685 fatal ("number of supported overflow lines exceeded"); 686 line++; 687 if (!fgets (lines[lastline], LINELEN, file)) 688 fatal ("unexpected end of file"); 689 strcpy (&linebuf[len - 2], lines[lastline]); 690 len += strlen (lines[lastline]) - 2; 691 } 692 } 693 694 if (linebuf[len - 1] != '\n') 695 fatal ("line doesn't terminate with newline"); 696 pos = 0; 697 consume_whitespace (); 698 if (linebuf[pos] != '\n' && linebuf[pos] != ';') 699 return 1; 700 } 701} 702 703static inline void 704safe_inc_pos (void) 705{ 706 if (++pos >= LINELEN) 707 { 708 diag (pos, "line length overrun.\n"); 709 exit (1); 710 } 711} 712 713/* Match an identifier, returning NULL on failure, else a pointer to a 714 buffer containing the identifier. */ 715static char * 716match_identifier (void) 717{ 718 int lastpos = pos - 1; 719 while (lastpos < LINELEN - 1 720 && (isalnum (linebuf[lastpos + 1]) || linebuf[lastpos + 1] == '_')) 721 ++lastpos; 722 723 if (lastpos >= LINELEN - 1) 724 { 725 diag (lastpos, "line length overrun.\n"); 726 exit (1); 727 } 728 729 if (lastpos < pos) 730 return 0; 731 732 char *buf = (char *) malloc (lastpos - pos + 2); 733 memcpy (buf, &linebuf[pos], lastpos - pos + 1); 734 buf[lastpos - pos + 1] = '\0'; 735 736 pos = lastpos + 1; 737 return buf; 738} 739 740/* Match an integer and return the string representing its value, 741 or a null string on failure. */ 742static char * 743match_integer (void) 744{ 745 int startpos = pos; 746 if (linebuf[pos] == '-') 747 safe_inc_pos (); 748 749 int lastpos = pos - 1; 750 while (lastpos < LINELEN - 1 && isdigit (linebuf[lastpos + 1])) 751 ++lastpos; 752 753 if (lastpos >= LINELEN - 1) 754 { 755 diag (lastpos, "line length overrun.\n"); 756 exit (1); 757 } 758 759 if (lastpos < pos) 760 return NULL; 761 762 pos = lastpos + 1; 763 char *buf = (char *) malloc (lastpos - startpos + 2); 764 memcpy (buf, &linebuf[startpos], lastpos - startpos + 1); 765 buf[lastpos - startpos + 1] = '\0'; 766 return buf; 767} 768 769/* Match a string up to but not including a ']', and return its value, 770 or zero if there is nothing before the ']'. Error if we don't find 771 such a character. */ 772static const char * 773match_to_right_bracket (void) 774{ 775 int lastpos = pos - 1; 776 while (lastpos < LINELEN - 1 && linebuf[lastpos + 1] != ']') 777 { 778 if (linebuf[lastpos + 1] == '\n') 779 fatal ("no ']' found before end of line.\n"); 780 ++lastpos; 781 } 782 783 if (lastpos >= LINELEN - 1) 784 { 785 diag (lastpos, "line length overrun.\n"); 786 exit (1); 787 } 788 789 if (lastpos < pos) 790 return 0; 791 792 char *buf = (char *) malloc (lastpos - pos + 2); 793 memcpy (buf, &linebuf[pos], lastpos - pos + 1); 794 buf[lastpos - pos + 1] = '\0'; 795 796 pos = lastpos + 1; 797 return buf; 798} 799 800static inline void 801handle_pointer (typeinfo *typedata) 802{ 803 consume_whitespace (); 804 if (linebuf[pos] == '*') 805 { 806 typedata->ispointer = 1; 807 safe_inc_pos (); 808 } 809} 810 811static bif_stanza 812stanza_name_to_stanza (const char *stanza_name) 813{ 814 for (int i = 0; i < NUMBIFSTANZAS; i++) 815 if (!strcmp (stanza_name, stanza_map[i].stanza_name)) 816 return stanza_map[i].stanza; 817 fatal ("Stanza mapping is inconsistent."); 818 /* Unreachable. */ 819 return BSTZ_ALWAYS; 820} 821 822/* Match one of the allowable base types. Consumes one token unless the 823 token is "long", which must be paired with a second "long". Optionally 824 consumes a following '*' token for pointers. Return 1 for success, 825 0 for failure. */ 826static int 827match_basetype (typeinfo *typedata) 828{ 829 consume_whitespace (); 830 int oldpos = pos; 831 char *token = match_identifier (); 832 if (!token) 833 { 834 diag (pos, "missing base type in return type\n"); 835 return 0; 836 } 837 838 if (!strcmp (token, "char")) 839 typedata->base = BT_CHAR; 840 else if (!strcmp (token, "short")) 841 typedata->base = BT_SHORT; 842 else if (!strcmp (token, "int")) 843 typedata->base = BT_INT; 844 else if (!strcmp (token, "long")) 845 { 846 consume_whitespace (); 847 oldpos = pos; 848 char *mustbelongordbl = match_identifier (); 849 if (!mustbelongordbl) 850 typedata->base = BT_LONG; 851 else if (!strcmp (mustbelongordbl, "long")) 852 typedata->base = BT_LONGLONG; 853 else if (!strcmp (mustbelongordbl, "double")) 854 typedata->base = BT_LONGDOUBLE; 855 else 856 /* Speculatively accept "long" here and push back the token. 857 This occurs when "long" is a return type and the next token 858 is the function name. */ 859 { 860 typedata->base = BT_LONG; 861 pos = oldpos; 862 } 863 } 864 else if (!strcmp (token, "float")) 865 typedata->base = BT_FLOAT; 866 else if (!strcmp (token, "double")) 867 typedata->base = BT_DOUBLE; 868 else if (!strcmp (token, "__int128")) 869 typedata->base = BT_INT128; 870 else if (!strcmp (token, "_Float128")) 871 typedata->base = BT_FLOAT128; 872 else if (!strcmp (token, "bool")) 873 typedata->base = BT_BOOL; 874 /* A "string" is a special "const char *" -- we need it because it 875 cannot match either signed or unsigned char *. */ 876 else if (!strcmp (token, "string")) 877 typedata->base = BT_STRING; 878 else if (!strcmp (token, "_Decimal32")) 879 typedata->base = BT_DECIMAL32; 880 else if (!strcmp (token, "_Decimal64")) 881 typedata->base = BT_DECIMAL64; 882 else if (!strcmp (token, "_Decimal128")) 883 typedata->base = BT_DECIMAL128; 884 else if (!strcmp (token, "__ibm128")) 885 typedata->base = BT_IBM128; 886 else 887 { 888 diag (oldpos, "unrecognized base type\n"); 889 return 0; 890 } 891 892 handle_pointer (typedata); 893 return 1; 894} 895 896/* Helper routine for match_const_restriction. */ 897static int 898match_bracketed_pair (typeinfo *typedata, char open, char close, 899 restriction restr) 900{ 901 if (linebuf[pos] == open) 902 { 903 safe_inc_pos (); 904 int oldpos = pos; 905 char *x = match_integer (); 906 if (x == NULL) 907 { 908 diag (oldpos, "malformed integer.\n"); 909 return 0; 910 } 911 consume_whitespace (); 912 if (linebuf[pos] != ',') 913 { 914 diag (pos, "missing comma.\n"); 915 return 0; 916 } 917 safe_inc_pos (); 918 consume_whitespace (); 919 oldpos = pos; 920 char *y = match_integer (); 921 if (y == NULL) 922 { 923 diag (oldpos, "malformed integer.\n"); 924 return 0; 925 } 926 typedata->restr = restr; 927 typedata->val1 = x; 928 typedata->val2 = y; 929 930 consume_whitespace (); 931 if (linebuf[pos] != close) 932 { 933 diag (pos, "malformed restriction.\n"); 934 return 0; 935 } 936 safe_inc_pos (); 937 return 1; 938 } 939 940 return 0; 941} 942 943/* A const int argument may be restricted to certain values. This is 944 indicated by one of the following occurring after the "int' token: 945 946 <x> restricts the constant to x bits, interpreted as unsigned 947 <x,y> restricts the constant to the inclusive range [x,y] 948 [x,y] restricts the constant to the inclusive range [x,y], 949 but only applies if the argument is constant. 950 {x,y} restricts the constant to one of two values, x or y. 951 952 Here x and y are integer tokens. Note that the "const" token is a 953 lie when the restriction is [x,y], but this simplifies the parsing 954 significantly and is hopefully forgivable. 955 956 Return 1 for success, else 0. */ 957static int 958match_const_restriction (typeinfo *typedata) 959{ 960 int oldpos = pos; 961 if (linebuf[pos] == '<') 962 { 963 safe_inc_pos (); 964 oldpos = pos; 965 char *x = match_integer (); 966 if (x == NULL) 967 { 968 diag (oldpos, "malformed integer.\n"); 969 return 0; 970 } 971 consume_whitespace (); 972 if (linebuf[pos] == '>') 973 { 974 typedata->restr = RES_BITS; 975 typedata->val1 = x; 976 safe_inc_pos (); 977 return 1; 978 } 979 else if (linebuf[pos] != ',') 980 { 981 diag (pos, "malformed restriction.\n"); 982 return 0; 983 } 984 safe_inc_pos (); 985 oldpos = pos; 986 char *y = match_integer (); 987 if (y == NULL) 988 { 989 diag (oldpos, "malformed integer.\n"); 990 return 0; 991 } 992 typedata->restr = RES_RANGE; 993 typedata->val1 = x; 994 typedata->val2 = y; 995 996 consume_whitespace (); 997 if (linebuf[pos] != '>') 998 { 999 diag (pos, "malformed restriction.\n"); 1000 return 0; 1001 } 1002 safe_inc_pos (); 1003 return 1; 1004 } 1005 else if (match_bracketed_pair (typedata, '{', '}', RES_VALUES) 1006 || match_bracketed_pair (typedata, '[', ']', RES_VAR_RANGE)) 1007 return 1; 1008 1009 return 0; 1010} 1011 1012/* Look for a type, which can be terminated by a token that is not part of 1013 a type, a comma, or a closing parenthesis. Place information about the 1014 type in TYPEDATA. Return 1 for success, 0 for failure. */ 1015static int 1016match_type (typeinfo *typedata, int voidok) 1017{ 1018 /* A legal type is of the form: 1019 1020 [const] [[signed|unsigned] <basetype> | <vectype>] [*] 1021 1022 Legal values of <basetype> are (for now): 1023 1024 char 1025 short 1026 int 1027 long 1028 long double 1029 long long 1030 float 1031 double 1032 __int128 1033 _Float128 1034 bool 1035 string 1036 _Decimal32 1037 _Decimal64 1038 _Decimal128 1039 __ibm128 1040 1041 Legal values of <vectype> are as follows, and are shorthand for 1042 the associated meaning: 1043 1044 vsc vector signed char 1045 vuc vector unsigned char 1046 vbc vector bool char 1047 vss vector signed short 1048 vus vector unsigned short 1049 vbs vector bool short 1050 vsi vector signed int 1051 vui vector unsigned int 1052 vbi vector bool int 1053 vsll vector signed long long 1054 vull vector unsigned long long 1055 vbll vector bool long long 1056 vsq vector signed __int128 1057 vuq vector unsigned __int128 1058 vbq vector bool __int128 1059 vp vector pixel 1060 vf vector float 1061 vd vector double 1062 v256 __vector_pair 1063 v512 __vector_quad 1064 1065 For simplicity, We don't support "short int" and "long long int". 1066 We don't currently support a <basetype> of "_Float16". "signed" 1067 and "unsigned" only apply to integral base types. The optional * 1068 indicates a pointer type. */ 1069 1070 consume_whitespace (); 1071 memset (typedata, 0, sizeof *typedata); 1072 int oldpos = pos; 1073 1074 char *token = match_identifier (); 1075 if (!token) 1076 return 0; 1077 1078 if (!strcmp (token, "const")) 1079 { 1080 typedata->isconst = 1; 1081 consume_whitespace (); 1082 oldpos = pos; 1083 token = match_identifier (); 1084 } 1085 1086 if (!strcmp (token, "void")) 1087 typedata->isvoid = 1; 1088 1089 if (!strcmp (token, "vsc")) 1090 { 1091 typedata->isvector = 1; 1092 typedata->issigned = 1; 1093 typedata->base = BT_CHAR; 1094 handle_pointer (typedata); 1095 return 1; 1096 } 1097 else if (!strcmp (token, "vuc")) 1098 { 1099 typedata->isvector = 1; 1100 typedata->isunsigned = 1; 1101 typedata->base = BT_CHAR; 1102 handle_pointer (typedata); 1103 return 1; 1104 } 1105 else if (!strcmp (token, "vbc")) 1106 { 1107 typedata->isvector = 1; 1108 typedata->isbool = 1; 1109 typedata->base = BT_CHAR; 1110 handle_pointer (typedata); 1111 return 1; 1112 } 1113 else if (!strcmp (token, "vss")) 1114 { 1115 typedata->isvector = 1; 1116 typedata->issigned = 1; 1117 typedata->base = BT_SHORT; 1118 handle_pointer (typedata); 1119 return 1; 1120 } 1121 else if (!strcmp (token, "vus")) 1122 { 1123 typedata->isvector = 1; 1124 typedata->isunsigned = 1; 1125 typedata->base = BT_SHORT; 1126 handle_pointer (typedata); 1127 return 1; 1128 } 1129 else if (!strcmp (token, "vbs")) 1130 { 1131 typedata->isvector = 1; 1132 typedata->isbool = 1; 1133 typedata->base = BT_SHORT; 1134 handle_pointer (typedata); 1135 return 1; 1136 } 1137 else if (!strcmp (token, "vsi")) 1138 { 1139 typedata->isvector = 1; 1140 typedata->issigned = 1; 1141 typedata->base = BT_INT; 1142 handle_pointer (typedata); 1143 return 1; 1144 } 1145 else if (!strcmp (token, "vui")) 1146 { 1147 typedata->isvector = 1; 1148 typedata->isunsigned = 1; 1149 typedata->base = BT_INT; 1150 handle_pointer (typedata); 1151 return 1; 1152 } 1153 else if (!strcmp (token, "vbi")) 1154 { 1155 typedata->isvector = 1; 1156 typedata->isbool = 1; 1157 typedata->base = BT_INT; 1158 handle_pointer (typedata); 1159 return 1; 1160 } 1161 else if (!strcmp (token, "vsll")) 1162 { 1163 typedata->isvector = 1; 1164 typedata->issigned = 1; 1165 typedata->base = BT_LONGLONG; 1166 handle_pointer (typedata); 1167 return 1; 1168 } 1169 else if (!strcmp (token, "vull")) 1170 { 1171 typedata->isvector = 1; 1172 typedata->isunsigned = 1; 1173 typedata->base = BT_LONGLONG; 1174 handle_pointer (typedata); 1175 return 1; 1176 } 1177 else if (!strcmp (token, "vbll")) 1178 { 1179 typedata->isvector = 1; 1180 typedata->isbool = 1; 1181 typedata->base = BT_LONGLONG; 1182 handle_pointer (typedata); 1183 return 1; 1184 } 1185 else if (!strcmp (token, "vsq")) 1186 { 1187 typedata->isvector = 1; 1188 typedata->issigned = 1; 1189 typedata->base = BT_INT128; 1190 handle_pointer (typedata); 1191 return 1; 1192 } 1193 else if (!strcmp (token, "vuq")) 1194 { 1195 typedata->isvector = 1; 1196 typedata->isunsigned = 1; 1197 typedata->base = BT_INT128; 1198 handle_pointer (typedata); 1199 return 1; 1200 } 1201 else if (!strcmp (token, "vbq")) 1202 { 1203 typedata->isvector = 1; 1204 typedata->isbool = 1; 1205 typedata->base = BT_INT128; 1206 handle_pointer (typedata); 1207 return 1; 1208 } 1209 else if (!strcmp (token, "vp")) 1210 { 1211 typedata->isvector = 1; 1212 typedata->ispixel = 1; 1213 typedata->base = BT_SHORT; 1214 handle_pointer (typedata); 1215 return 1; 1216 } 1217 else if (!strcmp (token, "vf")) 1218 { 1219 typedata->isvector = 1; 1220 typedata->base = BT_FLOAT; 1221 handle_pointer (typedata); 1222 return 1; 1223 } 1224 else if (!strcmp (token, "vd")) 1225 { 1226 typedata->isvector = 1; 1227 typedata->base = BT_DOUBLE; 1228 handle_pointer (typedata); 1229 return 1; 1230 } 1231 else if (!strcmp (token, "v256")) 1232 { 1233 typedata->isvector = 1; 1234 typedata->base = BT_VPAIR; 1235 handle_pointer (typedata); 1236 return 1; 1237 } 1238 else if (!strcmp (token, "v512")) 1239 { 1240 typedata->isvector = 1; 1241 typedata->base = BT_VQUAD; 1242 handle_pointer (typedata); 1243 return 1; 1244 } 1245 else if (!strcmp (token, "signed")) 1246 typedata->issigned = 1; 1247 else if (!strcmp (token, "unsigned")) 1248 typedata->isunsigned = 1; 1249 else if (!typedata->isvoid && !typedata->isconst) 1250 { 1251 /* Push back token. */ 1252 pos = oldpos; 1253 return match_basetype (typedata); 1254 } 1255 1256 if (typedata->isvoid) 1257 { 1258 consume_whitespace (); 1259 if (linebuf[pos] == '*') 1260 { 1261 typedata->ispointer = 1; 1262 safe_inc_pos (); 1263 } 1264 else if (!voidok) 1265 return 0; 1266 return 1; 1267 } 1268 1269 if (!typedata->issigned && !typedata->isunsigned) 1270 pos = oldpos; 1271 if (!match_basetype (typedata)) 1272 return 0; 1273 1274 if (typedata->isconst) 1275 { 1276 if (typedata->ispointer) 1277 return 1; 1278 if (typedata->base != BT_INT) 1279 { 1280 diag (oldpos, "'const' requires pointer or integer type\n"); 1281 return 0; 1282 } 1283 consume_whitespace (); 1284 if (linebuf[pos] == '<' || linebuf[pos] == '{' || linebuf[pos] == '[') 1285 return match_const_restriction (typedata); 1286 } 1287 1288 return 1; 1289} 1290 1291/* Parse the argument list. */ 1292static parse_codes 1293parse_args (prototype *protoptr) 1294{ 1295 typelist **argptr = &protoptr->args; 1296 int *nargs = &protoptr->nargs; 1297 int *restr_opnd = protoptr->restr_opnd; 1298 restriction *restr = protoptr->restr; 1299 char **val1 = protoptr->restr_val1; 1300 char **val2 = protoptr->restr_val2; 1301 int restr_cnt = 0; 1302 1303 int success; 1304 *nargs = 0; 1305 1306 /* Start the argument list. */ 1307 consume_whitespace (); 1308 if (linebuf[pos] != '(') 1309 { 1310 diag (pos, "missing '('.\n"); 1311 return PC_PARSEFAIL; 1312 } 1313 safe_inc_pos (); 1314 1315 do { 1316 consume_whitespace (); 1317 int oldpos = pos; 1318 typelist *argentry = (typelist *) malloc (sizeof (typelist)); 1319 memset (argentry, 0, sizeof *argentry); 1320 typeinfo *argtype = &argentry->info; 1321 success = match_type (argtype, VOID_NOTOK); 1322 if (success) 1323 { 1324 if (argtype->restr) 1325 { 1326 if (restr_cnt >= MAXRESTROPNDS) 1327 { 1328 diag (pos, "More than two %d operands\n", MAXRESTROPNDS); 1329 return PC_PARSEFAIL; 1330 } 1331 restr_opnd[restr_cnt] = *nargs + 1; 1332 restr[restr_cnt] = argtype->restr; 1333 val1[restr_cnt] = argtype->val1; 1334 val2[restr_cnt] = argtype->val2; 1335 restr_cnt++; 1336 } 1337 (*nargs)++; 1338 *argptr = argentry; 1339 argptr = &argentry->next; 1340 consume_whitespace (); 1341 if (linebuf[pos] == ',') 1342 safe_inc_pos (); 1343 else if (linebuf[pos] != ')') 1344 { 1345 diag (pos, "arg not followed by ',' or ')'.\n"); 1346 return PC_PARSEFAIL; 1347 } 1348 1349#ifdef DEBUG 1350 diag (0, 1351 "argument type: isvoid = %d, isconst = %d, isvector = %d, " 1352 "issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, " 1353 "ispointer = %d, base = %d, restr = %d, val1 = \"%s\", " 1354 "val2 = \"%s\", pos = %d.\n", 1355 argtype->isvoid, argtype->isconst, argtype->isvector, 1356 argtype->issigned, argtype->isunsigned, argtype->isbool, 1357 argtype->ispixel, argtype->ispointer, argtype->base, 1358 argtype->restr, argtype->val1, argtype->val2, pos + 1); 1359#endif 1360 } 1361 else 1362 { 1363 free (argentry); 1364 *argptr = NULL; 1365 pos = oldpos; 1366 if (linebuf[pos] != ')') 1367 { 1368 diag (pos, "badly terminated arg list.\n"); 1369 return PC_PARSEFAIL; 1370 } 1371 safe_inc_pos (); 1372 } 1373 } while (success); 1374 1375 return PC_OK; 1376} 1377 1378/* Parse the attribute list. */ 1379static parse_codes 1380parse_bif_attrs (attrinfo *attrptr) 1381{ 1382 consume_whitespace (); 1383 if (linebuf[pos] != '{') 1384 { 1385 diag (pos, "missing attribute set.\n"); 1386 return PC_PARSEFAIL; 1387 } 1388 safe_inc_pos (); 1389 1390 memset (attrptr, 0, sizeof *attrptr); 1391 char *attrname = NULL; 1392 1393 do { 1394 consume_whitespace (); 1395 int oldpos = pos; 1396 attrname = match_identifier (); 1397 if (attrname) 1398 { 1399 if (!strcmp (attrname, "init")) 1400 attrptr->isinit = 1; 1401 else if (!strcmp (attrname, "set")) 1402 attrptr->isset = 1; 1403 else if (!strcmp (attrname, "extract")) 1404 attrptr->isextract = 1; 1405 else if (!strcmp (attrname, "nosoft")) 1406 attrptr->isnosoft = 1; 1407 else if (!strcmp (attrname, "ldvec")) 1408 attrptr->isldvec = 1; 1409 else if (!strcmp (attrname, "stvec")) 1410 attrptr->isstvec = 1; 1411 else if (!strcmp (attrname, "reve")) 1412 attrptr->isreve = 1; 1413 else if (!strcmp (attrname, "pred")) 1414 attrptr->ispred = 1; 1415 else if (!strcmp (attrname, "htm")) 1416 attrptr->ishtm = 1; 1417 else if (!strcmp (attrname, "htmspr")) 1418 attrptr->ishtmspr = 1; 1419 else if (!strcmp (attrname, "htmcr")) 1420 attrptr->ishtmcr = 1; 1421 else if (!strcmp (attrname, "mma")) 1422 attrptr->ismma = 1; 1423 else if (!strcmp (attrname, "quad")) 1424 attrptr->isquad = 1; 1425 else if (!strcmp (attrname, "pair")) 1426 attrptr->ispair = 1; 1427 else if (!strcmp (attrname, "mmaint")) 1428 attrptr->ismmaint = 1; 1429 else if (!strcmp (attrname, "no32bit")) 1430 attrptr->isno32bit = 1; 1431 else if (!strcmp (attrname, "32bit")) 1432 attrptr->is32bit = 1; 1433 else if (!strcmp (attrname, "cpu")) 1434 attrptr->iscpu = 1; 1435 else if (!strcmp (attrname, "ldstmask")) 1436 attrptr->isldstmask = 1; 1437 else if (!strcmp (attrname, "lxvrse")) 1438 attrptr->islxvrse = 1; 1439 else if (!strcmp (attrname, "lxvrze")) 1440 attrptr->islxvrze = 1; 1441 else if (!strcmp (attrname, "endian")) 1442 attrptr->isendian = 1; 1443 else if (!strcmp (attrname, "ibmld")) 1444 attrptr->isibmld = 1; 1445 else if (!strcmp (attrname, "ibm128")) 1446 attrptr->isibm128 = 1; 1447 else 1448 { 1449 diag (oldpos, "unknown attribute.\n"); 1450 return PC_PARSEFAIL; 1451 } 1452 1453 consume_whitespace (); 1454 if (linebuf[pos] == ',') 1455 safe_inc_pos (); 1456 else if (linebuf[pos] != '}') 1457 { 1458 diag (pos, "arg not followed by ',' or '}'.\n"); 1459 return PC_PARSEFAIL; 1460 } 1461 } 1462 else 1463 { 1464 pos = oldpos; 1465 if (linebuf[pos] != '}') 1466 { 1467 diag (pos, "badly terminated attr set.\n"); 1468 return PC_PARSEFAIL; 1469 } 1470 safe_inc_pos (); 1471 } 1472 } while (attrname); 1473 1474#ifdef DEBUG 1475 diag (0, 1476 "attribute set: init = %d, set = %d, extract = %d, nosoft = %d, " 1477 "ldvec = %d, stvec = %d, reve = %d, pred = %d, htm = %d, " 1478 "htmspr = %d, htmcr = %d, mma = %d, quad = %d, pair = %d, " 1479 "mmaint = %d, no32bit = %d, 32bit = %d, cpu = %d, ldstmask = %d, " 1480 "lxvrse = %d, lxvrze = %d, endian = %d, ibmdld = %d, ibm128 = %d.\n", 1481 attrptr->isinit, attrptr->isset, attrptr->isextract, 1482 attrptr->isnosoft, attrptr->isldvec, attrptr->isstvec, 1483 attrptr->isreve, attrptr->ispred, attrptr->ishtm, attrptr->ishtmspr, 1484 attrptr->ishtmcr, attrptr->ismma, attrptr->isquad, attrptr->ispair, 1485 attrptr->ismmaint, attrptr->isno32bit, attrptr->is32bit, 1486 attrptr->iscpu, attrptr->isldstmask, attrptr->islxvrse, 1487 attrptr->islxvrze, attrptr->isendian, attrptr->isibmld, 1488 attrptr->isibm128); 1489#endif 1490 1491 return PC_OK; 1492} 1493 1494/* Convert a vector type into a mode string. */ 1495static void 1496complete_vector_type (typeinfo *typeptr, char *buf, int *bufi) 1497{ 1498 if (typeptr->isbool) 1499 buf[(*bufi)++] = 'b'; 1500 buf[(*bufi)++] = 'v'; 1501 if (typeptr->ispixel) 1502 { 1503 memcpy (&buf[*bufi], "p8hi", 4); 1504 *bufi += 4; 1505 return; 1506 } 1507 switch (typeptr->base) 1508 { 1509 case BT_CHAR: 1510 memcpy (&buf[*bufi], "16qi", 4); 1511 *bufi += 4; 1512 break; 1513 case BT_SHORT: 1514 memcpy (&buf[*bufi], "8hi", 3); 1515 *bufi += 3; 1516 break; 1517 case BT_INT: 1518 memcpy (&buf[*bufi], "4si", 3); 1519 *bufi += 3; 1520 break; 1521 case BT_LONGLONG: 1522 memcpy (&buf[*bufi], "2di", 3); 1523 *bufi += 3; 1524 break; 1525 case BT_FLOAT: 1526 memcpy (&buf[*bufi], "4sf", 3); 1527 *bufi += 3; 1528 break; 1529 case BT_DOUBLE: 1530 memcpy (&buf[*bufi], "2df", 3); 1531 *bufi += 3; 1532 break; 1533 case BT_INT128: 1534 memcpy (&buf[*bufi], "1ti", 3); 1535 *bufi += 3; 1536 break; 1537 case BT_FLOAT128: 1538 memcpy (&buf[*bufi], "1tf", 3); 1539 *bufi += 3; 1540 break; 1541 case BT_VPAIR: 1542 memcpy (&buf[*bufi], "1poi", 4); 1543 *bufi += 4; 1544 break; 1545 case BT_VQUAD: 1546 memcpy (&buf[*bufi], "1pxi", 4); 1547 *bufi += 4; 1548 break; 1549 default: 1550 diag (pos, "unhandled basetype %d.\n", typeptr->base); 1551 exit (1); 1552 } 1553} 1554 1555/* Convert a base type into a mode string. */ 1556static void 1557complete_base_type (typeinfo *typeptr, char *buf, int *bufi) 1558{ 1559 switch (typeptr->base) 1560 { 1561 case BT_CHAR: 1562 memcpy (&buf[*bufi], "qi", 2); 1563 break; 1564 case BT_SHORT: 1565 memcpy (&buf[*bufi], "hi", 2); 1566 break; 1567 case BT_INT: 1568 memcpy (&buf[*bufi], "si", 2); 1569 break; 1570 case BT_LONG: 1571 memcpy (&buf[*bufi], "lg", 2); 1572 break; 1573 case BT_LONGLONG: 1574 memcpy (&buf[*bufi], "di", 2); 1575 break; 1576 case BT_FLOAT: 1577 memcpy (&buf[*bufi], "sf", 2); 1578 break; 1579 case BT_DOUBLE: 1580 memcpy (&buf[*bufi], "df", 2); 1581 break; 1582 case BT_LONGDOUBLE: 1583 memcpy (&buf[*bufi], "ld", 2); 1584 break; 1585 case BT_INT128: 1586 memcpy (&buf[*bufi], "ti", 2); 1587 break; 1588 case BT_FLOAT128: 1589 memcpy (&buf[*bufi], "tf", 2); 1590 break; 1591 case BT_BOOL: 1592 memcpy (&buf[*bufi], "bi", 2); 1593 break; 1594 case BT_STRING: 1595 memcpy (&buf[*bufi], "st", 2); 1596 break; 1597 case BT_DECIMAL32: 1598 memcpy (&buf[*bufi], "sd", 2); 1599 break; 1600 case BT_DECIMAL64: 1601 memcpy (&buf[*bufi], "dd", 2); 1602 break; 1603 case BT_DECIMAL128: 1604 memcpy (&buf[*bufi], "td", 2); 1605 break; 1606 case BT_IBM128: 1607 memcpy (&buf[*bufi], "if", 2); 1608 break; 1609 default: 1610 diag (pos, "unhandled basetype %d.\n", typeptr->base); 1611 exit (1); 1612 } 1613 1614 *bufi += 2; 1615} 1616 1617/* Build a function type descriptor identifier from the return type 1618 and argument types described by PROTOPTR, and store it if it does 1619 not already exist. Return the identifier. */ 1620static char * 1621construct_fntype_id (prototype *protoptr) 1622{ 1623 /* Determine the maximum space for a function type descriptor id. 1624 Each type requires at most 9 characters (6 for the mode*, 1 for 1625 the optional 'u' preceding the mode, 1 for the optional 'p' 1626 preceding the mode, and 1 for an underscore following the mode). 1627 We also need 5 characters for the string "ftype" that separates 1628 the return mode from the argument modes. The last argument doesn't 1629 need a trailing underscore, but we count that as the one trailing 1630 "ftype" instead. For the special case of zero arguments, we need 9 1631 for the return type and 7 for "ftype_v". Finally, we need one 1632 character for the terminating null. Thus for a function with N 1633 arguments, we need at most 9N+15 characters for N>0, otherwise 17. 1634 ---- 1635 *Worst case is bv16qi for "vector bool char". */ 1636 int len = protoptr->nargs ? (protoptr->nargs + 1) * 9 + 6 : 17; 1637 char *buf = (char *) malloc (len); 1638 int bufi = 0; 1639 1640 if (protoptr->rettype.ispointer) 1641 buf[bufi++] = 'p'; 1642 1643 if (protoptr->rettype.isvoid) 1644 buf[bufi++] = 'v'; 1645 else 1646 { 1647 if (protoptr->rettype.isunsigned) 1648 buf[bufi++] = 'u'; 1649 if (protoptr->rettype.isvector) 1650 complete_vector_type (&protoptr->rettype, buf, &bufi); 1651 else 1652 complete_base_type (&protoptr->rettype, buf, &bufi); 1653 } 1654 1655 memcpy (&buf[bufi], "_ftype", 6); 1656 bufi += 6; 1657 1658 if (!protoptr->nargs) 1659 { 1660 memcpy (&buf[bufi], "_v", 2); 1661 bufi += 2; 1662 } 1663 else 1664 { 1665 typelist *argptr = protoptr->args; 1666 for (int i = 0; i < protoptr->nargs; i++, argptr = argptr->next) 1667 { 1668 assert (argptr); 1669 buf[bufi++] = '_'; 1670 if (argptr->info.isconst 1671 && argptr->info.base == BT_INT 1672 && !argptr->info.ispointer) 1673 { 1674 buf[bufi++] = 'c'; 1675 buf[bufi++] = 'i'; 1676 continue; 1677 } 1678 if (argptr->info.ispointer) 1679 { 1680 if (argptr->info.isvoid) 1681 { 1682 if (argptr->info.isconst) 1683 { 1684 memcpy (&buf[bufi], "pcvoid", 6); 1685 bufi += 6; 1686 continue; 1687 } 1688 else 1689 { 1690 buf[bufi++] = 'p'; 1691 buf[bufi++] = 'v'; 1692 continue; 1693 } 1694 } 1695 else 1696 buf[bufi++] = 'p'; 1697 } 1698 1699 if (argptr->info.isunsigned) 1700 buf[bufi++] = 'u'; 1701 if (argptr->info.isvector) 1702 complete_vector_type (&argptr->info, buf, &bufi); 1703 else 1704 complete_base_type (&argptr->info, buf, &bufi); 1705 } 1706 assert (!argptr); 1707 } 1708 1709 buf[bufi] = '\0'; 1710 1711 /* Ignore return value, as duplicates are fine and expected here. */ 1712 rbt_insert (&fntype_rbt, buf); 1713 1714 return buf; 1715} 1716 1717/* Parse a function prototype. This code is shared by the bif and overload 1718 file processing. */ 1719static parse_codes 1720parse_prototype (prototype *protoptr) 1721{ 1722 typeinfo *ret_type = &protoptr->rettype; 1723 char **bifname = &protoptr->bifname; 1724 1725 /* Get the return type. */ 1726 consume_whitespace (); 1727 int oldpos = pos; 1728 int success = match_type (ret_type, VOID_OK); 1729 if (!success) 1730 { 1731 diag (oldpos, "missing or badly formed return type.\n"); 1732 return PC_PARSEFAIL; 1733 } 1734 1735#ifdef DEBUG 1736 diag (0, 1737 "return type: isvoid = %d, isconst = %d, isvector = %d, " 1738 "issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, " 1739 "ispointer = %d, base = %d, restr = %d, val1 = \"%s\", " 1740 "val2 = \"%s\", pos = %d.\n", 1741 ret_type->isvoid, ret_type->isconst, ret_type->isvector, 1742 ret_type->issigned, ret_type->isunsigned, ret_type->isbool, 1743 ret_type->ispixel, ret_type->ispointer, ret_type->base, 1744 ret_type->restr, ret_type->val1, ret_type->val2, pos + 1); 1745#endif 1746 1747 /* Get the bif name. */ 1748 consume_whitespace (); 1749 oldpos = pos; 1750 *bifname = match_identifier (); 1751 if (!*bifname) 1752 { 1753 diag (oldpos, "missing function name.\n"); 1754 return PC_PARSEFAIL; 1755 } 1756 1757#ifdef DEBUG 1758 diag (0, "function name is '%s'.\n", *bifname); 1759#endif 1760 1761 /* Process arguments. */ 1762 if (parse_args (protoptr) == PC_PARSEFAIL) 1763 return PC_PARSEFAIL; 1764 1765 /* Process terminating semicolon. */ 1766 consume_whitespace (); 1767 if (linebuf[pos] != ';') 1768 { 1769 diag (pos, "missing semicolon.\n"); 1770 return PC_PARSEFAIL; 1771 } 1772 safe_inc_pos (); 1773 consume_whitespace (); 1774 if (linebuf[pos] != '\n') 1775 { 1776 diag (pos, "garbage at end of line.\n"); 1777 return PC_PARSEFAIL; 1778 } 1779 1780 return PC_OK; 1781} 1782 1783/* Parse a two-line entry for a built-in function. */ 1784static parse_codes 1785parse_bif_entry (void) 1786{ 1787 /* Check for end of stanza. */ 1788 pos = 0; 1789 consume_whitespace (); 1790 if (linebuf[pos] == '[') 1791 return PC_EOSTANZA; 1792 1793 /* Allocate an entry in the bif table. */ 1794 if (num_bifs >= MAXBIFS - 1) 1795 { 1796 diag (pos, "too many built-in functions.\n"); 1797 return PC_PARSEFAIL; 1798 } 1799 1800 curr_bif = num_bifs++; 1801 bifs[curr_bif].stanza = curr_bif_stanza; 1802 1803 /* Read the first token and see if it is a function modifier. */ 1804 consume_whitespace (); 1805 int oldpos = pos; 1806 char *token = match_identifier (); 1807 if (!token) 1808 { 1809 diag (oldpos, "malformed entry.\n"); 1810 return PC_PARSEFAIL; 1811 } 1812 1813 if (!strcmp (token, "const")) 1814 bifs[curr_bif].kind = FNK_CONST; 1815 else if (!strcmp (token, "pure")) 1816 bifs[curr_bif].kind = FNK_PURE; 1817 else if (!strcmp (token, "fpmath")) 1818 bifs[curr_bif].kind = FNK_FPMATH; 1819 else 1820 { 1821 /* No function modifier, so push the token back. */ 1822 pos = oldpos; 1823 bifs[curr_bif].kind = FNK_NONE; 1824 } 1825 1826 if (parse_prototype (&bifs[curr_bif].proto) == PC_PARSEFAIL) 1827 return PC_PARSEFAIL; 1828 1829 /* Build a function type descriptor identifier from the return type 1830 and argument types, and store it if it does not already exist. */ 1831 bifs[curr_bif].fndecl = construct_fntype_id (&bifs[curr_bif].proto); 1832 1833 /* Now process line 2. First up is the builtin id. */ 1834 if (!advance_line (bif_file)) 1835 { 1836 diag (pos, "unexpected EOF.\n"); 1837 return PC_PARSEFAIL; 1838 } 1839 1840 pos = 0; 1841 consume_whitespace (); 1842 oldpos = pos; 1843 bifs[curr_bif].idname = match_identifier (); 1844 if (!bifs[curr_bif].idname) 1845 { 1846 diag (pos, "missing builtin id.\n"); 1847 return PC_PARSEFAIL; 1848 } 1849 1850#ifdef DEBUG 1851 diag (0, "ID name is '%s'.\n", bifs[curr_bif].idname); 1852#endif 1853 1854 /* Save the ID in a lookup structure. */ 1855 if (!rbt_insert (&bif_rbt, bifs[curr_bif].idname)) 1856 { 1857 diag (oldpos, "duplicate function ID '%s'.\n", bifs[curr_bif].idname); 1858 return PC_PARSEFAIL; 1859 } 1860 1861 /* Append a number representing the order in which this function 1862 was encountered to its name, and save in another lookup 1863 structure. */ 1864 int orig_len = strlen (bifs[curr_bif].idname); 1865 char *buf = (char *) malloc (orig_len + 7); 1866 sprintf (buf, "%s:%05d", bifs[curr_bif].idname, curr_bif); 1867 1868 if (!rbt_insert (&bifo_rbt, buf)) 1869 { 1870 diag (pos, "internal error inserting '%s' in bifo_rbt\n", buf); 1871 return PC_PARSEFAIL; 1872 } 1873 1874 /* Now the pattern name. */ 1875 consume_whitespace (); 1876 bifs[curr_bif].patname = match_identifier (); 1877 if (!bifs[curr_bif].patname) 1878 { 1879 diag (pos, "missing pattern name.\n"); 1880 return PC_PARSEFAIL; 1881 } 1882 1883#ifdef DEBUG 1884 diag (0, "pattern name is '%s'.\n", bifs[curr_bif].patname); 1885#endif 1886 1887 /* Process attributes. */ 1888 return parse_bif_attrs (&bifs[curr_bif].attrs); 1889} 1890 1891/* Parse one stanza of the input BIF file. linebuf already contains the 1892 first line to parse. */ 1893static parse_codes 1894parse_bif_stanza (void) 1895{ 1896 /* Parse the stanza header. */ 1897 pos = 0; 1898 consume_whitespace (); 1899 1900 if (linebuf[pos] != '[') 1901 { 1902 diag (pos, "ill-formed stanza header.\n"); 1903 return PC_PARSEFAIL; 1904 } 1905 safe_inc_pos (); 1906 1907 const char *stanza_name = match_to_right_bracket (); 1908 if (!stanza_name) 1909 { 1910 diag (pos, "no expression found in stanza header.\n"); 1911 return PC_PARSEFAIL; 1912 } 1913 1914 curr_bif_stanza = stanza_name_to_stanza (stanza_name); 1915 1916 if (linebuf[pos] != ']') 1917 { 1918 diag (pos, "ill-formed stanza header.\n"); 1919 return PC_PARSEFAIL; 1920 } 1921 safe_inc_pos (); 1922 1923 consume_whitespace (); 1924 if (linebuf[pos] != '\n' && pos != LINELEN - 1) 1925 { 1926 diag (pos, "garbage after stanza header.\n"); 1927 return PC_PARSEFAIL; 1928 } 1929 1930 parse_codes result = PC_OK; 1931 1932 while (result != PC_EOSTANZA) 1933 { 1934 if (!advance_line (bif_file)) 1935 return PC_EOFILE; 1936 result = parse_bif_entry (); 1937 if (result == PC_PARSEFAIL) 1938 return PC_PARSEFAIL; 1939 } 1940 1941 return PC_OK; 1942} 1943 1944/* Parse the built-in file. */ 1945static parse_codes 1946parse_bif (void) 1947{ 1948 parse_codes result; 1949 diag = &bif_diag; 1950 if (!advance_line (bif_file)) 1951 return PC_OK; 1952 1953 do 1954 result = parse_bif_stanza (); 1955 while (result == PC_OK); 1956 1957 if (result == PC_EOFILE) 1958 return PC_OK; 1959 return result; 1960} 1961 1962/* Callback function for create_bif_order. */ 1963void set_bif_order (char *str) 1964{ 1965 int num = 0; 1966 char *colon = strchr (str, ':'); 1967 sscanf (++colon, "%d", &num); 1968 bif_order[bif_index++] = num; 1969} 1970 1971/* Create a mapping from function IDs in their final order to the order 1972 they appear in the built-in function file. */ 1973static void 1974create_bif_order (void) 1975{ 1976 bif_order = (int *) malloc ((curr_bif + 1) * sizeof (int)); 1977 rbt_inorder_callback (&bifo_rbt, bifo_rbt.rbt_root, set_bif_order); 1978} 1979 1980/* Parse one two-line entry in the overload file. */ 1981static parse_codes 1982parse_ovld_entry (void) 1983{ 1984 /* Check for end of stanza. */ 1985 pos = 0; 1986 consume_whitespace (); 1987 if (linebuf[pos] == '[') 1988 return PC_EOSTANZA; 1989 1990 /* Allocate an entry in the overload table. */ 1991 if (num_ovlds >= MAXOVLDS - 1) 1992 { 1993 diag (pos, "too many overloads.\n"); 1994 return PC_PARSEFAIL; 1995 } 1996 1997 curr_ovld = num_ovlds++; 1998 ovlds[curr_ovld].stanza = curr_ovld_stanza; 1999 2000 if (parse_prototype (&ovlds[curr_ovld].proto) == PC_PARSEFAIL) 2001 return PC_PARSEFAIL; 2002 2003 if (ovlds[curr_ovld].proto.nargs > max_ovld_args) 2004 max_ovld_args = ovlds[curr_ovld].proto.nargs; 2005 2006 /* Build a function type descriptor identifier from the return type 2007 and argument types, and store it if it does not already exist. */ 2008 ovlds[curr_ovld].fndecl = construct_fntype_id (&ovlds[curr_ovld].proto); 2009 2010 /* Now process line 2, which just contains the builtin id and an 2011 optional overload id. */ 2012 if (!advance_line (ovld_file)) 2013 { 2014 diag (0, "unexpected EOF.\n"); 2015 return PC_EOFILE; 2016 } 2017 2018 pos = 0; 2019 consume_whitespace (); 2020 int oldpos = pos; 2021 char *id = match_identifier (); 2022 ovlds[curr_ovld].bif_id_name = id; 2023 ovlds[curr_ovld].ovld_id_name = id; 2024 if (!id) 2025 { 2026 diag (pos, "missing overload id.\n"); 2027 return PC_PARSEFAIL; 2028 } 2029 2030#ifdef DEBUG 2031 diag (pos, "ID name is '%s'.\n", id); 2032#endif 2033 2034 /* The builtin id has to match one from the bif file. */ 2035 if (!rbt_find (&bif_rbt, id)) 2036 { 2037 diag (pos, "builtin ID '%s' not found in bif file.\n", id); 2038 return PC_PARSEFAIL; 2039 } 2040 2041 /* Check for an optional overload id. Usually we use the builtin 2042 function id for that purpose, but sometimes we need multiple 2043 overload entries for the same builtin id, and it needs to be unique. */ 2044 consume_whitespace (); 2045 if (linebuf[pos] != '\n') 2046 { 2047 id = match_identifier (); 2048 ovlds[curr_ovld].ovld_id_name = id; 2049 consume_whitespace (); 2050 } 2051 2052 /* Save the overload ID in a lookup structure. */ 2053 if (!rbt_insert (&ovld_rbt, id)) 2054 { 2055 diag (oldpos, "duplicate overload ID '%s'.\n", id); 2056 return PC_PARSEFAIL; 2057 } 2058 2059 if (linebuf[pos] != '\n') 2060 { 2061 diag (pos, "garbage at end of line.\n"); 2062 return PC_PARSEFAIL; 2063 } 2064 return PC_OK; 2065} 2066 2067/* Parse one stanza of the input overload file. linebuf already contains the 2068 first line to parse. */ 2069static parse_codes 2070parse_ovld_stanza (void) 2071{ 2072 /* Parse the stanza header. */ 2073 pos = 0; 2074 consume_whitespace (); 2075 2076 if (linebuf[pos] != '[') 2077 { 2078 diag (pos, "ill-formed stanza header.\n"); 2079 return PC_PARSEFAIL; 2080 } 2081 safe_inc_pos (); 2082 2083 char *stanza_name = match_identifier (); 2084 if (!stanza_name) 2085 { 2086 diag (pos, "no identifier found in stanza header.\n"); 2087 return PC_PARSEFAIL; 2088 } 2089 2090 /* Add the identifier to a table and set the number to be recorded 2091 with subsequent overload entries. */ 2092 if (num_ovld_stanzas >= MAXOVLDSTANZAS) 2093 { 2094 diag (pos, "too many stanza headers.\n"); 2095 return PC_PARSEFAIL; 2096 } 2097 2098 curr_ovld_stanza = num_ovld_stanzas++; 2099 ovld_stanza *stanza = &ovld_stanzas[curr_ovld_stanza]; 2100 stanza->stanza_id = stanza_name; 2101 2102 consume_whitespace (); 2103 if (linebuf[pos] != ',') 2104 { 2105 diag (pos, "missing comma.\n"); 2106 return PC_PARSEFAIL; 2107 } 2108 safe_inc_pos (); 2109 2110 consume_whitespace (); 2111 stanza->extern_name = match_identifier (); 2112 if (!stanza->extern_name) 2113 { 2114 diag (pos, "missing external name.\n"); 2115 return PC_PARSEFAIL; 2116 } 2117 2118 consume_whitespace (); 2119 if (linebuf[pos] != ',') 2120 { 2121 diag (pos, "missing comma.\n"); 2122 return PC_PARSEFAIL; 2123 } 2124 safe_inc_pos (); 2125 2126 consume_whitespace (); 2127 stanza->intern_name = match_identifier (); 2128 if (!stanza->intern_name) 2129 { 2130 diag (pos, "missing internal name.\n"); 2131 return PC_PARSEFAIL; 2132 } 2133 2134 consume_whitespace (); 2135 if (linebuf[pos] == ',') 2136 { 2137 safe_inc_pos (); 2138 consume_whitespace (); 2139 stanza->ifdef = match_identifier (); 2140 if (!stanza->ifdef) 2141 { 2142 diag (pos, "missing ifdef token.\n"); 2143 return PC_PARSEFAIL; 2144 } 2145 consume_whitespace (); 2146 } 2147 else 2148 stanza->ifdef = 0; 2149 2150 if (linebuf[pos] != ']') 2151 { 2152 diag (pos, "ill-formed stanza header.\n"); 2153 return PC_PARSEFAIL; 2154 } 2155 safe_inc_pos (); 2156 2157 consume_whitespace (); 2158 if (linebuf[pos] != '\n' && pos != LINELEN - 1) 2159 { 2160 diag (pos, "garbage after stanza header.\n"); 2161 return PC_PARSEFAIL; 2162 } 2163 2164 parse_codes result = PC_OK; 2165 2166 while (result != PC_EOSTANZA) 2167 { 2168 if (!advance_line (ovld_file)) 2169 return PC_EOFILE; 2170 2171 result = parse_ovld_entry (); 2172 if (result == PC_EOFILE || result == PC_PARSEFAIL) 2173 return result; 2174 } 2175 2176 return PC_OK; 2177} 2178 2179/* Parse the overload file. */ 2180static parse_codes 2181parse_ovld (void) 2182{ 2183 parse_codes result = PC_OK; 2184 diag = &ovld_diag; 2185 2186 if (!advance_line (ovld_file)) 2187 return PC_OK; 2188 2189 while (result == PC_OK) 2190 result = parse_ovld_stanza (); 2191 2192 if (result == PC_EOFILE) 2193 return PC_OK; 2194 return result; 2195} 2196 2197/* Write a comment at the top of FILE about how the code was generated. */ 2198static void 2199write_autogenerated_header (FILE *file) 2200{ 2201 fprintf (file, "/* Automatically generated by the program '%s'\n", 2202 pgm_path); 2203 fprintf (file, " from the files '%s' and '%s'. */\n\n", 2204 bif_path, ovld_path); 2205} 2206 2207/* Write declarations into the header file. */ 2208static void 2209write_decls (void) 2210{ 2211 fprintf (header_file, "enum rs6000_gen_builtins\n{\n RS6000_BIF_NONE,\n"); 2212 for (int i = 0; i <= curr_bif; i++) 2213 fprintf (header_file, " RS6000_BIF_%s,\n", bifs[bif_order[i]].idname); 2214 fprintf (header_file, " RS6000_BIF_MAX,\n"); 2215 fprintf (header_file, " RS6000_OVLD_NONE,\n"); 2216 for (int i = 0; i < num_ovld_stanzas; i++) 2217 fprintf (header_file, " RS6000_OVLD_%s,\n", ovld_stanzas[i].stanza_id); 2218 fprintf (header_file, " RS6000_OVLD_MAX\n};\n\n"); 2219 2220 fprintf (header_file, 2221 "extern GTY(()) tree rs6000_builtin_decls[RS6000_OVLD_MAX];\n\n"); 2222 2223 fprintf (header_file, 2224 "enum rs6000_ovld_instances\n{\n RS6000_INST_NONE,\n"); 2225 for (int i = 0; i <= curr_ovld; i++) 2226 fprintf (header_file, " RS6000_INST_%s,\n", ovlds[i].ovld_id_name); 2227 fprintf (header_file, " RS6000_INST_MAX\n};\n\n"); 2228 2229 fprintf (header_file, "#define MAX_OVLD_ARGS %d\n", max_ovld_args); 2230 2231 fprintf (header_file, "enum restriction {\n"); 2232 fprintf (header_file, " RES_NONE,\n"); 2233 fprintf (header_file, " RES_BITS,\n"); 2234 fprintf (header_file, " RES_RANGE,\n"); 2235 fprintf (header_file, " RES_VAR_RANGE,\n"); 2236 fprintf (header_file, " RES_VALUES\n"); 2237 fprintf (header_file, "};\n\n"); 2238 2239 fprintf (header_file, "enum bif_enable {\n"); 2240 fprintf (header_file, " ENB_ALWAYS,\n"); 2241 fprintf (header_file, " ENB_P5,\n"); 2242 fprintf (header_file, " ENB_P6,\n"); 2243 fprintf (header_file, " ENB_P6_64,\n"); 2244 fprintf (header_file, " ENB_ALTIVEC,\n"); 2245 fprintf (header_file, " ENB_CELL,\n"); 2246 fprintf (header_file, " ENB_VSX,\n"); 2247 fprintf (header_file, " ENB_P7,\n"); 2248 fprintf (header_file, " ENB_P7_64,\n"); 2249 fprintf (header_file, " ENB_P8,\n"); 2250 fprintf (header_file, " ENB_P8V,\n"); 2251 fprintf (header_file, " ENB_P9,\n"); 2252 fprintf (header_file, " ENB_P9_64,\n"); 2253 fprintf (header_file, " ENB_P9V,\n"); 2254 fprintf (header_file, " ENB_IEEE128_HW,\n"); 2255 fprintf (header_file, " ENB_DFP,\n"); 2256 fprintf (header_file, " ENB_CRYPTO,\n"); 2257 fprintf (header_file, " ENB_HTM,\n"); 2258 fprintf (header_file, " ENB_P10,\n"); 2259 fprintf (header_file, " ENB_P10_64,\n"); 2260 fprintf (header_file, " ENB_MMA\n"); 2261 fprintf (header_file, "};\n\n"); 2262 2263 fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n"); 2264 fprintf (header_file, "struct GTY(()) bifdata\n"); 2265 fprintf (header_file, "{\n"); 2266 fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); 2267 fprintf (header_file, " bif_enable GTY((skip(\"\"))) enable;\n"); 2268 fprintf (header_file, " tree fntype;\n"); 2269 fprintf (header_file, " insn_code GTY((skip(\"\"))) icode;\n"); 2270 fprintf (header_file, " int nargs;\n"); 2271 fprintf (header_file, " int bifattrs;\n"); 2272 fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n"); 2273 fprintf (header_file, " restriction GTY((skip(\"\"))) restr[PPC_MAXRESTROPNDS];\n"); 2274 fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n"); 2275 fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n"); 2276 fprintf (header_file, " const char *GTY((skip(\"\"))) attr_string;\n"); 2277 fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) assoc_bif;\n"); 2278 fprintf (header_file, "};\n\n"); 2279 2280 fprintf (header_file, "#define bif_init_bit\t\t(0x00000001)\n"); 2281 fprintf (header_file, "#define bif_set_bit\t\t(0x00000002)\n"); 2282 fprintf (header_file, "#define bif_extract_bit\t\t(0x00000004)\n"); 2283 fprintf (header_file, "#define bif_nosoft_bit\t\t(0x00000008)\n"); 2284 fprintf (header_file, "#define bif_ldvec_bit\t\t(0x00000010)\n"); 2285 fprintf (header_file, "#define bif_stvec_bit\t\t(0x00000020)\n"); 2286 fprintf (header_file, "#define bif_reve_bit\t\t(0x00000040)\n"); 2287 fprintf (header_file, "#define bif_pred_bit\t\t(0x00000080)\n"); 2288 fprintf (header_file, "#define bif_htm_bit\t\t(0x00000100)\n"); 2289 fprintf (header_file, "#define bif_htmspr_bit\t\t(0x00000200)\n"); 2290 fprintf (header_file, "#define bif_htmcr_bit\t\t(0x00000400)\n"); 2291 fprintf (header_file, "#define bif_mma_bit\t\t(0x00000800)\n"); 2292 fprintf (header_file, "#define bif_quad_bit\t\t(0x00001000)\n"); 2293 fprintf (header_file, "#define bif_pair_bit\t\t(0x00002000)\n"); 2294 fprintf (header_file, "#define bif_mmaint_bit\t\t(0x00004000)\n"); 2295 fprintf (header_file, "#define bif_no32bit_bit\t\t(0x00008000)\n"); 2296 fprintf (header_file, "#define bif_32bit_bit\t\t(0x00010000)\n"); 2297 fprintf (header_file, "#define bif_cpu_bit\t\t(0x00020000)\n"); 2298 fprintf (header_file, "#define bif_ldstmask_bit\t(0x00040000)\n"); 2299 fprintf (header_file, "#define bif_lxvrse_bit\t\t(0x00080000)\n"); 2300 fprintf (header_file, "#define bif_lxvrze_bit\t\t(0x00100000)\n"); 2301 fprintf (header_file, "#define bif_endian_bit\t\t(0x00200000)\n"); 2302 fprintf (header_file, "#define bif_ibmld_bit\t\t(0x00400000)\n"); 2303 fprintf (header_file, "#define bif_ibm128_bit\t\t(0x00800000)\n"); 2304 fprintf (header_file, "\n"); 2305 fprintf (header_file, 2306 "#define bif_is_init(x)\t\t((x).bifattrs & bif_init_bit)\n"); 2307 fprintf (header_file, 2308 "#define bif_is_set(x)\t\t((x).bifattrs & bif_set_bit)\n"); 2309 fprintf (header_file, 2310 "#define bif_is_extract(x)\t((x).bifattrs & bif_extract_bit)\n"); 2311 fprintf (header_file, 2312 "#define bif_is_nosoft(x)\t((x).bifattrs & bif_nosoft_bit)\n"); 2313 fprintf (header_file, 2314 "#define bif_is_ldvec(x)\t\t((x).bifattrs & bif_ldvec_bit)\n"); 2315 fprintf (header_file, 2316 "#define bif_is_stvec(x)\t\t((x).bifattrs & bif_stvec_bit)\n"); 2317 fprintf (header_file, 2318 "#define bif_is_reve(x)\t\t((x).bifattrs & bif_reve_bit)\n"); 2319 fprintf (header_file, 2320 "#define bif_is_predicate(x)\t((x).bifattrs & bif_pred_bit)\n"); 2321 fprintf (header_file, 2322 "#define bif_is_htm(x)\t\t((x).bifattrs & bif_htm_bit)\n"); 2323 fprintf (header_file, 2324 "#define bif_is_htmspr(x)\t((x).bifattrs & bif_htmspr_bit)\n"); 2325 fprintf (header_file, 2326 "#define bif_is_htmcr(x)\t\t((x).bifattrs & bif_htmcr_bit)\n"); 2327 fprintf (header_file, 2328 "#define bif_is_mma(x)\t\t((x).bifattrs & bif_mma_bit)\n"); 2329 fprintf (header_file, 2330 "#define bif_is_quad(x)\t\t((x).bifattrs & bif_quad_bit)\n"); 2331 fprintf (header_file, 2332 "#define bif_is_pair(x)\t\t((x).bifattrs & bif_pair_bit)\n"); 2333 fprintf (header_file, 2334 "#define bif_is_mmaint(x)\t\t((x).bifattrs & bif_mmaint_bit)\n"); 2335 fprintf (header_file, 2336 "#define bif_is_no32bit(x)\t((x).bifattrs & bif_no32bit_bit)\n"); 2337 fprintf (header_file, 2338 "#define bif_is_32bit(x)\t((x).bifattrs & bif_32bit_bit)\n"); 2339 fprintf (header_file, 2340 "#define bif_is_cpu(x)\t\t((x).bifattrs & bif_cpu_bit)\n"); 2341 fprintf (header_file, 2342 "#define bif_is_ldstmask(x)\t((x).bifattrs & bif_ldstmask_bit)\n"); 2343 fprintf (header_file, 2344 "#define bif_is_lxvrse(x)\t((x).bifattrs & bif_lxvrse_bit)\n"); 2345 fprintf (header_file, 2346 "#define bif_is_lxvrze(x)\t((x).bifattrs & bif_lxvrze_bit)\n"); 2347 fprintf (header_file, 2348 "#define bif_is_endian(x)\t((x).bifattrs & bif_endian_bit)\n"); 2349 fprintf (header_file, 2350 "#define bif_is_ibmld(x)\t((x).bifattrs & bif_ibmld_bit)\n"); 2351 fprintf (header_file, 2352 "#define bif_is_ibm128(x)\t((x).bifattrs & bif_ibm128_bit)\n"); 2353 fprintf (header_file, "\n"); 2354 2355 fprintf (header_file, 2356 "extern GTY(()) bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n"); 2357 2358 fprintf (header_file, "struct GTY(()) ovlddata\n"); 2359 fprintf (header_file, "{\n"); 2360 fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); 2361 fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) bifid;\n"); 2362 fprintf (header_file, " tree fntype;\n"); 2363 fprintf (header_file, " ovlddata *GTY((skip(\"\"))) next;\n"); 2364 fprintf (header_file, "};\n\n"); 2365 2366 fprintf (header_file, "struct ovldrecord\n"); 2367 fprintf (header_file, "{\n"); 2368 fprintf (header_file, " const char *ovld_name;\n"); 2369 fprintf (header_file, " ovlddata *first_instance;\n"); 2370 fprintf (header_file, "};\n\n"); 2371 2372 fprintf (header_file, 2373 "extern GTY(()) ovlddata rs6000_instance_info[RS6000_INST_MAX];\n"); 2374 fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n"); 2375 2376 fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n"); 2377 fprintf (header_file, 2378 "extern bool rs6000_builtin_is_supported (rs6000_gen_builtins);\n"); 2379 fprintf (header_file, 2380 "extern tree rs6000_builtin_decl (unsigned, " 2381 "bool ATTRIBUTE_UNUSED);\n\n"); 2382} 2383 2384/* Comparator for bsearch on the type map. */ 2385int 2386typemap_cmp (const void *key, const void *entry) 2387{ 2388 return strcmp ((const char *)key, ((const typemap *)entry)->key); 2389} 2390 2391/* Write the type node corresponding to TOK. */ 2392static void 2393write_type_node (char *tok, bool indent) 2394{ 2395 if (indent) 2396 fprintf (init_file, " "); 2397 typemap *entry 2398 = (typemap *) bsearch (tok, type_map, 2399 sizeof type_map / sizeof type_map[0], 2400 sizeof (typemap), typemap_cmp); 2401 if (!entry) 2402 fatal ("Type map is inconsistent."); 2403 fprintf (init_file, "%s_type_node", entry->value); 2404} 2405 2406/* Write an initializer for a function type identified by STR. */ 2407void 2408write_fntype_init (char *str) 2409{ 2410 char *tok; 2411 2412 /* Check whether we have a "tf" token in this string, representing 2413 a float128_type_node. It's possible that float128_type_node is 2414 undefined (occurs for -maltivec -mno-vsx, for example), so we 2415 must guard against that. */ 2416 int tf_found = strstr (str, "tf") != NULL; 2417 2418 /* Similarly, look for decimal float tokens. */ 2419 int dfp_found = (strstr (str, "dd") != NULL 2420 || strstr (str, "td") != NULL 2421 || strstr (str, "sd") != NULL); 2422 2423 /* Avoid side effects of strtok on the original string by using a copy. */ 2424 char *buf = strdup (str); 2425 2426 if (tf_found || dfp_found) 2427 fprintf (init_file, " tree %s = NULL_TREE;\n", buf); 2428 else 2429 fprintf (init_file, " tree "); 2430 2431 if (tf_found) 2432 fprintf (init_file, " if (float128_type_node)\n "); 2433 else if (dfp_found) 2434 fprintf (init_file, " if (dfloat64_type_node)\n "); 2435 2436 fprintf (init_file, "%s\n = build_function_type_list (", buf); 2437 tok = strtok (buf, "_"); 2438 write_type_node (tok, tf_found || dfp_found); 2439 tok = strtok (0, "_"); 2440 assert (tok); 2441 assert (!strcmp (tok, "ftype")); 2442 2443 tok = strtok (0, "_"); 2444 if (tok) 2445 fprintf (init_file, ",\n\t\t\t\t"); 2446 2447 /* Note: A function with no arguments ends with '_ftype_v'. */ 2448 while (tok && strcmp (tok, "v")) 2449 { 2450 write_type_node (tok, tf_found || dfp_found); 2451 tok = strtok (0, "_"); 2452 fprintf (init_file, ",\n\t\t\t\t"); 2453 } 2454 fprintf (init_file, "NULL_TREE);\n"); 2455 free (buf); 2456} 2457 2458/* Write everything to the header file (rs6000-builtins.h). Return 2459 1 if successful, 0 otherwise. */ 2460static int 2461write_header_file (void) 2462{ 2463 write_autogenerated_header (header_file); 2464 2465 fprintf (header_file, "#ifndef _RS6000_BUILTINS_H\n"); 2466 fprintf (header_file, "#define _RS6000_BUILTINS_H 1\n\n"); 2467 2468 write_decls (); 2469 2470 fprintf (header_file, "\n"); 2471 fprintf (header_file, "\n#endif\n"); 2472 2473 return 1; 2474} 2475 2476/* Write the decl and initializer for rs6000_builtin_info[]. */ 2477static void 2478write_bif_static_init (void) 2479{ 2480 const char *res[3]; 2481 fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n"); 2482 fprintf (init_file, " {\n"); 2483 fprintf (init_file, " { /* RS6000_BIF_NONE: */\n"); 2484 fprintf (init_file, " \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n"); 2485 fprintf (init_file, " 0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n"); 2486 fprintf (init_file, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n"); 2487 fprintf (init_file, " },\n"); 2488 for (int i = 0; i <= curr_bif; i++) 2489 { 2490 bifdata *bifp = &bifs[bif_order[i]]; 2491 fprintf (init_file, " { /* RS6000_BIF_%s: */\n", bifp->idname); 2492 fprintf (init_file, " /* bifname */\t\"%s\",\n", 2493 bifp->proto.bifname); 2494 fprintf (init_file, " /* enable*/\t%s,\n", 2495 enable_string[bifp->stanza]); 2496 /* Type must be instantiated at run time. */ 2497 fprintf (init_file, " /* fntype */\t0,\n"); 2498 fprintf (init_file, " /* icode */\tCODE_FOR_%s,\n", 2499 bifp->patname); 2500 fprintf (init_file, " /* nargs */\t%d,\n", 2501 bifp->proto.nargs); 2502 fprintf (init_file, " /* bifattrs */\t0"); 2503 if (bifp->attrs.isinit) 2504 fprintf (init_file, " | bif_init_bit"); 2505 if (bifp->attrs.isset) 2506 fprintf (init_file, " | bif_set_bit"); 2507 if (bifp->attrs.isextract) 2508 fprintf (init_file, " | bif_extract_bit"); 2509 if (bifp->attrs.isnosoft) 2510 fprintf (init_file, " | bif_nosoft_bit"); 2511 if (bifp->attrs.isldvec) 2512 fprintf (init_file, " | bif_ldvec_bit"); 2513 if (bifp->attrs.isstvec) 2514 fprintf (init_file, " | bif_stvec_bit"); 2515 if (bifp->attrs.isreve) 2516 fprintf (init_file, " | bif_reve_bit"); 2517 if (bifp->attrs.ispred) 2518 fprintf (init_file, " | bif_pred_bit"); 2519 if (bifp->attrs.ishtm) 2520 fprintf (init_file, " | bif_htm_bit"); 2521 if (bifp->attrs.ishtmspr) 2522 fprintf (init_file, " | bif_htmspr_bit"); 2523 if (bifp->attrs.ishtmcr) 2524 fprintf (init_file, " | bif_htmcr_bit"); 2525 if (bifp->attrs.ismma) 2526 fprintf (init_file, " | bif_mma_bit"); 2527 if (bifp->attrs.isquad) 2528 fprintf (init_file, " | bif_quad_bit"); 2529 if (bifp->attrs.ispair) 2530 fprintf (init_file, " | bif_pair_bit"); 2531 if (bifp->attrs.ismmaint) 2532 fprintf (init_file, " | bif_mmaint_bit"); 2533 if (bifp->attrs.isno32bit) 2534 fprintf (init_file, " | bif_no32bit_bit"); 2535 if (bifp->attrs.is32bit) 2536 fprintf (init_file, " | bif_32bit_bit"); 2537 if (bifp->attrs.iscpu) 2538 fprintf (init_file, " | bif_cpu_bit"); 2539 if (bifp->attrs.isldstmask) 2540 fprintf (init_file, " | bif_ldstmask_bit"); 2541 if (bifp->attrs.islxvrse) 2542 fprintf (init_file, " | bif_lxvrse_bit"); 2543 if (bifp->attrs.islxvrze) 2544 fprintf (init_file, " | bif_lxvrze_bit"); 2545 if (bifp->attrs.isendian) 2546 fprintf (init_file, " | bif_endian_bit"); 2547 if (bifp->attrs.isibmld) 2548 fprintf (init_file, " | bif_ibmld_bit"); 2549 if (bifp->attrs.isibm128) 2550 fprintf (init_file, " | bif_ibm128_bit"); 2551 fprintf (init_file, ",\n"); 2552 fprintf (init_file, " /* restr_opnd */\t{%d, %d, %d},\n", 2553 bifp->proto.restr_opnd[0], bifp->proto.restr_opnd[1], 2554 bifp->proto.restr_opnd[2]); 2555 for (int j = 0; j < 3; j++) 2556 if (!bifp->proto.restr_opnd[j]) 2557 res[j] = "RES_NONE"; 2558 else if (bifp->proto.restr[j] == RES_BITS) 2559 res[j] = "RES_BITS"; 2560 else if (bifp->proto.restr[j] == RES_RANGE) 2561 res[j] = "RES_RANGE"; 2562 else if (bifp->proto.restr[j] == RES_VALUES) 2563 res[j] = "RES_VALUES"; 2564 else if (bifp->proto.restr[j] == RES_VAR_RANGE) 2565 res[j] = "RES_VAR_RANGE"; 2566 else 2567 res[j] = "ERROR"; 2568 fprintf (init_file, " /* restr */\t{%s, %s, %s},\n", 2569 res[0], res[1], res[2]); 2570 fprintf (init_file, " /* restr_val1 */\t{%s, %s, %s},\n", 2571 bifp->proto.restr_val1[0] ? bifp->proto.restr_val1[0] : "0", 2572 bifp->proto.restr_val1[1] ? bifp->proto.restr_val1[1] : "0", 2573 bifp->proto.restr_val1[2] ? bifp->proto.restr_val1[2] : "0"); 2574 fprintf (init_file, " /* restr_val2 */\t{%s, %s, %s},\n", 2575 bifp->proto.restr_val2[0] ? bifp->proto.restr_val2[0] : "0", 2576 bifp->proto.restr_val2[1] ? bifp->proto.restr_val2[1] : "0", 2577 bifp->proto.restr_val2[2] ? bifp->proto.restr_val2[2] : "0"); 2578 fprintf (init_file, " /* attr_string */\t\"%s\",\n", 2579 (bifp->kind == FNK_CONST ? "= const" 2580 : (bifp->kind == FNK_PURE ? "= pure" 2581 : (bifp->kind == FNK_FPMATH ? "= fp, const" 2582 : "")))); 2583 fprintf (init_file, " /* assoc_bif */\tRS6000_BIF_%s%s\n", 2584 bifp->attrs.ismmaint ? bifp->idname : "NONE", 2585 bifp->attrs.ismmaint ? "_INTERNAL" : ""); 2586 fprintf (init_file, " },\n"); 2587 } 2588 fprintf (init_file, " };\n\n"); 2589} 2590 2591/* Write the decls and initializers for rs6000_overload_info[] and 2592 rs6000_instance_info[]. */ 2593static void 2594write_ovld_static_init (void) 2595{ 2596 fprintf (init_file, 2597 "ovldrecord rs6000_overload_info[RS6000_OVLD_MAX " 2598 "- RS6000_OVLD_NONE] =\n"); 2599 fprintf (init_file, " {\n"); 2600 fprintf (init_file, " { /* RS6000_OVLD_NONE: */\n"); 2601 fprintf (init_file, " \"\", NULL\n"); 2602 fprintf (init_file, " },\n"); 2603 for (int i = 0; i <= curr_ovld_stanza; i++) 2604 { 2605 fprintf (init_file, " { /* RS6000_OVLD_%s: */\n", 2606 ovld_stanzas[i].stanza_id); 2607 fprintf (init_file, " /* ovld_name */\t\"%s\",\n", 2608 ovld_stanzas[i].intern_name); 2609 /* First-instance must currently be instantiated at run time. */ 2610 fprintf (init_file, " /* first_instance */\tNULL\n"); 2611 fprintf (init_file, " },\n"); 2612 } 2613 fprintf (init_file, " };\n\n"); 2614 2615 fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n"); 2616 fprintf (init_file, " {\n"); 2617 fprintf (init_file, " { /* RS6000_INST_NONE: */\n"); 2618 fprintf (init_file, " \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n"); 2619 fprintf (init_file, " },\n"); 2620 for (int i = 0; i <= curr_ovld; i++) 2621 { 2622 fprintf (init_file, " { /* RS6000_INST_%s: */\n", 2623 ovlds[i].ovld_id_name); 2624 fprintf (init_file, " /* bifname */\t\"%s\",\n", 2625 ovlds[i].proto.bifname); 2626 fprintf (init_file, " /* bifid */\tRS6000_BIF_%s,\n", 2627 ovlds[i].bif_id_name); 2628 /* Type must be instantiated at run time. */ 2629 fprintf (init_file, " /* fntype */\t0,\n"); 2630 fprintf (init_file, " /* next */\t"); 2631 if (i < curr_ovld 2632 && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname)) 2633 fprintf (init_file, 2634 "&rs6000_instance_info[RS6000_INST_%s]\n", 2635 ovlds[i+1].ovld_id_name); 2636 else 2637 fprintf (init_file, "NULL\n"); 2638 fprintf (init_file, " },\n"); 2639 } 2640 fprintf (init_file, " };\n\n"); 2641} 2642 2643/* Write code to initialize the built-in function table. */ 2644static void 2645write_init_bif_table (void) 2646{ 2647 for (int i = 0; i <= curr_bif; i++) 2648 { 2649 fprintf (init_file, 2650 " rs6000_builtin_info[RS6000_BIF_%s].fntype" 2651 "\n = %s;\n", 2652 bifs[i].idname, bifs[i].fndecl); 2653 2654 /* Check whether we have a "tf" token in this string, representing 2655 a float128_type_node. It's possible that float128_type_node is 2656 undefined (occurs for -maltivec -mno-vsx, for example), so we 2657 must guard against that. */ 2658 int tf_found = strstr (bifs[i].fndecl, "tf") != NULL; 2659 2660 /* Similarly, look for decimal float tokens. */ 2661 int dfp_found = (strstr (bifs[i].fndecl, "sd") != NULL 2662 || strstr (bifs[i].fndecl, "dd") != NULL 2663 || strstr (bifs[i].fndecl, "td") != NULL); 2664 2665 if (tf_found) 2666 { 2667 fprintf (init_file, " if (float128_type_node)\n"); 2668 fprintf (init_file, " {\n"); 2669 } 2670 else if (dfp_found) 2671 { 2672 fprintf (init_file, " if (dfloat64_type_node)\n"); 2673 fprintf (init_file, " {\n"); 2674 } 2675 2676 fprintf (init_file, 2677 " rs6000_builtin_decls[(int)RS6000_BIF_%s] = t\n", 2678 bifs[i].idname); 2679 fprintf (init_file, 2680 " = add_builtin_function (\"%s\",\n", 2681 bifs[i].proto.bifname); 2682 fprintf (init_file, 2683 " %s,\n", 2684 bifs[i].fndecl); 2685 fprintf (init_file, 2686 " (int)RS6000_BIF_%s," 2687 " BUILT_IN_MD,\n", 2688 bifs[i].idname); 2689 fprintf (init_file, 2690 " NULL, NULL_TREE);\n"); 2691 if (bifs[i].kind == FNK_CONST) 2692 { 2693 fprintf (init_file, " TREE_READONLY (t) = 1;\n"); 2694 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n"); 2695 } 2696 else if (bifs[i].kind == FNK_PURE) 2697 { 2698 fprintf (init_file, " DECL_PURE_P (t) = 1;\n"); 2699 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n"); 2700 } 2701 else if (bifs[i].kind == FNK_FPMATH) 2702 { 2703 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n"); 2704 fprintf (init_file, " if (flag_rounding_math)\n"); 2705 fprintf (init_file, " {\n"); 2706 fprintf (init_file, " DECL_PURE_P (t) = 1;\n"); 2707 fprintf (init_file, " DECL_IS_NOVOPS (t) = 1;\n"); 2708 fprintf (init_file, " }\n"); 2709 fprintf (init_file, " else\n"); 2710 fprintf (init_file, " TREE_READONLY (t) = 1;\n"); 2711 } 2712 2713 if (tf_found || dfp_found) 2714 { 2715 fprintf (init_file, " }\n"); 2716 fprintf (init_file, " else\n"); 2717 fprintf (init_file, " {\n"); 2718 fprintf (init_file, " rs6000_builtin_decls" 2719 "[(int)RS6000_BIF_%s] = NULL_TREE;\n", bifs[i].idname); 2720 fprintf (init_file, " }\n"); 2721 } 2722 fprintf (init_file, "\n"); 2723 } 2724} 2725 2726/* Write code to initialize the overload table. */ 2727static void 2728write_init_ovld_table (void) 2729{ 2730 fprintf (init_file, " int base = RS6000_OVLD_NONE;\n\n"); 2731 fprintf (init_file, 2732 " /* The fndecl for an overload is arbitrarily the first one\n" 2733 " for the overload. We sort out the real types when\n" 2734 " processing the overload in the gcc front end. */\n"); 2735 2736 for (int i = 0; i <= curr_ovld; i++) 2737 { 2738 fprintf (init_file, 2739 " rs6000_instance_info[RS6000_INST_%s].fntype" 2740 "\n = %s;\n", 2741 ovlds[i].ovld_id_name, ovlds[i].fndecl); 2742 2743 if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza) 2744 { 2745 ovld_stanza *stanza = &ovld_stanzas[ovlds[i].stanza]; 2746 fprintf (init_file, "\n"); 2747 2748 /* Check whether we have a "tf" token in this string, representing 2749 a float128_type_node. It's possible that float128_type_node is 2750 undefined (occurs for -maltivec -mno-vsx, for example), so we 2751 must guard against that. */ 2752 int tf_found = strstr (ovlds[i].fndecl, "tf") != NULL; 2753 2754 /* Similarly, look for decimal float tokens. */ 2755 int dfp_found = (strstr (ovlds[i].fndecl, "sd") != NULL 2756 || strstr (ovlds[i].fndecl, "dd") != NULL 2757 || strstr (ovlds[i].fndecl, "td") != NULL); 2758 2759 if (tf_found) 2760 { 2761 fprintf (init_file, " if (float128_type_node)\n"); 2762 fprintf (init_file, " {\n"); 2763 } 2764 else if (dfp_found) 2765 { 2766 fprintf (init_file, " if (dfloat64_type_node)\n"); 2767 fprintf (init_file, " {\n"); 2768 } 2769 2770 fprintf (init_file, 2771 " rs6000_builtin_decls[(int)RS6000_OVLD_%s] = t\n", 2772 stanza->stanza_id); 2773 fprintf (init_file, 2774 " = add_builtin_function (\"%s\",\n", 2775 stanza->intern_name); 2776 fprintf (init_file, 2777 " %s,\n", 2778 ovlds[i].fndecl); 2779 fprintf (init_file, 2780 " (int)RS6000_OVLD_%s," 2781 " BUILT_IN_MD,\n", 2782 stanza->stanza_id); 2783 fprintf (init_file, 2784 " NULL, NULL_TREE);\n"); 2785 2786 if (tf_found || dfp_found) 2787 fprintf (init_file, " }\n"); 2788 2789 fprintf (init_file, "\n"); 2790 2791 fprintf (init_file, 2792 " rs6000_overload_info[RS6000_OVLD_%s - base]" 2793 ".first_instance\n", 2794 stanza->stanza_id); 2795 fprintf (init_file, 2796 " = &rs6000_instance_info[RS6000_INST_%s];\n\n", 2797 ovlds[i].ovld_id_name); 2798 } 2799 } 2800} 2801 2802/* Write everything to the initialization file (rs6000-builtins.cc). 2803 Return 1 if successful, 0 otherwise. */ 2804static int 2805write_init_file (void) 2806{ 2807 write_autogenerated_header (init_file); 2808 2809 fprintf (init_file, "#include \"config.h\"\n"); 2810 fprintf (init_file, "#include \"system.h\"\n"); 2811 fprintf (init_file, "#include \"coretypes.h\"\n"); 2812 fprintf (init_file, "#include \"backend.h\"\n"); 2813 fprintf (init_file, "#include \"rtl.h\"\n"); 2814 fprintf (init_file, "#include \"tree.h\"\n"); 2815 fprintf (init_file, "#include \"langhooks.h\"\n"); 2816 fprintf (init_file, "#include \"insn-codes.h\"\n"); 2817 fprintf (init_file, "#include \"rs6000-builtins.h\"\n"); 2818 fprintf (init_file, "\n"); 2819 2820 fprintf (init_file, "tree rs6000_builtin_decls[RS6000_OVLD_MAX];\n\n"); 2821 2822 write_bif_static_init (); 2823 write_ovld_static_init (); 2824 2825 fprintf (init_file, "void\n"); 2826 fprintf (init_file, "rs6000_init_generated_builtins ()\n"); 2827 fprintf (init_file, "{\n"); 2828 fprintf (init_file, " tree t;\n"); 2829 rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init); 2830 fprintf (init_file, "\n"); 2831 2832 fprintf (init_file, 2833 " rs6000_builtin_decls[RS6000_BIF_NONE] = NULL_TREE;\n"); 2834 fprintf (init_file, 2835 " rs6000_builtin_decls[RS6000_BIF_MAX] = NULL_TREE;\n"); 2836 fprintf (init_file, 2837 " rs6000_builtin_decls[RS6000_OVLD_NONE] = NULL_TREE;\n\n"); 2838 2839 write_init_bif_table (); 2840 write_init_ovld_table (); 2841 2842 fprintf (init_file, "}\n\n"); 2843 2844 return 1; 2845} 2846 2847/* Write everything to the include file (rs6000-vecdefines.h). 2848 Return 1 if successful, 0 otherwise. */ 2849static int 2850write_defines_file (void) 2851{ 2852 fprintf (defines_file, "#ifndef _RS6000_VECDEFINES_H\n"); 2853 fprintf (defines_file, "#define _RS6000_VECDEFINES_H 1\n\n"); 2854 fprintf (defines_file, "#if defined(_ARCH_PPC64) && defined (_ARCH_PWR9)\n"); 2855 fprintf (defines_file, " #define _ARCH_PPC64_PWR9 1\n"); 2856 fprintf (defines_file, "#endif\n\n"); 2857 for (int i = 0; i < num_ovld_stanzas; i++) 2858 if (strcmp (ovld_stanzas[i].extern_name, "SKIP")) 2859 { 2860 if (ovld_stanzas[i].ifdef) 2861 fprintf (defines_file, "#ifdef %s\n", ovld_stanzas[i].ifdef); 2862 fprintf (defines_file, "#define %s %s\n", 2863 ovld_stanzas[i].extern_name, 2864 ovld_stanzas[i].intern_name); 2865 if (ovld_stanzas[i].ifdef) 2866 fprintf (defines_file, "#endif\n"); 2867 } 2868 fprintf (defines_file, "\n#endif\n"); 2869 return 1; 2870} 2871 2872/* Close and delete output files after any failure, so that subsequent 2873 build dependencies will fail. */ 2874static void 2875delete_output_files (void) 2876{ 2877 /* Depending on whence we're called, some of these may already be 2878 closed. Don't check for errors. */ 2879 fclose (header_file); 2880 fclose (init_file); 2881 fclose (defines_file); 2882 2883 remove (header_path); 2884 remove (init_path); 2885 remove (defines_path); 2886} 2887 2888/* Main program to convert flat files into built-in initialization code. */ 2889int 2890main (int argc, const char **argv) 2891{ 2892 if (argc != 6) 2893 { 2894 fprintf (stderr, 2895 "Five arguments required: two input files and three output " 2896 "files.\n"); 2897 exit (1); 2898 } 2899 2900 pgm_path = argv[0]; 2901 bif_path = argv[1]; 2902 ovld_path = argv[2]; 2903 header_path = argv[3]; 2904 init_path = argv[4]; 2905 defines_path = argv[5]; 2906 2907 bif_file = fopen (bif_path, "r"); 2908 if (!bif_file) 2909 { 2910 fprintf (stderr, "Cannot open input built-in file '%s'.\n", bif_path); 2911 exit (1); 2912 } 2913 ovld_file = fopen (ovld_path, "r"); 2914 if (!ovld_file) 2915 { 2916 fprintf (stderr, "Cannot open input overload file '%s'.\n", ovld_path); 2917 exit (1); 2918 } 2919 header_file = fopen (header_path, "w"); 2920 if (!header_file) 2921 { 2922 fprintf (stderr, "Cannot open header file '%s' for output.\n", 2923 header_path); 2924 exit (1); 2925 } 2926 init_file = fopen (init_path, "w"); 2927 if (!init_file) 2928 { 2929 fprintf (stderr, "Cannot open init file '%s' for output.\n", init_path); 2930 exit (1); 2931 } 2932 defines_file = fopen (defines_path, "w"); 2933 if (!defines_file) 2934 { 2935 fprintf (stderr, "Cannot open defines file '%s' for output.\n", 2936 defines_path); 2937 exit (1); 2938 } 2939 2940 /* Allocate some buffers. */ 2941 for (int i = 0; i < MAXLINES; i++) 2942 lines[i] = (char *) malloc (LINELEN); 2943 2944 /* Initialize the balanced trees containing built-in function ids, 2945 overload function ids, and function type declaration ids. */ 2946 rbt_new (&bif_rbt); 2947 rbt_new (&ovld_rbt); 2948 rbt_new (&fntype_rbt); 2949 2950 /* Initialize another balanced tree that contains a map from built-in 2951 function ids to the order in which they were encountered. */ 2952 rbt_new (&bifo_rbt); 2953 2954 /* Parse the built-in function file. */ 2955 num_bifs = 0; 2956 line = 0; 2957 if (parse_bif () == PC_PARSEFAIL) 2958 { 2959 fprintf (stderr, "Parsing of '%s' failed, aborting.\n", bif_path); 2960 delete_output_files (); 2961 exit (1); 2962 } 2963 fclose (bif_file); 2964 2965 /* Create a mapping from function IDs in their final order to 2966 the order they appear in the built-in function file. */ 2967 create_bif_order (); 2968 2969#ifdef DEBUG 2970 fprintf (stderr, "\nFunction ID list:\n"); 2971 rbt_dump (&bif_rbt, bif_rbt.rbt_root); 2972 fprintf (stderr, "\n"); 2973#endif 2974 2975 /* Parse the overload file. */ 2976 num_ovld_stanzas = 0; 2977 num_ovlds = 0; 2978 line = 0; 2979 if (parse_ovld () == PC_PARSEFAIL) 2980 { 2981 fprintf (stderr, "Parsing of '%s' failed, aborting.\n", ovld_path); 2982 delete_output_files (); 2983 exit (1); 2984 } 2985 fclose (ovld_file); 2986 2987#ifdef DEBUG 2988 fprintf (stderr, "\nFunction type decl list:\n"); 2989 rbt_dump (&fntype_rbt, fntype_rbt.rbt_root); 2990 fprintf (stderr, "\n"); 2991#endif 2992 2993 /* Write the header file and the file containing initialization code. */ 2994 if (!write_header_file ()) 2995 { 2996 fprintf (stderr, "Output to '%s' failed, aborting.\n", header_path); 2997 delete_output_files (); 2998 exit (1); 2999 } 3000 if (!write_init_file ()) 3001 { 3002 fprintf (stderr, "Output to '%s' failed, aborting.\n", init_path); 3003 delete_output_files (); 3004 exit (1); 3005 } 3006 3007 /* Write the defines file to be included into altivec.h. */ 3008 if (!write_defines_file ()) 3009 { 3010 fprintf (stderr, "Output to '%s' failed, aborting.\n", defines_path); 3011 delete_output_files (); 3012 exit (1); 3013 } 3014 3015 /* Always close init_file last. This avoids race conditions in the 3016 build machinery. See comments in t-rs6000. */ 3017 fclose (header_file); 3018 fclose (defines_file); 3019 fclose (init_file); 3020 3021 return 0; 3022} 3023