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