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