]> gcc.gnu.org Git - gcc.git/blob - gcc/config/rs6000/rs6000-gen-builtins.cc
Revert patches
[gcc.git] / gcc / config / rs6000 / rs6000-gen-builtins.cc
1 /* Generate built-in function initialization and recognition for Power.
2 Copyright (C) 2020-2023 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
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)))
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)))
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
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
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
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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. */
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
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
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
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
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
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
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 GTY(()) bifdata\n");
2265 fprintf (header_file, "{\n");
2266 fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n");
2267 fprintf (header_file, " bif_enable GTY((skip(\"\"))) enable;\n");
2268 fprintf (header_file, " tree fntype;\n");
2269 fprintf (header_file, " insn_code GTY((skip(\"\"))) icode;\n");
2270 fprintf (header_file, " int nargs;\n");
2271 fprintf (header_file, " int bifattrs;\n");
2272 fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n");
2273 fprintf (header_file, " restriction GTY((skip(\"\"))) restr[PPC_MAXRESTROPNDS];\n");
2274 fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n");
2275 fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n");
2276 fprintf (header_file, " const char *GTY((skip(\"\"))) attr_string;\n");
2277 fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) assoc_bif;\n");
2278 fprintf (header_file, "};\n\n");
2279
2280 fprintf (header_file, "#define bif_init_bit\t\t(0x00000001)\n");
2281 fprintf (header_file, "#define bif_set_bit\t\t(0x00000002)\n");
2282 fprintf (header_file, "#define bif_extract_bit\t\t(0x00000004)\n");
2283 fprintf (header_file, "#define bif_nosoft_bit\t\t(0x00000008)\n");
2284 fprintf (header_file, "#define bif_ldvec_bit\t\t(0x00000010)\n");
2285 fprintf (header_file, "#define bif_stvec_bit\t\t(0x00000020)\n");
2286 fprintf (header_file, "#define bif_reve_bit\t\t(0x00000040)\n");
2287 fprintf (header_file, "#define bif_pred_bit\t\t(0x00000080)\n");
2288 fprintf (header_file, "#define bif_htm_bit\t\t(0x00000100)\n");
2289 fprintf (header_file, "#define bif_htmspr_bit\t\t(0x00000200)\n");
2290 fprintf (header_file, "#define bif_htmcr_bit\t\t(0x00000400)\n");
2291 fprintf (header_file, "#define bif_mma_bit\t\t(0x00000800)\n");
2292 fprintf (header_file, "#define bif_quad_bit\t\t(0x00001000)\n");
2293 fprintf (header_file, "#define bif_pair_bit\t\t(0x00002000)\n");
2294 fprintf (header_file, "#define bif_mmaint_bit\t\t(0x00004000)\n");
2295 fprintf (header_file, "#define bif_no32bit_bit\t\t(0x00008000)\n");
2296 fprintf (header_file, "#define bif_32bit_bit\t\t(0x00010000)\n");
2297 fprintf (header_file, "#define bif_cpu_bit\t\t(0x00020000)\n");
2298 fprintf (header_file, "#define bif_ldstmask_bit\t(0x00040000)\n");
2299 fprintf (header_file, "#define bif_lxvrse_bit\t\t(0x00080000)\n");
2300 fprintf (header_file, "#define bif_lxvrze_bit\t\t(0x00100000)\n");
2301 fprintf (header_file, "#define bif_endian_bit\t\t(0x00200000)\n");
2302 fprintf (header_file, "#define bif_ibmld_bit\t\t(0x00400000)\n");
2303 fprintf (header_file, "#define bif_ibm128_bit\t\t(0x00800000)\n");
2304 fprintf (header_file, "\n");
2305 fprintf (header_file,
2306 "#define bif_is_init(x)\t\t((x).bifattrs & bif_init_bit)\n");
2307 fprintf (header_file,
2308 "#define bif_is_set(x)\t\t((x).bifattrs & bif_set_bit)\n");
2309 fprintf (header_file,
2310 "#define bif_is_extract(x)\t((x).bifattrs & bif_extract_bit)\n");
2311 fprintf (header_file,
2312 "#define bif_is_nosoft(x)\t((x).bifattrs & bif_nosoft_bit)\n");
2313 fprintf (header_file,
2314 "#define bif_is_ldvec(x)\t\t((x).bifattrs & bif_ldvec_bit)\n");
2315 fprintf (header_file,
2316 "#define bif_is_stvec(x)\t\t((x).bifattrs & bif_stvec_bit)\n");
2317 fprintf (header_file,
2318 "#define bif_is_reve(x)\t\t((x).bifattrs & bif_reve_bit)\n");
2319 fprintf (header_file,
2320 "#define bif_is_predicate(x)\t((x).bifattrs & bif_pred_bit)\n");
2321 fprintf (header_file,
2322 "#define bif_is_htm(x)\t\t((x).bifattrs & bif_htm_bit)\n");
2323 fprintf (header_file,
2324 "#define bif_is_htmspr(x)\t((x).bifattrs & bif_htmspr_bit)\n");
2325 fprintf (header_file,
2326 "#define bif_is_htmcr(x)\t\t((x).bifattrs & bif_htmcr_bit)\n");
2327 fprintf (header_file,
2328 "#define bif_is_mma(x)\t\t((x).bifattrs & bif_mma_bit)\n");
2329 fprintf (header_file,
2330 "#define bif_is_quad(x)\t\t((x).bifattrs & bif_quad_bit)\n");
2331 fprintf (header_file,
2332 "#define bif_is_pair(x)\t\t((x).bifattrs & bif_pair_bit)\n");
2333 fprintf (header_file,
2334 "#define bif_is_mmaint(x)\t\t((x).bifattrs & bif_mmaint_bit)\n");
2335 fprintf (header_file,
2336 "#define bif_is_no32bit(x)\t((x).bifattrs & bif_no32bit_bit)\n");
2337 fprintf (header_file,
2338 "#define bif_is_32bit(x)\t((x).bifattrs & bif_32bit_bit)\n");
2339 fprintf (header_file,
2340 "#define bif_is_cpu(x)\t\t((x).bifattrs & bif_cpu_bit)\n");
2341 fprintf (header_file,
2342 "#define bif_is_ldstmask(x)\t((x).bifattrs & bif_ldstmask_bit)\n");
2343 fprintf (header_file,
2344 "#define bif_is_lxvrse(x)\t((x).bifattrs & bif_lxvrse_bit)\n");
2345 fprintf (header_file,
2346 "#define bif_is_lxvrze(x)\t((x).bifattrs & bif_lxvrze_bit)\n");
2347 fprintf (header_file,
2348 "#define bif_is_endian(x)\t((x).bifattrs & bif_endian_bit)\n");
2349 fprintf (header_file,
2350 "#define bif_is_ibmld(x)\t((x).bifattrs & bif_ibmld_bit)\n");
2351 fprintf (header_file,
2352 "#define bif_is_ibm128(x)\t((x).bifattrs & bif_ibm128_bit)\n");
2353 fprintf (header_file, "\n");
2354
2355 fprintf (header_file,
2356 "extern GTY(()) bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n");
2357
2358 fprintf (header_file, "struct GTY(()) ovlddata\n");
2359 fprintf (header_file, "{\n");
2360 fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n");
2361 fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) bifid;\n");
2362 fprintf (header_file, " tree fntype;\n");
2363 fprintf (header_file, " ovlddata *GTY((skip(\"\"))) next;\n");
2364 fprintf (header_file, "};\n\n");
2365
2366 fprintf (header_file, "struct ovldrecord\n");
2367 fprintf (header_file, "{\n");
2368 fprintf (header_file, " const char *ovld_name;\n");
2369 fprintf (header_file, " ovlddata *first_instance;\n");
2370 fprintf (header_file, "};\n\n");
2371
2372 fprintf (header_file,
2373 "extern GTY(()) ovlddata rs6000_instance_info[RS6000_INST_MAX];\n");
2374 fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n");
2375
2376 fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n");
2377 fprintf (header_file,
2378 "extern bool rs6000_builtin_is_supported (rs6000_gen_builtins);\n");
2379 fprintf (header_file,
2380 "extern tree rs6000_builtin_decl (unsigned, "
2381 "bool ATTRIBUTE_UNUSED);\n\n");
2382 }
2383
2384 /* Comparator for bsearch on the type map. */
2385 int
2386 typemap_cmp (const void *key, const void *entry)
2387 {
2388 return strcmp ((const char *)key, ((const typemap *)entry)->key);
2389 }
2390
2391 /* Write the type node corresponding to TOK. */
2392 static void
2393 write_type_node (char *tok, bool indent)
2394 {
2395 if (indent)
2396 fprintf (init_file, " ");
2397 typemap *entry
2398 = (typemap *) bsearch (tok, type_map,
2399 sizeof type_map / sizeof type_map[0],
2400 sizeof (typemap), typemap_cmp);
2401 if (!entry)
2402 fatal ("Type map is inconsistent.");
2403 fprintf (init_file, "%s_type_node", entry->value);
2404 }
2405
2406 /* Write an initializer for a function type identified by STR. */
2407 void
2408 write_fntype_init (char *str)
2409 {
2410 char *tok;
2411
2412 /* Check whether we have a "tf" token in this string, representing
2413 a float128_type_node. It's possible that float128_type_node is
2414 undefined (occurs for -maltivec -mno-vsx, for example), so we
2415 must guard against that. */
2416 int tf_found = strstr (str, "tf") != NULL;
2417
2418 /* Similarly, look for decimal float tokens. */
2419 int dfp_found = (strstr (str, "dd") != NULL
2420 || strstr (str, "td") != NULL
2421 || strstr (str, "sd") != NULL);
2422
2423 /* Avoid side effects of strtok on the original string by using a copy. */
2424 char *buf = strdup (str);
2425
2426 if (tf_found || dfp_found)
2427 fprintf (init_file, " tree %s = NULL_TREE;\n", buf);
2428 else
2429 fprintf (init_file, " tree ");
2430
2431 if (tf_found)
2432 fprintf (init_file, " if (float128_type_node)\n ");
2433 else if (dfp_found)
2434 fprintf (init_file, " if (dfloat64_type_node)\n ");
2435
2436 fprintf (init_file, "%s\n = build_function_type_list (", buf);
2437 tok = strtok (buf, "_");
2438 write_type_node (tok, tf_found || dfp_found);
2439 tok = strtok (0, "_");
2440 assert (tok);
2441 assert (!strcmp (tok, "ftype"));
2442
2443 tok = strtok (0, "_");
2444 if (tok)
2445 fprintf (init_file, ",\n\t\t\t\t");
2446
2447 /* Note: A function with no arguments ends with '_ftype_v'. */
2448 while (tok && strcmp (tok, "v"))
2449 {
2450 write_type_node (tok, tf_found || dfp_found);
2451 tok = strtok (0, "_");
2452 fprintf (init_file, ",\n\t\t\t\t");
2453 }
2454 fprintf (init_file, "NULL_TREE);\n");
2455 free (buf);
2456 }
2457
2458 /* Write everything to the header file (rs6000-builtins.h). Return
2459 1 if successful, 0 otherwise. */
2460 static int
2461 write_header_file (void)
2462 {
2463 write_autogenerated_header (header_file);
2464
2465 fprintf (header_file, "#ifndef _RS6000_BUILTINS_H\n");
2466 fprintf (header_file, "#define _RS6000_BUILTINS_H 1\n\n");
2467
2468 write_decls ();
2469
2470 fprintf (header_file, "\n");
2471 fprintf (header_file, "\n#endif\n");
2472
2473 return 1;
2474 }
2475
2476 /* Write the decl and initializer for rs6000_builtin_info[]. */
2477 static void
2478 write_bif_static_init (void)
2479 {
2480 const char *res[3];
2481 fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n");
2482 fprintf (init_file, " {\n");
2483 fprintf (init_file, " { /* RS6000_BIF_NONE: */\n");
2484 fprintf (init_file, " \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n");
2485 fprintf (init_file, " 0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n");
2486 fprintf (init_file, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n");
2487 fprintf (init_file, " },\n");
2488 for (int i = 0; i <= curr_bif; i++)
2489 {
2490 bifdata *bifp = &bifs[bif_order[i]];
2491 fprintf (init_file, " { /* RS6000_BIF_%s: */\n", bifp->idname);
2492 fprintf (init_file, " /* bifname */\t\"%s\",\n",
2493 bifp->proto.bifname);
2494 fprintf (init_file, " /* enable*/\t%s,\n",
2495 enable_string[bifp->stanza]);
2496 /* Type must be instantiated at run time. */
2497 fprintf (init_file, " /* fntype */\t0,\n");
2498 fprintf (init_file, " /* icode */\tCODE_FOR_%s,\n",
2499 bifp->patname);
2500 fprintf (init_file, " /* nargs */\t%d,\n",
2501 bifp->proto.nargs);
2502 fprintf (init_file, " /* bifattrs */\t0");
2503 if (bifp->attrs.isinit)
2504 fprintf (init_file, " | bif_init_bit");
2505 if (bifp->attrs.isset)
2506 fprintf (init_file, " | bif_set_bit");
2507 if (bifp->attrs.isextract)
2508 fprintf (init_file, " | bif_extract_bit");
2509 if (bifp->attrs.isnosoft)
2510 fprintf (init_file, " | bif_nosoft_bit");
2511 if (bifp->attrs.isldvec)
2512 fprintf (init_file, " | bif_ldvec_bit");
2513 if (bifp->attrs.isstvec)
2514 fprintf (init_file, " | bif_stvec_bit");
2515 if (bifp->attrs.isreve)
2516 fprintf (init_file, " | bif_reve_bit");
2517 if (bifp->attrs.ispred)
2518 fprintf (init_file, " | bif_pred_bit");
2519 if (bifp->attrs.ishtm)
2520 fprintf (init_file, " | bif_htm_bit");
2521 if (bifp->attrs.ishtmspr)
2522 fprintf (init_file, " | bif_htmspr_bit");
2523 if (bifp->attrs.ishtmcr)
2524 fprintf (init_file, " | bif_htmcr_bit");
2525 if (bifp->attrs.ismma)
2526 fprintf (init_file, " | bif_mma_bit");
2527 if (bifp->attrs.isquad)
2528 fprintf (init_file, " | bif_quad_bit");
2529 if (bifp->attrs.ispair)
2530 fprintf (init_file, " | bif_pair_bit");
2531 if (bifp->attrs.ismmaint)
2532 fprintf (init_file, " | bif_mmaint_bit");
2533 if (bifp->attrs.isno32bit)
2534 fprintf (init_file, " | bif_no32bit_bit");
2535 if (bifp->attrs.is32bit)
2536 fprintf (init_file, " | bif_32bit_bit");
2537 if (bifp->attrs.iscpu)
2538 fprintf (init_file, " | bif_cpu_bit");
2539 if (bifp->attrs.isldstmask)
2540 fprintf (init_file, " | bif_ldstmask_bit");
2541 if (bifp->attrs.islxvrse)
2542 fprintf (init_file, " | bif_lxvrse_bit");
2543 if (bifp->attrs.islxvrze)
2544 fprintf (init_file, " | bif_lxvrze_bit");
2545 if (bifp->attrs.isendian)
2546 fprintf (init_file, " | bif_endian_bit");
2547 if (bifp->attrs.isibmld)
2548 fprintf (init_file, " | bif_ibmld_bit");
2549 if (bifp->attrs.isibm128)
2550 fprintf (init_file, " | bif_ibm128_bit");
2551 fprintf (init_file, ",\n");
2552 fprintf (init_file, " /* restr_opnd */\t{%d, %d, %d},\n",
2553 bifp->proto.restr_opnd[0], bifp->proto.restr_opnd[1],
2554 bifp->proto.restr_opnd[2]);
2555 for (int j = 0; j < 3; j++)
2556 if (!bifp->proto.restr_opnd[j])
2557 res[j] = "RES_NONE";
2558 else if (bifp->proto.restr[j] == RES_BITS)
2559 res[j] = "RES_BITS";
2560 else if (bifp->proto.restr[j] == RES_RANGE)
2561 res[j] = "RES_RANGE";
2562 else if (bifp->proto.restr[j] == RES_VALUES)
2563 res[j] = "RES_VALUES";
2564 else if (bifp->proto.restr[j] == RES_VAR_RANGE)
2565 res[j] = "RES_VAR_RANGE";
2566 else
2567 res[j] = "ERROR";
2568 fprintf (init_file, " /* restr */\t{%s, %s, %s},\n",
2569 res[0], res[1], res[2]);
2570 fprintf (init_file, " /* restr_val1 */\t{%s, %s, %s},\n",
2571 bifp->proto.restr_val1[0] ? bifp->proto.restr_val1[0] : "0",
2572 bifp->proto.restr_val1[1] ? bifp->proto.restr_val1[1] : "0",
2573 bifp->proto.restr_val1[2] ? bifp->proto.restr_val1[2] : "0");
2574 fprintf (init_file, " /* restr_val2 */\t{%s, %s, %s},\n",
2575 bifp->proto.restr_val2[0] ? bifp->proto.restr_val2[0] : "0",
2576 bifp->proto.restr_val2[1] ? bifp->proto.restr_val2[1] : "0",
2577 bifp->proto.restr_val2[2] ? bifp->proto.restr_val2[2] : "0");
2578 fprintf (init_file, " /* attr_string */\t\"%s\",\n",
2579 (bifp->kind == FNK_CONST ? "= const"
2580 : (bifp->kind == FNK_PURE ? "= pure"
2581 : (bifp->kind == FNK_FPMATH ? "= fp, const"
2582 : ""))));
2583 fprintf (init_file, " /* assoc_bif */\tRS6000_BIF_%s%s\n",
2584 bifp->attrs.ismmaint ? bifp->idname : "NONE",
2585 bifp->attrs.ismmaint ? "_INTERNAL" : "");
2586 fprintf (init_file, " },\n");
2587 }
2588 fprintf (init_file, " };\n\n");
2589 }
2590
2591 /* Write the decls and initializers for rs6000_overload_info[] and
2592 rs6000_instance_info[]. */
2593 static void
2594 write_ovld_static_init (void)
2595 {
2596 fprintf (init_file,
2597 "ovldrecord rs6000_overload_info[RS6000_OVLD_MAX "
2598 "- RS6000_OVLD_NONE] =\n");
2599 fprintf (init_file, " {\n");
2600 fprintf (init_file, " { /* RS6000_OVLD_NONE: */\n");
2601 fprintf (init_file, " \"\", NULL\n");
2602 fprintf (init_file, " },\n");
2603 for (int i = 0; i <= curr_ovld_stanza; i++)
2604 {
2605 fprintf (init_file, " { /* RS6000_OVLD_%s: */\n",
2606 ovld_stanzas[i].stanza_id);
2607 fprintf (init_file, " /* ovld_name */\t\"%s\",\n",
2608 ovld_stanzas[i].intern_name);
2609 /* First-instance must currently be instantiated at run time. */
2610 fprintf (init_file, " /* first_instance */\tNULL\n");
2611 fprintf (init_file, " },\n");
2612 }
2613 fprintf (init_file, " };\n\n");
2614
2615 fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n");
2616 fprintf (init_file, " {\n");
2617 fprintf (init_file, " { /* RS6000_INST_NONE: */\n");
2618 fprintf (init_file, " \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n");
2619 fprintf (init_file, " },\n");
2620 for (int i = 0; i <= curr_ovld; i++)
2621 {
2622 fprintf (init_file, " { /* RS6000_INST_%s: */\n",
2623 ovlds[i].ovld_id_name);
2624 fprintf (init_file, " /* bifname */\t\"%s\",\n",
2625 ovlds[i].proto.bifname);
2626 fprintf (init_file, " /* bifid */\tRS6000_BIF_%s,\n",
2627 ovlds[i].bif_id_name);
2628 /* Type must be instantiated at run time. */
2629 fprintf (init_file, " /* fntype */\t0,\n");
2630 fprintf (init_file, " /* next */\t");
2631 if (i < curr_ovld
2632 && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname))
2633 fprintf (init_file,
2634 "&rs6000_instance_info[RS6000_INST_%s]\n",
2635 ovlds[i+1].ovld_id_name);
2636 else
2637 fprintf (init_file, "NULL\n");
2638 fprintf (init_file, " },\n");
2639 }
2640 fprintf (init_file, " };\n\n");
2641 }
2642
2643 /* Write code to initialize the built-in function table. */
2644 static void
2645 write_init_bif_table (void)
2646 {
2647 for (int i = 0; i <= curr_bif; i++)
2648 {
2649 fprintf (init_file,
2650 " rs6000_builtin_info[RS6000_BIF_%s].fntype"
2651 "\n = %s;\n",
2652 bifs[i].idname, bifs[i].fndecl);
2653
2654 /* Check whether we have a "tf" token in this string, representing
2655 a float128_type_node. It's possible that float128_type_node is
2656 undefined (occurs for -maltivec -mno-vsx, for example), so we
2657 must guard against that. */
2658 int tf_found = strstr (bifs[i].fndecl, "tf") != NULL;
2659
2660 /* Similarly, look for decimal float tokens. */
2661 int dfp_found = (strstr (bifs[i].fndecl, "sd") != NULL
2662 || strstr (bifs[i].fndecl, "dd") != NULL
2663 || strstr (bifs[i].fndecl, "td") != NULL);
2664
2665 if (tf_found)
2666 {
2667 fprintf (init_file, " if (float128_type_node)\n");
2668 fprintf (init_file, " {\n");
2669 }
2670 else if (dfp_found)
2671 {
2672 fprintf (init_file, " if (dfloat64_type_node)\n");
2673 fprintf (init_file, " {\n");
2674 }
2675
2676 fprintf (init_file,
2677 " rs6000_builtin_decls[(int)RS6000_BIF_%s] = t\n",
2678 bifs[i].idname);
2679 fprintf (init_file,
2680 " = add_builtin_function (\"%s\",\n",
2681 bifs[i].proto.bifname);
2682 fprintf (init_file,
2683 " %s,\n",
2684 bifs[i].fndecl);
2685 fprintf (init_file,
2686 " (int)RS6000_BIF_%s,"
2687 " BUILT_IN_MD,\n",
2688 bifs[i].idname);
2689 fprintf (init_file,
2690 " NULL, NULL_TREE);\n");
2691 if (bifs[i].kind == FNK_CONST)
2692 {
2693 fprintf (init_file, " TREE_READONLY (t) = 1;\n");
2694 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n");
2695 }
2696 else if (bifs[i].kind == FNK_PURE)
2697 {
2698 fprintf (init_file, " DECL_PURE_P (t) = 1;\n");
2699 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n");
2700 }
2701 else if (bifs[i].kind == FNK_FPMATH)
2702 {
2703 fprintf (init_file, " TREE_NOTHROW (t) = 1;\n");
2704 fprintf (init_file, " if (flag_rounding_math)\n");
2705 fprintf (init_file, " {\n");
2706 fprintf (init_file, " DECL_PURE_P (t) = 1;\n");
2707 fprintf (init_file, " DECL_IS_NOVOPS (t) = 1;\n");
2708 fprintf (init_file, " }\n");
2709 fprintf (init_file, " else\n");
2710 fprintf (init_file, " TREE_READONLY (t) = 1;\n");
2711 }
2712
2713 if (tf_found || dfp_found)
2714 {
2715 fprintf (init_file, " }\n");
2716 fprintf (init_file, " else\n");
2717 fprintf (init_file, " {\n");
2718 fprintf (init_file, " rs6000_builtin_decls"
2719 "[(int)RS6000_BIF_%s] = NULL_TREE;\n", bifs[i].idname);
2720 fprintf (init_file, " }\n");
2721 }
2722 fprintf (init_file, "\n");
2723 }
2724 }
2725
2726 /* Write code to initialize the overload table. */
2727 static void
2728 write_init_ovld_table (void)
2729 {
2730 fprintf (init_file, " int base = RS6000_OVLD_NONE;\n\n");
2731 fprintf (init_file,
2732 " /* The fndecl for an overload is arbitrarily the first one\n"
2733 " for the overload. We sort out the real types when\n"
2734 " processing the overload in the gcc front end. */\n");
2735
2736 for (int i = 0; i <= curr_ovld; i++)
2737 {
2738 fprintf (init_file,
2739 " rs6000_instance_info[RS6000_INST_%s].fntype"
2740 "\n = %s;\n",
2741 ovlds[i].ovld_id_name, ovlds[i].fndecl);
2742
2743 if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza)
2744 {
2745 ovld_stanza *stanza = &ovld_stanzas[ovlds[i].stanza];
2746 fprintf (init_file, "\n");
2747
2748 /* Check whether we have a "tf" token in this string, representing
2749 a float128_type_node. It's possible that float128_type_node is
2750 undefined (occurs for -maltivec -mno-vsx, for example), so we
2751 must guard against that. */
2752 int tf_found = strstr (ovlds[i].fndecl, "tf") != NULL;
2753
2754 /* Similarly, look for decimal float tokens. */
2755 int dfp_found = (strstr (ovlds[i].fndecl, "sd") != NULL
2756 || strstr (ovlds[i].fndecl, "dd") != NULL
2757 || strstr (ovlds[i].fndecl, "td") != NULL);
2758
2759 if (tf_found)
2760 {
2761 fprintf (init_file, " if (float128_type_node)\n");
2762 fprintf (init_file, " {\n");
2763 }
2764 else if (dfp_found)
2765 {
2766 fprintf (init_file, " if (dfloat64_type_node)\n");
2767 fprintf (init_file, " {\n");
2768 }
2769
2770 fprintf (init_file,
2771 " rs6000_builtin_decls[(int)RS6000_OVLD_%s] = t\n",
2772 stanza->stanza_id);
2773 fprintf (init_file,
2774 " = add_builtin_function (\"%s\",\n",
2775 stanza->intern_name);
2776 fprintf (init_file,
2777 " %s,\n",
2778 ovlds[i].fndecl);
2779 fprintf (init_file,
2780 " (int)RS6000_OVLD_%s,"
2781 " BUILT_IN_MD,\n",
2782 stanza->stanza_id);
2783 fprintf (init_file,
2784 " NULL, NULL_TREE);\n");
2785
2786 if (tf_found || dfp_found)
2787 fprintf (init_file, " }\n");
2788
2789 fprintf (init_file, "\n");
2790
2791 fprintf (init_file,
2792 " rs6000_overload_info[RS6000_OVLD_%s - base]"
2793 ".first_instance\n",
2794 stanza->stanza_id);
2795 fprintf (init_file,
2796 " = &rs6000_instance_info[RS6000_INST_%s];\n\n",
2797 ovlds[i].ovld_id_name);
2798 }
2799 }
2800 }
2801
2802 /* Write everything to the initialization file (rs6000-builtins.cc).
2803 Return 1 if successful, 0 otherwise. */
2804 static int
2805 write_init_file (void)
2806 {
2807 write_autogenerated_header (init_file);
2808
2809 fprintf (init_file, "#include \"config.h\"\n");
2810 fprintf (init_file, "#include \"system.h\"\n");
2811 fprintf (init_file, "#include \"coretypes.h\"\n");
2812 fprintf (init_file, "#include \"backend.h\"\n");
2813 fprintf (init_file, "#include \"rtl.h\"\n");
2814 fprintf (init_file, "#include \"tree.h\"\n");
2815 fprintf (init_file, "#include \"langhooks.h\"\n");
2816 fprintf (init_file, "#include \"insn-codes.h\"\n");
2817 fprintf (init_file, "#include \"rs6000-builtins.h\"\n");
2818 fprintf (init_file, "\n");
2819
2820 fprintf (init_file, "tree rs6000_builtin_decls[RS6000_OVLD_MAX];\n\n");
2821
2822 write_bif_static_init ();
2823 write_ovld_static_init ();
2824
2825 fprintf (init_file, "void\n");
2826 fprintf (init_file, "rs6000_init_generated_builtins ()\n");
2827 fprintf (init_file, "{\n");
2828 fprintf (init_file, " tree t;\n");
2829 rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init);
2830 fprintf (init_file, "\n");
2831
2832 fprintf (init_file,
2833 " rs6000_builtin_decls[RS6000_BIF_NONE] = NULL_TREE;\n");
2834 fprintf (init_file,
2835 " rs6000_builtin_decls[RS6000_BIF_MAX] = NULL_TREE;\n");
2836 fprintf (init_file,
2837 " rs6000_builtin_decls[RS6000_OVLD_NONE] = NULL_TREE;\n\n");
2838
2839 write_init_bif_table ();
2840 write_init_ovld_table ();
2841
2842 fprintf (init_file, "}\n\n");
2843
2844 return 1;
2845 }
2846
2847 /* Write everything to the include file (rs6000-vecdefines.h).
2848 Return 1 if successful, 0 otherwise. */
2849 static int
2850 write_defines_file (void)
2851 {
2852 fprintf (defines_file, "#ifndef _RS6000_VECDEFINES_H\n");
2853 fprintf (defines_file, "#define _RS6000_VECDEFINES_H 1\n\n");
2854 fprintf (defines_file, "#if defined(_ARCH_PPC64) && defined (_ARCH_PWR9)\n");
2855 fprintf (defines_file, " #define _ARCH_PPC64_PWR9 1\n");
2856 fprintf (defines_file, "#endif\n\n");
2857 for (int i = 0; i < num_ovld_stanzas; i++)
2858 if (strcmp (ovld_stanzas[i].extern_name, "SKIP"))
2859 {
2860 if (ovld_stanzas[i].ifdef)
2861 fprintf (defines_file, "#ifdef %s\n", ovld_stanzas[i].ifdef);
2862 fprintf (defines_file, "#define %s %s\n",
2863 ovld_stanzas[i].extern_name,
2864 ovld_stanzas[i].intern_name);
2865 if (ovld_stanzas[i].ifdef)
2866 fprintf (defines_file, "#endif\n");
2867 }
2868 fprintf (defines_file, "\n#endif\n");
2869 return 1;
2870 }
2871
2872 /* Close and delete output files after any failure, so that subsequent
2873 build dependencies will fail. */
2874 static void
2875 delete_output_files (void)
2876 {
2877 /* Depending on whence we're called, some of these may already be
2878 closed. Don't check for errors. */
2879 fclose (header_file);
2880 fclose (init_file);
2881 fclose (defines_file);
2882
2883 remove (header_path);
2884 remove (init_path);
2885 remove (defines_path);
2886 }
2887
2888 /* Main program to convert flat files into built-in initialization code. */
2889 int
2890 main (int argc, const char **argv)
2891 {
2892 if (argc != 6)
2893 {
2894 fprintf (stderr,
2895 "Five arguments required: two input files and three output "
2896 "files.\n");
2897 exit (1);
2898 }
2899
2900 pgm_path = argv[0];
2901 bif_path = argv[1];
2902 ovld_path = argv[2];
2903 header_path = argv[3];
2904 init_path = argv[4];
2905 defines_path = argv[5];
2906
2907 bif_file = fopen (bif_path, "r");
2908 if (!bif_file)
2909 {
2910 fprintf (stderr, "Cannot open input built-in file '%s'.\n", bif_path);
2911 exit (1);
2912 }
2913 ovld_file = fopen (ovld_path, "r");
2914 if (!ovld_file)
2915 {
2916 fprintf (stderr, "Cannot open input overload file '%s'.\n", ovld_path);
2917 exit (1);
2918 }
2919 header_file = fopen (header_path, "w");
2920 if (!header_file)
2921 {
2922 fprintf (stderr, "Cannot open header file '%s' for output.\n",
2923 header_path);
2924 exit (1);
2925 }
2926 init_file = fopen (init_path, "w");
2927 if (!init_file)
2928 {
2929 fprintf (stderr, "Cannot open init file '%s' for output.\n", init_path);
2930 exit (1);
2931 }
2932 defines_file = fopen (defines_path, "w");
2933 if (!defines_file)
2934 {
2935 fprintf (stderr, "Cannot open defines file '%s' for output.\n",
2936 defines_path);
2937 exit (1);
2938 }
2939
2940 /* Allocate some buffers. */
2941 for (int i = 0; i < MAXLINES; i++)
2942 lines[i] = (char *) malloc (LINELEN);
2943
2944 /* Initialize the balanced trees containing built-in function ids,
2945 overload function ids, and function type declaration ids. */
2946 rbt_new (&bif_rbt);
2947 rbt_new (&ovld_rbt);
2948 rbt_new (&fntype_rbt);
2949
2950 /* Initialize another balanced tree that contains a map from built-in
2951 function ids to the order in which they were encountered. */
2952 rbt_new (&bifo_rbt);
2953
2954 /* Parse the built-in function file. */
2955 num_bifs = 0;
2956 line = 0;
2957 if (parse_bif () == PC_PARSEFAIL)
2958 {
2959 fprintf (stderr, "Parsing of '%s' failed, aborting.\n", bif_path);
2960 delete_output_files ();
2961 exit (1);
2962 }
2963 fclose (bif_file);
2964
2965 /* Create a mapping from function IDs in their final order to
2966 the order they appear in the built-in function file. */
2967 create_bif_order ();
2968
2969 #ifdef DEBUG
2970 fprintf (stderr, "\nFunction ID list:\n");
2971 rbt_dump (&bif_rbt, bif_rbt.rbt_root);
2972 fprintf (stderr, "\n");
2973 #endif
2974
2975 /* Parse the overload file. */
2976 num_ovld_stanzas = 0;
2977 num_ovlds = 0;
2978 line = 0;
2979 if (parse_ovld () == PC_PARSEFAIL)
2980 {
2981 fprintf (stderr, "Parsing of '%s' failed, aborting.\n", ovld_path);
2982 delete_output_files ();
2983 exit (1);
2984 }
2985 fclose (ovld_file);
2986
2987 #ifdef DEBUG
2988 fprintf (stderr, "\nFunction type decl list:\n");
2989 rbt_dump (&fntype_rbt, fntype_rbt.rbt_root);
2990 fprintf (stderr, "\n");
2991 #endif
2992
2993 /* Write the header file and the file containing initialization code. */
2994 if (!write_header_file ())
2995 {
2996 fprintf (stderr, "Output to '%s' failed, aborting.\n", header_path);
2997 delete_output_files ();
2998 exit (1);
2999 }
3000 if (!write_init_file ())
3001 {
3002 fprintf (stderr, "Output to '%s' failed, aborting.\n", init_path);
3003 delete_output_files ();
3004 exit (1);
3005 }
3006
3007 /* Write the defines file to be included into altivec.h. */
3008 if (!write_defines_file ())
3009 {
3010 fprintf (stderr, "Output to '%s' failed, aborting.\n", defines_path);
3011 delete_output_files ();
3012 exit (1);
3013 }
3014
3015 /* Always close init_file last. This avoids race conditions in the
3016 build machinery. See comments in t-rs6000. */
3017 fclose (header_file);
3018 fclose (defines_file);
3019 fclose (init_file);
3020
3021 return 0;
3022 }
This page took 0.174908 seconds and 5 git commands to generate.