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