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>
5 This file is part of GCC.
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
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
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/>. */
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:
25 rs6000-builtins.def Table of built-in functions
26 rs6000-overload.def Table of overload functions
28 Both files group similar functions together in "stanzas," as
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
42 The bracketed gating predicate is the only information allowed on
43 the stanza header line, other than whitespace.
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:
50 [kind] <return-type> <bif-name> (<argument-list>);
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.
59 The attributes line looks like this:
61 <bif-id> <bif-pattern> {<attribute-list>}
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.
71 Attributes are strings, such as these:
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
97 An example stanza might look like this:
100 const vsc __builtin_altivec_abs_v16qi (vsc);
101 ABS_V16QI absv16qi2 {}
102 const vss __builtin_altivec_abs_v8hi (vss);
105 Here "vsc" and "vss" are shorthand for "vector signed char" and
106 "vector signed short" to shorten line lengths and improve readability.
107 Note the use of indentation, which is recommended but not required.
109 The overload file has more complex stanza headers. Here the stanza
110 represents all functions with the same overloaded function name:
112 [<overload-id>, <abi-name>, <builtin-name>[[, <ifdef>]] ]
114 Here the single square brackets are part of the syntax, <overload-id>
115 is a unique internal identifier for the overload that will be used as
116 part of an enumeration of all overloaded functions; <abi-name> is the
117 name that will appear as a #define in rs6000-vecdefines.h;
118 <builtin-name> is the name that is overloaded in the back end; and
119 <ifdef> is an optional token used to guard the #define with an #ifdef
120 in rs6000-vecdefines.h.
122 Each function entry again has two lines. The first line is again a
123 prototype line (this time without [kind]):
125 <return-type> <internal-name> (<argument-list>);
127 The second line contains the <bif-id> that this particular instance of
128 the overloaded function maps to. It must match a token that appears in
129 rs6000-builtins.def. Optionally, a second token may appear. If only
130 one token is on the line, it is also used to build the unique identifier
131 for the overloaded function. If a second token is present, the second
132 token is used instead for this purpose. This is necessary in cases
133 where a built-in function accepts more than one type signature. It is
134 common to have a built-in function that, for example, specifies a
135 "vector signed char" argument, but accepts "vector unsigned char" and
136 "vector bool char" as well because only the mode matters. Note that
137 the overload resolution mechanism has always handled these cases by
138 performing fold_convert on vector arguments to hide type mismatches,
139 and it will continue to do so.
141 As a concrete example, __builtin_altivec_mtvscr uses an opaque argument
142 type for the source operand. Its built-in function id is MTVSCR. The
143 overloaded function __builtin_vec_mtvscr takes a variety of specific
144 types, but not all vector types. Each of these maps to the same
145 __builtin_altivec_mtvscr built-in function, but the overload ID must
146 be unique, so we must specify the second token as shown here.
148 [VEC_MTVSCR, vec_mtvscr, __builtin_vec_mtvscr]
149 void __builtin_vec_mtvscr (vbc);
151 void __builtin_vec_mtvscr (vsc);
155 Blank lines may be used as desired in these files between the lines as
156 defined above; that is, you can introduce as many extra newlines as you
157 like after a required newline, but nowhere else. Lines beginning with
158 a semicolon are also treated as blank lines. */
170 /* Input and output file descriptors and pathnames. */
171 static FILE *bif_file
;
172 static FILE *ovld_file
;
173 static FILE *header_file
;
174 static FILE *init_file
;
175 static FILE *defines_file
;
177 static const char *pgm_path
;
178 static const char *bif_path
;
179 static const char *ovld_path
;
180 static const char *header_path
;
181 static const char *init_path
;
182 static const char *defines_path
;
184 /* Position information. Note that "pos" is zero-indexed, but users
185 expect one-indexed column information, so representations of "pos"
186 as columns in diagnostic messages must be adjusted. */
189 static char linebuf
[LINELEN
* MAXLINES
];
193 /* Escape-newline support. For readability, we prefer to allow developers
194 to use escape-newline to continue long lines to the next one. We
195 maintain a buffer of "original" lines here, which are concatenated into
196 linebuf, above, and which can be used to convert the virtual line
197 position "line / pos" into actual line and position information. */
198 static char *lines
[MAXLINES
];
201 /* Used to determine whether a type can be void (only return types). */
208 /* Stanzas are groupings of built-in functions and overloads by some
209 common feature/attribute. These definitions are for built-in function
237 static bif_stanza curr_bif_stanza
;
241 const char *stanza_name
;
245 static stanza_entry stanza_map
[NUMBIFSTANZAS
] =
247 { "always", BSTZ_ALWAYS
},
248 { "power5", BSTZ_P5
},
249 { "power6", BSTZ_P6
},
250 { "power6-64", BSTZ_P6_64
},
251 { "altivec", BSTZ_ALTIVEC
},
252 { "cell", BSTZ_CELL
},
254 { "power7", BSTZ_P7
},
255 { "power7-64", BSTZ_P7_64
},
256 { "power8", BSTZ_P8
},
257 { "power8-vector", BSTZ_P8V
},
258 { "power9", BSTZ_P9
},
259 { "power9-64", BSTZ_P9_64
},
260 { "power9-vector", BSTZ_P9V
},
261 { "ieee128-hw", BSTZ_IEEE128_HW
},
263 { "crypto", BSTZ_CRYPTO
},
265 { "power10", BSTZ_P10
},
266 { "power10-64", BSTZ_P10_64
},
270 static const char *enable_string
[NUMBIFSTANZAS
] =
295 /* Function modifiers provide special handling for const, pure, and fpmath
296 functions. These are mutually exclusive, and therefore kept separate
297 from other bif attributes. */
306 /* Legal base types for an argument or return type. */
329 /* Ways in which a const int value can be restricted. RES_BITS indicates
330 that the integer is restricted to val1 bits, interpreted as an unsigned
331 number. RES_RANGE indicates that the integer is restricted to values
332 between val1 and val2, inclusive. RES_VAR_RANGE is like RES_RANGE, but
333 the argument may be variable, so it can only be checked if it is constant.
334 RES_VALUES indicates that the integer must have one of the values val1
345 /* Type modifiers for an argument or return type. */
362 /* A list of argument types. */
369 /* Attributes of a builtin function. */
397 /* Fields associated with a function prototype (bif or overload). */
398 #define MAXRESTROPNDS 3
405 int restr_opnd
[MAXRESTROPNDS
];
406 restriction restr
[MAXRESTROPNDS
];
407 char *restr_val1
[MAXRESTROPNDS
];
408 char *restr_val2
[MAXRESTROPNDS
];
411 /* Data associated with a builtin function, and a table of such data. */
412 #define MAXBIFS 16384
424 static bifdata bifs
[MAXBIFS
];
428 /* Array used to track the order in which built-ins appeared in the
429 built-in file. We reorder them alphabetically but sometimes need
431 static int *bif_order
;
432 static int bif_index
= 0;
434 /* Stanzas are groupings of built-in functions and overloads by some
435 common feature/attribute. These definitions are for overload stanzas. */
444 #define MAXOVLDSTANZAS 512
445 static ovld_stanza ovld_stanzas
[MAXOVLDSTANZAS
];
446 static int num_ovld_stanzas
;
447 static int curr_ovld_stanza
;
449 #define MAXOVLDS 16384
459 static ovlddata ovlds
[MAXOVLDS
];
460 static int num_ovlds
;
461 static int curr_ovld
;
462 static int max_ovld_args
= 0;
464 /* Return codes for parsing routines. */
473 /* The red-black trees for built-in function identifiers, built-in
474 overload identifiers, and function type descriptors. */
475 static rbt_strings bif_rbt
;
476 static rbt_strings ovld_rbt
;
477 static rbt_strings fntype_rbt
;
479 /* Another red-black tree containing a mapping from built-in function
480 identifiers to the order in which they were encountered. */
481 static rbt_strings bifo_rbt
;
483 /* Mapping from type tokens to type node names. */
490 /* This table must be kept in alphabetical order, as we use binary
491 search for table lookups in map_token_to_type_node. The table
492 maps tokens from a fntype string to a tree type. For example,
493 in "si_ftype_hi" we would map "si" to "intSI_type_node" and
494 map "hi" to "intHI_type_node". */
495 #define TYPE_MAP_SIZE 86
496 static typemap type_map
[TYPE_MAP_SIZE
] =
498 { "bi", "bool_int" },
499 { "bv16qi", "bool_V16QI" },
500 { "bv1ti", "bool_V1TI" },
501 { "bv2di", "bool_V2DI" },
502 { "bv4si", "bool_V4SI" },
503 { "bv8hi", "bool_V8HI" },
505 { "dd", "dfloat64" },
507 { "di", "long_long_integer" },
509 { "if", "ibm128_float" },
510 { "ld", "long_double" },
511 { "lg", "long_integer" },
512 { "pbv16qi", "ptr_bool_V16QI" },
513 { "pbv1ti", "ptr_bool_V1TI" },
514 { "pbv2di", "ptr_bool_V2DI" },
515 { "pbv4si", "ptr_bool_V4SI" },
516 { "pbv8hi", "ptr_bool_V8HI" },
517 { "pcvoid", "pcvoid" },
518 { "pdd", "ptr_dfloat64" },
519 { "pdf", "ptr_double" },
520 { "pdi", "ptr_long_long_integer" },
521 { "phi", "ptr_intHI" },
522 { "pif", "ptr_ibm128_float" },
523 { "pld", "ptr_long_double" },
524 { "plg", "ptr_long_integer" },
525 { "pqi", "ptr_intQI" },
526 { "psf", "ptr_float" },
527 { "psi", "ptr_intSI" },
528 { "ptd", "ptr_dfloat128" },
529 { "ptf", "ptr_float128" },
530 { "pti", "ptr_intTI" },
531 { "pudi", "ptr_long_long_unsigned" },
532 { "puhi", "ptr_uintHI" },
533 { "pulg", "ptr_long_unsigned" },
534 { "puqi", "ptr_uintQI" },
535 { "pusi", "ptr_uintSI" },
536 { "puti", "ptr_uintTI" },
537 { "puv16qi", "ptr_unsigned_V16QI" },
538 { "puv1ti", "ptr_unsigned_V1TI" },
539 { "puv2di", "ptr_unsigned_V2DI" },
540 { "puv4si", "ptr_unsigned_V4SI" },
541 { "puv8hi", "ptr_unsigned_V8HI" },
543 { "pv16qi", "ptr_V16QI" },
544 { "pv1poi", "ptr_vector_pair" },
545 { "pv1pxi", "ptr_vector_quad" },
546 { "pv1ti", "ptr_V1TI" },
547 { "pv2df", "ptr_V2DF" },
548 { "pv2di", "ptr_V2DI" },
549 { "pv4sf", "ptr_V4SF" },
550 { "pv4si", "ptr_V4SI" },
551 { "pv8hi", "ptr_V8HI" },
552 { "pvp8hi", "ptr_pixel_V8HI" },
554 { "sd", "dfloat32" },
557 { "st", "const_str" },
558 { "td", "dfloat128" },
559 { "tf", "float128" },
561 { "udi", "long_long_unsigned" },
562 { "uhi", "unsigned_intHI" },
563 { "ulg", "long_unsigned" },
564 { "uqi", "unsigned_intQI" },
565 { "usi", "unsigned_intSI" },
566 { "uti", "unsigned_intTI" },
567 { "uv16qi", "unsigned_V16QI" },
568 { "uv1ti", "unsigned_V1TI" },
569 { "uv2di", "unsigned_V2DI" },
570 { "uv4si", "unsigned_V4SI" },
571 { "uv8hi", "unsigned_V8HI" },
573 { "v16qi", "V16QI" },
574 { "v1poi", "vector_pair" },
575 { "v1pxi", "vector_quad" },
582 { "vp8hi", "pixel_V8HI" },
585 /* From a possibly extended line with a virtual position, calculate
586 the current line and character position. */
588 real_line_pos (int diagpos
, int *real_line
, int *real_pos
)
590 *real_line
= line
- lastline
;
593 for (int i
= 0; i
< MAXLINES
; i
++)
595 int len
= strlen(lines
[i
]);
596 if (*real_pos
<= len
)
600 *real_pos
-= len
- 2;
603 /* Convert from zero-base to one-base for printing. */
607 /* Pointer to a diagnostic function. */
608 static void (*diag
) (int, const char *, ...)
609 __attribute__ ((format (printf
, 2, 3)));
611 /* Custom diagnostics. */
612 static void __attribute__ ((format (printf
, 2, 3)))
613 bif_diag (int diagpos
, const char * fmt
, ...)
616 int real_line
, real_pos
;
617 real_line_pos (diagpos
, &real_line
, &real_pos
);
618 fprintf (stderr
, "%s:%d:%d: ", bif_path
, real_line
, real_pos
);
619 va_start (args
, fmt
);
620 vfprintf (stderr
, fmt
, args
);
624 static void __attribute__ ((format (printf
, 2, 3)))
625 ovld_diag (int diagpos
, const char * fmt
, ...)
628 int real_line
, real_pos
;
629 real_line_pos (diagpos
, &real_line
, &real_pos
);
630 fprintf (stderr
, "%s:%d:%d: ", ovld_path
, real_line
, real_pos
);
631 va_start (args
, fmt
);
632 vfprintf (stderr
, fmt
, args
);
636 /* Produce a fatal error message. */
638 fatal (const char *msg
)
640 fprintf (stderr
, "FATAL: %s\n", msg
);
644 /* Pass over whitespace (other than a newline, which terminates the scan). */
646 consume_whitespace (void)
648 while (pos
< LINELEN
&& isspace(linebuf
[pos
]) && linebuf
[pos
] != '\n')
653 diag (pos
, "line length overrun.\n");
660 /* Get the next nonblank, noncomment line, returning 0 on EOF, 1 otherwise. */
662 advance_line (FILE *file
)
666 /* Read ahead one line and check for EOF. */
667 if (!fgets (linebuf
, sizeof linebuf
, file
))
670 size_t len
= strlen (linebuf
);
672 /* Escape-newline processing. */
676 strcpy (lines
[0], linebuf
);
677 while (linebuf
[len
- 2] == '\\'
678 && linebuf
[len
- 1] == '\n')
681 if (lastline
== MAXLINES
)
682 fatal ("number of supported overflow lines exceeded");
684 if (!fgets (lines
[lastline
], LINELEN
, file
))
685 fatal ("unexpected end of file");
686 strcpy (&linebuf
[len
- 2], lines
[lastline
]);
687 len
+= strlen (lines
[lastline
]) - 2;
691 if (linebuf
[len
- 1] != '\n')
692 fatal ("line doesn't terminate with newline");
694 consume_whitespace ();
695 if (linebuf
[pos
] != '\n' && linebuf
[pos
] != ';')
703 if (++pos
>= LINELEN
)
705 diag (pos
, "line length overrun.\n");
710 /* Match an identifier, returning NULL on failure, else a pointer to a
711 buffer containing the identifier. */
713 match_identifier (void)
715 int lastpos
= pos
- 1;
716 while (lastpos
< LINELEN
- 1
717 && (isalnum (linebuf
[lastpos
+ 1]) || linebuf
[lastpos
+ 1] == '_'))
720 if (lastpos
>= LINELEN
- 1)
722 diag (lastpos
, "line length overrun.\n");
729 char *buf
= (char *) malloc (lastpos
- pos
+ 2);
730 memcpy (buf
, &linebuf
[pos
], lastpos
- pos
+ 1);
731 buf
[lastpos
- pos
+ 1] = '\0';
737 /* Match an integer and return the string representing its value,
738 or a null string on failure. */
743 if (linebuf
[pos
] == '-')
746 int lastpos
= pos
- 1;
747 while (lastpos
< LINELEN
- 1 && isdigit (linebuf
[lastpos
+ 1]))
750 if (lastpos
>= LINELEN
- 1)
752 diag (lastpos
, "line length overrun.\n");
760 char *buf
= (char *) malloc (lastpos
- startpos
+ 2);
761 memcpy (buf
, &linebuf
[startpos
], lastpos
- startpos
+ 1);
762 buf
[lastpos
- startpos
+ 1] = '\0';
766 /* Match a string up to but not including a ']', and return its value,
767 or zero if there is nothing before the ']'. Error if we don't find
770 match_to_right_bracket (void)
772 int lastpos
= pos
- 1;
773 while (lastpos
< LINELEN
- 1 && linebuf
[lastpos
+ 1] != ']')
775 if (linebuf
[lastpos
+ 1] == '\n')
776 fatal ("no ']' found before end of line.\n");
780 if (lastpos
>= LINELEN
- 1)
782 diag (lastpos
, "line length overrun.\n");
789 char *buf
= (char *) malloc (lastpos
- pos
+ 2);
790 memcpy (buf
, &linebuf
[pos
], lastpos
- pos
+ 1);
791 buf
[lastpos
- pos
+ 1] = '\0';
798 handle_pointer (typeinfo
*typedata
)
800 consume_whitespace ();
801 if (linebuf
[pos
] == '*')
803 typedata
->ispointer
= 1;
809 stanza_name_to_stanza (const char *stanza_name
)
811 for (int i
= 0; i
< NUMBIFSTANZAS
; i
++)
812 if (!strcmp (stanza_name
, stanza_map
[i
].stanza_name
))
813 return stanza_map
[i
].stanza
;
814 fatal ("Stanza mapping is inconsistent.");
819 /* Match one of the allowable base types. Consumes one token unless the
820 token is "long", which must be paired with a second "long". Optionally
821 consumes a following '*' token for pointers. Return 1 for success,
824 match_basetype (typeinfo
*typedata
)
826 consume_whitespace ();
828 char *token
= match_identifier ();
831 diag (pos
, "missing base type in return type\n");
835 if (!strcmp (token
, "char"))
836 typedata
->base
= BT_CHAR
;
837 else if (!strcmp (token
, "short"))
838 typedata
->base
= BT_SHORT
;
839 else if (!strcmp (token
, "int"))
840 typedata
->base
= BT_INT
;
841 else if (!strcmp (token
, "long"))
843 consume_whitespace ();
845 char *mustbelongordbl
= match_identifier ();
846 if (!mustbelongordbl
)
847 typedata
->base
= BT_LONG
;
848 else if (!strcmp (mustbelongordbl
, "long"))
849 typedata
->base
= BT_LONGLONG
;
850 else if (!strcmp (mustbelongordbl
, "double"))
851 typedata
->base
= BT_LONGDOUBLE
;
853 /* Speculatively accept "long" here and push back the token.
854 This occurs when "long" is a return type and the next token
855 is the function name. */
857 typedata
->base
= BT_LONG
;
861 else if (!strcmp (token
, "float"))
862 typedata
->base
= BT_FLOAT
;
863 else if (!strcmp (token
, "double"))
864 typedata
->base
= BT_DOUBLE
;
865 else if (!strcmp (token
, "__int128"))
866 typedata
->base
= BT_INT128
;
867 else if (!strcmp (token
, "_Float128"))
868 typedata
->base
= BT_FLOAT128
;
869 else if (!strcmp (token
, "bool"))
870 typedata
->base
= BT_BOOL
;
871 /* A "string" is a special "const char *" -- we need it because it
872 cannot match either signed or unsigned char *. */
873 else if (!strcmp (token
, "string"))
874 typedata
->base
= BT_STRING
;
875 else if (!strcmp (token
, "_Decimal32"))
876 typedata
->base
= BT_DECIMAL32
;
877 else if (!strcmp (token
, "_Decimal64"))
878 typedata
->base
= BT_DECIMAL64
;
879 else if (!strcmp (token
, "_Decimal128"))
880 typedata
->base
= BT_DECIMAL128
;
881 else if (!strcmp (token
, "__ibm128"))
882 typedata
->base
= BT_IBM128
;
885 diag (oldpos
, "unrecognized base type\n");
889 handle_pointer (typedata
);
893 /* Helper routine for match_const_restriction. */
895 match_bracketed_pair (typeinfo
*typedata
, char open
, char close
,
898 if (linebuf
[pos
] == open
)
902 char *x
= match_integer ();
905 diag (oldpos
, "malformed integer.\n");
908 consume_whitespace ();
909 if (linebuf
[pos
] != ',')
911 diag (pos
, "missing comma.\n");
915 consume_whitespace ();
917 char *y
= match_integer ();
920 diag (oldpos
, "malformed integer.\n");
923 typedata
->restr
= restr
;
927 consume_whitespace ();
928 if (linebuf
[pos
] != close
)
930 diag (pos
, "malformed restriction.\n");
940 /* A const int argument may be restricted to certain values. This is
941 indicated by one of the following occurring after the "int' token:
943 <x> restricts the constant to x bits, interpreted as unsigned
944 <x,y> restricts the constant to the inclusive range [x,y]
945 [x,y] restricts the constant to the inclusive range [x,y],
946 but only applies if the argument is constant.
947 {x,y} restricts the constant to one of two values, x or y.
949 Here x and y are integer tokens. Note that the "const" token is a
950 lie when the restriction is [x,y], but this simplifies the parsing
951 significantly and is hopefully forgivable.
953 Return 1 for success, else 0. */
955 match_const_restriction (typeinfo
*typedata
)
958 if (linebuf
[pos
] == '<')
962 char *x
= match_integer ();
965 diag (oldpos
, "malformed integer.\n");
968 consume_whitespace ();
969 if (linebuf
[pos
] == '>')
971 typedata
->restr
= RES_BITS
;
976 else if (linebuf
[pos
] != ',')
978 diag (pos
, "malformed restriction.\n");
983 char *y
= match_integer ();
986 diag (oldpos
, "malformed integer.\n");
989 typedata
->restr
= RES_RANGE
;
993 consume_whitespace ();
994 if (linebuf
[pos
] != '>')
996 diag (pos
, "malformed restriction.\n");
1002 else if (match_bracketed_pair (typedata
, '{', '}', RES_VALUES
)
1003 || match_bracketed_pair (typedata
, '[', ']', RES_VAR_RANGE
))
1009 /* Look for a type, which can be terminated by a token that is not part of
1010 a type, a comma, or a closing parenthesis. Place information about the
1011 type in TYPEDATA. Return 1 for success, 0 for failure. */
1013 match_type (typeinfo
*typedata
, int voidok
)
1015 /* A legal type is of the form:
1017 [const] [[signed|unsigned] <basetype> | <vectype>] [*]
1019 Legal values of <basetype> are (for now):
1038 Legal values of <vectype> are as follows, and are shorthand for
1039 the associated meaning:
1041 vsc vector signed char
1042 vuc vector unsigned char
1043 vbc vector bool char
1044 vss vector signed short
1045 vus vector unsigned short
1046 vbs vector bool short
1047 vsi vector signed int
1048 vui vector unsigned int
1050 vsll vector signed long long
1051 vull vector unsigned long long
1052 vbll vector bool long long
1053 vsq vector signed __int128
1054 vuq vector unsigned __int128
1055 vbq vector bool __int128
1062 For simplicity, We don't support "short int" and "long long int".
1063 We don't currently support a <basetype> of "_Float16". "signed"
1064 and "unsigned" only apply to integral base types. The optional *
1065 indicates a pointer type. */
1067 consume_whitespace ();
1068 memset (typedata
, 0, sizeof *typedata
);
1071 char *token
= match_identifier ();
1075 if (!strcmp (token
, "const"))
1077 typedata
->isconst
= 1;
1078 consume_whitespace ();
1080 token
= match_identifier ();
1083 if (!strcmp (token
, "void"))
1084 typedata
->isvoid
= 1;
1086 if (!strcmp (token
, "vsc"))
1088 typedata
->isvector
= 1;
1089 typedata
->issigned
= 1;
1090 typedata
->base
= BT_CHAR
;
1091 handle_pointer (typedata
);
1094 else if (!strcmp (token
, "vuc"))
1096 typedata
->isvector
= 1;
1097 typedata
->isunsigned
= 1;
1098 typedata
->base
= BT_CHAR
;
1099 handle_pointer (typedata
);
1102 else if (!strcmp (token
, "vbc"))
1104 typedata
->isvector
= 1;
1105 typedata
->isbool
= 1;
1106 typedata
->base
= BT_CHAR
;
1107 handle_pointer (typedata
);
1110 else if (!strcmp (token
, "vss"))
1112 typedata
->isvector
= 1;
1113 typedata
->issigned
= 1;
1114 typedata
->base
= BT_SHORT
;
1115 handle_pointer (typedata
);
1118 else if (!strcmp (token
, "vus"))
1120 typedata
->isvector
= 1;
1121 typedata
->isunsigned
= 1;
1122 typedata
->base
= BT_SHORT
;
1123 handle_pointer (typedata
);
1126 else if (!strcmp (token
, "vbs"))
1128 typedata
->isvector
= 1;
1129 typedata
->isbool
= 1;
1130 typedata
->base
= BT_SHORT
;
1131 handle_pointer (typedata
);
1134 else if (!strcmp (token
, "vsi"))
1136 typedata
->isvector
= 1;
1137 typedata
->issigned
= 1;
1138 typedata
->base
= BT_INT
;
1139 handle_pointer (typedata
);
1142 else if (!strcmp (token
, "vui"))
1144 typedata
->isvector
= 1;
1145 typedata
->isunsigned
= 1;
1146 typedata
->base
= BT_INT
;
1147 handle_pointer (typedata
);
1150 else if (!strcmp (token
, "vbi"))
1152 typedata
->isvector
= 1;
1153 typedata
->isbool
= 1;
1154 typedata
->base
= BT_INT
;
1155 handle_pointer (typedata
);
1158 else if (!strcmp (token
, "vsll"))
1160 typedata
->isvector
= 1;
1161 typedata
->issigned
= 1;
1162 typedata
->base
= BT_LONGLONG
;
1163 handle_pointer (typedata
);
1166 else if (!strcmp (token
, "vull"))
1168 typedata
->isvector
= 1;
1169 typedata
->isunsigned
= 1;
1170 typedata
->base
= BT_LONGLONG
;
1171 handle_pointer (typedata
);
1174 else if (!strcmp (token
, "vbll"))
1176 typedata
->isvector
= 1;
1177 typedata
->isbool
= 1;
1178 typedata
->base
= BT_LONGLONG
;
1179 handle_pointer (typedata
);
1182 else if (!strcmp (token
, "vsq"))
1184 typedata
->isvector
= 1;
1185 typedata
->issigned
= 1;
1186 typedata
->base
= BT_INT128
;
1187 handle_pointer (typedata
);
1190 else if (!strcmp (token
, "vuq"))
1192 typedata
->isvector
= 1;
1193 typedata
->isunsigned
= 1;
1194 typedata
->base
= BT_INT128
;
1195 handle_pointer (typedata
);
1198 else if (!strcmp (token
, "vbq"))
1200 typedata
->isvector
= 1;
1201 typedata
->isbool
= 1;
1202 typedata
->base
= BT_INT128
;
1203 handle_pointer (typedata
);
1206 else if (!strcmp (token
, "vp"))
1208 typedata
->isvector
= 1;
1209 typedata
->ispixel
= 1;
1210 typedata
->base
= BT_SHORT
;
1211 handle_pointer (typedata
);
1214 else if (!strcmp (token
, "vf"))
1216 typedata
->isvector
= 1;
1217 typedata
->base
= BT_FLOAT
;
1218 handle_pointer (typedata
);
1221 else if (!strcmp (token
, "vd"))
1223 typedata
->isvector
= 1;
1224 typedata
->base
= BT_DOUBLE
;
1225 handle_pointer (typedata
);
1228 else if (!strcmp (token
, "v256"))
1230 typedata
->isvector
= 1;
1231 typedata
->base
= BT_VPAIR
;
1232 handle_pointer (typedata
);
1235 else if (!strcmp (token
, "v512"))
1237 typedata
->isvector
= 1;
1238 typedata
->base
= BT_VQUAD
;
1239 handle_pointer (typedata
);
1242 else if (!strcmp (token
, "signed"))
1243 typedata
->issigned
= 1;
1244 else if (!strcmp (token
, "unsigned"))
1245 typedata
->isunsigned
= 1;
1246 else if (!typedata
->isvoid
&& !typedata
->isconst
)
1248 /* Push back token. */
1250 return match_basetype (typedata
);
1253 if (typedata
->isvoid
)
1255 consume_whitespace ();
1256 if (linebuf
[pos
] == '*')
1258 typedata
->ispointer
= 1;
1266 if (!typedata
->issigned
&& !typedata
->isunsigned
)
1268 if (!match_basetype (typedata
))
1271 if (typedata
->isconst
)
1273 if (typedata
->ispointer
)
1275 if (typedata
->base
!= BT_INT
)
1277 diag (oldpos
, "'const' requires pointer or integer type\n");
1280 consume_whitespace ();
1281 if (linebuf
[pos
] == '<' || linebuf
[pos
] == '{' || linebuf
[pos
] == '[')
1282 return match_const_restriction (typedata
);
1288 /* Parse the argument list. */
1290 parse_args (prototype
*protoptr
)
1292 typelist
**argptr
= &protoptr
->args
;
1293 int *nargs
= &protoptr
->nargs
;
1294 int *restr_opnd
= protoptr
->restr_opnd
;
1295 restriction
*restr
= protoptr
->restr
;
1296 char **val1
= protoptr
->restr_val1
;
1297 char **val2
= protoptr
->restr_val2
;
1303 /* Start the argument list. */
1304 consume_whitespace ();
1305 if (linebuf
[pos
] != '(')
1307 diag (pos
, "missing '('.\n");
1308 return PC_PARSEFAIL
;
1313 consume_whitespace ();
1315 typelist
*argentry
= (typelist
*) malloc (sizeof (typelist
));
1316 memset (argentry
, 0, sizeof *argentry
);
1317 typeinfo
*argtype
= &argentry
->info
;
1318 success
= match_type (argtype
, VOID_NOTOK
);
1323 if (restr_cnt
>= MAXRESTROPNDS
)
1325 diag (pos
, "More than two %d operands\n", MAXRESTROPNDS
);
1326 return PC_PARSEFAIL
;
1328 restr_opnd
[restr_cnt
] = *nargs
+ 1;
1329 restr
[restr_cnt
] = argtype
->restr
;
1330 val1
[restr_cnt
] = argtype
->val1
;
1331 val2
[restr_cnt
] = argtype
->val2
;
1336 argptr
= &argentry
->next
;
1337 consume_whitespace ();
1338 if (linebuf
[pos
] == ',')
1340 else if (linebuf
[pos
] != ')')
1342 diag (pos
, "arg not followed by ',' or ')'.\n");
1343 return PC_PARSEFAIL
;
1348 "argument type: isvoid = %d, isconst = %d, isvector = %d, "
1349 "issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, "
1350 "ispointer = %d, base = %d, restr = %d, val1 = \"%s\", "
1351 "val2 = \"%s\", pos = %d.\n",
1352 argtype
->isvoid
, argtype
->isconst
, argtype
->isvector
,
1353 argtype
->issigned
, argtype
->isunsigned
, argtype
->isbool
,
1354 argtype
->ispixel
, argtype
->ispointer
, argtype
->base
,
1355 argtype
->restr
, argtype
->val1
, argtype
->val2
, pos
+ 1);
1363 if (linebuf
[pos
] != ')')
1365 diag (pos
, "badly terminated arg list.\n");
1366 return PC_PARSEFAIL
;
1375 /* Parse the attribute list. */
1377 parse_bif_attrs (attrinfo
*attrptr
)
1379 consume_whitespace ();
1380 if (linebuf
[pos
] != '{')
1382 diag (pos
, "missing attribute set.\n");
1383 return PC_PARSEFAIL
;
1387 memset (attrptr
, 0, sizeof *attrptr
);
1388 char *attrname
= NULL
;
1391 consume_whitespace ();
1393 attrname
= match_identifier ();
1396 if (!strcmp (attrname
, "init"))
1397 attrptr
->isinit
= 1;
1398 else if (!strcmp (attrname
, "set"))
1400 else if (!strcmp (attrname
, "extract"))
1401 attrptr
->isextract
= 1;
1402 else if (!strcmp (attrname
, "nosoft"))
1403 attrptr
->isnosoft
= 1;
1404 else if (!strcmp (attrname
, "ldvec"))
1405 attrptr
->isldvec
= 1;
1406 else if (!strcmp (attrname
, "stvec"))
1407 attrptr
->isstvec
= 1;
1408 else if (!strcmp (attrname
, "reve"))
1409 attrptr
->isreve
= 1;
1410 else if (!strcmp (attrname
, "pred"))
1411 attrptr
->ispred
= 1;
1412 else if (!strcmp (attrname
, "htm"))
1414 else if (!strcmp (attrname
, "htmspr"))
1415 attrptr
->ishtmspr
= 1;
1416 else if (!strcmp (attrname
, "htmcr"))
1417 attrptr
->ishtmcr
= 1;
1418 else if (!strcmp (attrname
, "mma"))
1420 else if (!strcmp (attrname
, "quad"))
1421 attrptr
->isquad
= 1;
1422 else if (!strcmp (attrname
, "pair"))
1423 attrptr
->ispair
= 1;
1424 else if (!strcmp (attrname
, "mmaint"))
1425 attrptr
->ismmaint
= 1;
1426 else if (!strcmp (attrname
, "no32bit"))
1427 attrptr
->isno32bit
= 1;
1428 else if (!strcmp (attrname
, "32bit"))
1429 attrptr
->is32bit
= 1;
1430 else if (!strcmp (attrname
, "cpu"))
1432 else if (!strcmp (attrname
, "ldstmask"))
1433 attrptr
->isldstmask
= 1;
1434 else if (!strcmp (attrname
, "lxvrse"))
1435 attrptr
->islxvrse
= 1;
1436 else if (!strcmp (attrname
, "lxvrze"))
1437 attrptr
->islxvrze
= 1;
1438 else if (!strcmp (attrname
, "endian"))
1439 attrptr
->isendian
= 1;
1440 else if (!strcmp (attrname
, "ibmld"))
1441 attrptr
->isibmld
= 1;
1444 diag (oldpos
, "unknown attribute.\n");
1445 return PC_PARSEFAIL
;
1448 consume_whitespace ();
1449 if (linebuf
[pos
] == ',')
1451 else if (linebuf
[pos
] != '}')
1453 diag (pos
, "arg not followed by ',' or '}'.\n");
1454 return PC_PARSEFAIL
;
1460 if (linebuf
[pos
] != '}')
1462 diag (pos
, "badly terminated attr set.\n");
1463 return PC_PARSEFAIL
;
1471 "attribute set: init = %d, set = %d, extract = %d, nosoft = %d, "
1472 "ldvec = %d, stvec = %d, reve = %d, pred = %d, htm = %d, "
1473 "htmspr = %d, htmcr = %d, mma = %d, quad = %d, pair = %d, "
1474 "mmaint = %d, no32bit = %d, 32bit = %d, cpu = %d, ldstmask = %d, "
1475 "lxvrse = %d, lxvrze = %d, endian = %d, ibmdld= %d.\n",
1476 attrptr
->isinit
, attrptr
->isset
, attrptr
->isextract
,
1477 attrptr
->isnosoft
, attrptr
->isldvec
, attrptr
->isstvec
,
1478 attrptr
->isreve
, attrptr
->ispred
, attrptr
->ishtm
, attrptr
->ishtmspr
,
1479 attrptr
->ishtmcr
, attrptr
->ismma
, attrptr
->isquad
, attrptr
->ispair
,
1480 attrptr
->ismmaint
, attrptr
->isno32bit
, attrptr
->is32bit
,
1481 attrptr
->iscpu
, attrptr
->isldstmask
, attrptr
->islxvrse
,
1482 attrptr
->islxvrze
, attrptr
->isendian
, attrptr
->isibmld
);
1488 /* Convert a vector type into a mode string. */
1490 complete_vector_type (typeinfo
*typeptr
, char *buf
, int *bufi
)
1492 if (typeptr
->isbool
)
1493 buf
[(*bufi
)++] = 'b';
1494 buf
[(*bufi
)++] = 'v';
1495 if (typeptr
->ispixel
)
1497 memcpy (&buf
[*bufi
], "p8hi", 4);
1501 switch (typeptr
->base
)
1504 memcpy (&buf
[*bufi
], "16qi", 4);
1508 memcpy (&buf
[*bufi
], "8hi", 3);
1512 memcpy (&buf
[*bufi
], "4si", 3);
1516 memcpy (&buf
[*bufi
], "2di", 3);
1520 memcpy (&buf
[*bufi
], "4sf", 3);
1524 memcpy (&buf
[*bufi
], "2df", 3);
1528 memcpy (&buf
[*bufi
], "1ti", 3);
1532 memcpy (&buf
[*bufi
], "1tf", 3);
1536 memcpy (&buf
[*bufi
], "1poi", 4);
1540 memcpy (&buf
[*bufi
], "1pxi", 4);
1544 diag (pos
, "unhandled basetype %d.\n", typeptr
->base
);
1549 /* Convert a base type into a mode string. */
1551 complete_base_type (typeinfo
*typeptr
, char *buf
, int *bufi
)
1553 switch (typeptr
->base
)
1556 memcpy (&buf
[*bufi
], "qi", 2);
1559 memcpy (&buf
[*bufi
], "hi", 2);
1562 memcpy (&buf
[*bufi
], "si", 2);
1565 memcpy (&buf
[*bufi
], "lg", 2);
1568 memcpy (&buf
[*bufi
], "di", 2);
1571 memcpy (&buf
[*bufi
], "sf", 2);
1574 memcpy (&buf
[*bufi
], "df", 2);
1577 memcpy (&buf
[*bufi
], "ld", 2);
1580 memcpy (&buf
[*bufi
], "ti", 2);
1583 memcpy (&buf
[*bufi
], "tf", 2);
1586 memcpy (&buf
[*bufi
], "bi", 2);
1589 memcpy (&buf
[*bufi
], "st", 2);
1592 memcpy (&buf
[*bufi
], "sd", 2);
1595 memcpy (&buf
[*bufi
], "dd", 2);
1598 memcpy (&buf
[*bufi
], "td", 2);
1601 memcpy (&buf
[*bufi
], "if", 2);
1604 diag (pos
, "unhandled basetype %d.\n", typeptr
->base
);
1611 /* Build a function type descriptor identifier from the return type
1612 and argument types described by PROTOPTR, and store it if it does
1613 not already exist. Return the identifier. */
1615 construct_fntype_id (prototype
*protoptr
)
1617 /* Determine the maximum space for a function type descriptor id.
1618 Each type requires at most 9 characters (6 for the mode*, 1 for
1619 the optional 'u' preceding the mode, 1 for the optional 'p'
1620 preceding the mode, and 1 for an underscore following the mode).
1621 We also need 5 characters for the string "ftype" that separates
1622 the return mode from the argument modes. The last argument doesn't
1623 need a trailing underscore, but we count that as the one trailing
1624 "ftype" instead. For the special case of zero arguments, we need 9
1625 for the return type and 7 for "ftype_v". Finally, we need one
1626 character for the terminating null. Thus for a function with N
1627 arguments, we need at most 9N+15 characters for N>0, otherwise 17.
1629 *Worst case is bv16qi for "vector bool char". */
1630 int len
= protoptr
->nargs
? (protoptr
->nargs
+ 1) * 9 + 6 : 17;
1631 char *buf
= (char *) malloc (len
);
1634 if (protoptr
->rettype
.ispointer
)
1637 if (protoptr
->rettype
.isvoid
)
1641 if (protoptr
->rettype
.isunsigned
)
1643 if (protoptr
->rettype
.isvector
)
1644 complete_vector_type (&protoptr
->rettype
, buf
, &bufi
);
1646 complete_base_type (&protoptr
->rettype
, buf
, &bufi
);
1649 memcpy (&buf
[bufi
], "_ftype", 6);
1652 if (!protoptr
->nargs
)
1654 memcpy (&buf
[bufi
], "_v", 2);
1659 typelist
*argptr
= protoptr
->args
;
1660 for (int i
= 0; i
< protoptr
->nargs
; i
++, argptr
= argptr
->next
)
1664 if (argptr
->info
.isconst
1665 && argptr
->info
.base
== BT_INT
1666 && !argptr
->info
.ispointer
)
1672 if (argptr
->info
.ispointer
)
1674 if (argptr
->info
.isvoid
)
1676 if (argptr
->info
.isconst
)
1678 memcpy (&buf
[bufi
], "pcvoid", 6);
1693 if (argptr
->info
.isunsigned
)
1695 if (argptr
->info
.isvector
)
1696 complete_vector_type (&argptr
->info
, buf
, &bufi
);
1698 complete_base_type (&argptr
->info
, buf
, &bufi
);
1705 /* Ignore return value, as duplicates are fine and expected here. */
1706 rbt_insert (&fntype_rbt
, buf
);
1711 /* Parse a function prototype. This code is shared by the bif and overload
1714 parse_prototype (prototype
*protoptr
)
1716 typeinfo
*ret_type
= &protoptr
->rettype
;
1717 char **bifname
= &protoptr
->bifname
;
1719 /* Get the return type. */
1720 consume_whitespace ();
1722 int success
= match_type (ret_type
, VOID_OK
);
1725 diag (oldpos
, "missing or badly formed return type.\n");
1726 return PC_PARSEFAIL
;
1731 "return type: isvoid = %d, isconst = %d, isvector = %d, "
1732 "issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, "
1733 "ispointer = %d, base = %d, restr = %d, val1 = \"%s\", "
1734 "val2 = \"%s\", pos = %d.\n",
1735 ret_type
->isvoid
, ret_type
->isconst
, ret_type
->isvector
,
1736 ret_type
->issigned
, ret_type
->isunsigned
, ret_type
->isbool
,
1737 ret_type
->ispixel
, ret_type
->ispointer
, ret_type
->base
,
1738 ret_type
->restr
, ret_type
->val1
, ret_type
->val2
, pos
+ 1);
1741 /* Get the bif name. */
1742 consume_whitespace ();
1744 *bifname
= match_identifier ();
1747 diag (oldpos
, "missing function name.\n");
1748 return PC_PARSEFAIL
;
1752 diag (0, "function name is '%s'.\n", *bifname
);
1755 /* Process arguments. */
1756 if (parse_args (protoptr
) == PC_PARSEFAIL
)
1757 return PC_PARSEFAIL
;
1759 /* Process terminating semicolon. */
1760 consume_whitespace ();
1761 if (linebuf
[pos
] != ';')
1763 diag (pos
, "missing semicolon.\n");
1764 return PC_PARSEFAIL
;
1767 consume_whitespace ();
1768 if (linebuf
[pos
] != '\n')
1770 diag (pos
, "garbage at end of line.\n");
1771 return PC_PARSEFAIL
;
1777 /* Parse a two-line entry for a built-in function. */
1779 parse_bif_entry (void)
1781 /* Check for end of stanza. */
1783 consume_whitespace ();
1784 if (linebuf
[pos
] == '[')
1787 /* Allocate an entry in the bif table. */
1788 if (num_bifs
>= MAXBIFS
- 1)
1790 diag (pos
, "too many built-in functions.\n");
1791 return PC_PARSEFAIL
;
1794 curr_bif
= num_bifs
++;
1795 bifs
[curr_bif
].stanza
= curr_bif_stanza
;
1797 /* Read the first token and see if it is a function modifier. */
1798 consume_whitespace ();
1800 char *token
= match_identifier ();
1803 diag (oldpos
, "malformed entry.\n");
1804 return PC_PARSEFAIL
;
1807 if (!strcmp (token
, "const"))
1808 bifs
[curr_bif
].kind
= FNK_CONST
;
1809 else if (!strcmp (token
, "pure"))
1810 bifs
[curr_bif
].kind
= FNK_PURE
;
1811 else if (!strcmp (token
, "fpmath"))
1812 bifs
[curr_bif
].kind
= FNK_FPMATH
;
1815 /* No function modifier, so push the token back. */
1817 bifs
[curr_bif
].kind
= FNK_NONE
;
1820 if (parse_prototype (&bifs
[curr_bif
].proto
) == PC_PARSEFAIL
)
1821 return PC_PARSEFAIL
;
1823 /* Build a function type descriptor identifier from the return type
1824 and argument types, and store it if it does not already exist. */
1825 bifs
[curr_bif
].fndecl
= construct_fntype_id (&bifs
[curr_bif
].proto
);
1827 /* Now process line 2. First up is the builtin id. */
1828 if (!advance_line (bif_file
))
1830 diag (pos
, "unexpected EOF.\n");
1831 return PC_PARSEFAIL
;
1835 consume_whitespace ();
1837 bifs
[curr_bif
].idname
= match_identifier ();
1838 if (!bifs
[curr_bif
].idname
)
1840 diag (pos
, "missing builtin id.\n");
1841 return PC_PARSEFAIL
;
1845 diag (0, "ID name is '%s'.\n", bifs
[curr_bif
].idname
);
1848 /* Save the ID in a lookup structure. */
1849 if (!rbt_insert (&bif_rbt
, bifs
[curr_bif
].idname
))
1851 diag (oldpos
, "duplicate function ID '%s'.\n", bifs
[curr_bif
].idname
);
1852 return PC_PARSEFAIL
;
1855 /* Append a number representing the order in which this function
1856 was encountered to its name, and save in another lookup
1858 int orig_len
= strlen (bifs
[curr_bif
].idname
);
1859 char *buf
= (char *) malloc (orig_len
+ 7);
1860 sprintf (buf
, "%s:%05d", bifs
[curr_bif
].idname
, curr_bif
);
1862 if (!rbt_insert (&bifo_rbt
, buf
))
1864 diag (pos
, "internal error inserting '%s' in bifo_rbt\n", buf
);
1865 return PC_PARSEFAIL
;
1868 /* Now the pattern name. */
1869 consume_whitespace ();
1870 bifs
[curr_bif
].patname
= match_identifier ();
1871 if (!bifs
[curr_bif
].patname
)
1873 diag (pos
, "missing pattern name.\n");
1874 return PC_PARSEFAIL
;
1878 diag (0, "pattern name is '%s'.\n", bifs
[curr_bif
].patname
);
1881 /* Process attributes. */
1882 return parse_bif_attrs (&bifs
[curr_bif
].attrs
);
1885 /* Parse one stanza of the input BIF file. linebuf already contains the
1886 first line to parse. */
1888 parse_bif_stanza (void)
1890 /* Parse the stanza header. */
1892 consume_whitespace ();
1894 if (linebuf
[pos
] != '[')
1896 diag (pos
, "ill-formed stanza header.\n");
1897 return PC_PARSEFAIL
;
1901 const char *stanza_name
= match_to_right_bracket ();
1904 diag (pos
, "no expression found in stanza header.\n");
1905 return PC_PARSEFAIL
;
1908 curr_bif_stanza
= stanza_name_to_stanza (stanza_name
);
1910 if (linebuf
[pos
] != ']')
1912 diag (pos
, "ill-formed stanza header.\n");
1913 return PC_PARSEFAIL
;
1917 consume_whitespace ();
1918 if (linebuf
[pos
] != '\n' && pos
!= LINELEN
- 1)
1920 diag (pos
, "garbage after stanza header.\n");
1921 return PC_PARSEFAIL
;
1924 parse_codes result
= PC_OK
;
1926 while (result
!= PC_EOSTANZA
)
1928 if (!advance_line (bif_file
))
1930 result
= parse_bif_entry ();
1931 if (result
== PC_PARSEFAIL
)
1932 return PC_PARSEFAIL
;
1938 /* Parse the built-in file. */
1944 if (!advance_line (bif_file
))
1948 result
= parse_bif_stanza ();
1949 while (result
== PC_OK
);
1951 if (result
== PC_EOFILE
)
1956 /* Callback function for create_bif_order. */
1957 void set_bif_order (char *str
)
1960 char *colon
= strchr (str
, ':');
1961 sscanf (++colon
, "%d", &num
);
1962 bif_order
[bif_index
++] = num
;
1965 /* Create a mapping from function IDs in their final order to the order
1966 they appear in the built-in function file. */
1968 create_bif_order (void)
1970 bif_order
= (int *) malloc ((curr_bif
+ 1) * sizeof (int));
1971 rbt_inorder_callback (&bifo_rbt
, bifo_rbt
.rbt_root
, set_bif_order
);
1974 /* Parse one two-line entry in the overload file. */
1976 parse_ovld_entry (void)
1978 /* Check for end of stanza. */
1980 consume_whitespace ();
1981 if (linebuf
[pos
] == '[')
1984 /* Allocate an entry in the overload table. */
1985 if (num_ovlds
>= MAXOVLDS
- 1)
1987 diag (pos
, "too many overloads.\n");
1988 return PC_PARSEFAIL
;
1991 curr_ovld
= num_ovlds
++;
1992 ovlds
[curr_ovld
].stanza
= curr_ovld_stanza
;
1994 if (parse_prototype (&ovlds
[curr_ovld
].proto
) == PC_PARSEFAIL
)
1995 return PC_PARSEFAIL
;
1997 if (ovlds
[curr_ovld
].proto
.nargs
> max_ovld_args
)
1998 max_ovld_args
= ovlds
[curr_ovld
].proto
.nargs
;
2000 /* Build a function type descriptor identifier from the return type
2001 and argument types, and store it if it does not already exist. */
2002 ovlds
[curr_ovld
].fndecl
= construct_fntype_id (&ovlds
[curr_ovld
].proto
);
2004 /* Now process line 2, which just contains the builtin id and an
2005 optional overload id. */
2006 if (!advance_line (ovld_file
))
2008 diag (0, "unexpected EOF.\n");
2013 consume_whitespace ();
2015 char *id
= match_identifier ();
2016 ovlds
[curr_ovld
].bif_id_name
= id
;
2017 ovlds
[curr_ovld
].ovld_id_name
= id
;
2020 diag (pos
, "missing overload id.\n");
2021 return PC_PARSEFAIL
;
2025 diag (pos
, "ID name is '%s'.\n", id
);
2028 /* The builtin id has to match one from the bif file. */
2029 if (!rbt_find (&bif_rbt
, id
))
2031 diag (pos
, "builtin ID '%s' not found in bif file.\n", id
);
2032 return PC_PARSEFAIL
;
2035 /* Check for an optional overload id. Usually we use the builtin
2036 function id for that purpose, but sometimes we need multiple
2037 overload entries for the same builtin id, and it needs to be unique. */
2038 consume_whitespace ();
2039 if (linebuf
[pos
] != '\n')
2041 id
= match_identifier ();
2042 ovlds
[curr_ovld
].ovld_id_name
= id
;
2043 consume_whitespace ();
2046 /* Save the overload ID in a lookup structure. */
2047 if (!rbt_insert (&ovld_rbt
, id
))
2049 diag (oldpos
, "duplicate overload ID '%s'.\n", id
);
2050 return PC_PARSEFAIL
;
2053 if (linebuf
[pos
] != '\n')
2055 diag (pos
, "garbage at end of line.\n");
2056 return PC_PARSEFAIL
;
2061 /* Parse one stanza of the input overload file. linebuf already contains the
2062 first line to parse. */
2064 parse_ovld_stanza (void)
2066 /* Parse the stanza header. */
2068 consume_whitespace ();
2070 if (linebuf
[pos
] != '[')
2072 diag (pos
, "ill-formed stanza header.\n");
2073 return PC_PARSEFAIL
;
2077 char *stanza_name
= match_identifier ();
2080 diag (pos
, "no identifier found in stanza header.\n");
2081 return PC_PARSEFAIL
;
2084 /* Add the identifier to a table and set the number to be recorded
2085 with subsequent overload entries. */
2086 if (num_ovld_stanzas
>= MAXOVLDSTANZAS
)
2088 diag (pos
, "too many stanza headers.\n");
2089 return PC_PARSEFAIL
;
2092 curr_ovld_stanza
= num_ovld_stanzas
++;
2093 ovld_stanza
*stanza
= &ovld_stanzas
[curr_ovld_stanza
];
2094 stanza
->stanza_id
= stanza_name
;
2096 consume_whitespace ();
2097 if (linebuf
[pos
] != ',')
2099 diag (pos
, "missing comma.\n");
2100 return PC_PARSEFAIL
;
2104 consume_whitespace ();
2105 stanza
->extern_name
= match_identifier ();
2106 if (!stanza
->extern_name
)
2108 diag (pos
, "missing external name.\n");
2109 return PC_PARSEFAIL
;
2112 consume_whitespace ();
2113 if (linebuf
[pos
] != ',')
2115 diag (pos
, "missing comma.\n");
2116 return PC_PARSEFAIL
;
2120 consume_whitespace ();
2121 stanza
->intern_name
= match_identifier ();
2122 if (!stanza
->intern_name
)
2124 diag (pos
, "missing internal name.\n");
2125 return PC_PARSEFAIL
;
2128 consume_whitespace ();
2129 if (linebuf
[pos
] == ',')
2132 consume_whitespace ();
2133 stanza
->ifdef
= match_identifier ();
2136 diag (pos
, "missing ifdef token.\n");
2137 return PC_PARSEFAIL
;
2139 consume_whitespace ();
2144 if (linebuf
[pos
] != ']')
2146 diag (pos
, "ill-formed stanza header.\n");
2147 return PC_PARSEFAIL
;
2151 consume_whitespace ();
2152 if (linebuf
[pos
] != '\n' && pos
!= LINELEN
- 1)
2154 diag (pos
, "garbage after stanza header.\n");
2155 return PC_PARSEFAIL
;
2158 parse_codes result
= PC_OK
;
2160 while (result
!= PC_EOSTANZA
)
2162 if (!advance_line (ovld_file
))
2165 result
= parse_ovld_entry ();
2166 if (result
== PC_EOFILE
|| result
== PC_PARSEFAIL
)
2173 /* Parse the overload file. */
2177 parse_codes result
= PC_OK
;
2180 if (!advance_line (ovld_file
))
2183 while (result
== PC_OK
)
2184 result
= parse_ovld_stanza ();
2186 if (result
== PC_EOFILE
)
2191 /* Write a comment at the top of FILE about how the code was generated. */
2193 write_autogenerated_header (FILE *file
)
2195 fprintf (file
, "/* Automatically generated by the program '%s'\n",
2197 fprintf (file
, " from the files '%s' and '%s'. */\n\n",
2198 bif_path
, ovld_path
);
2201 /* Write declarations into the header file. */
2205 fprintf (header_file
, "enum rs6000_gen_builtins\n{\n RS6000_BIF_NONE,\n");
2206 for (int i
= 0; i
<= curr_bif
; i
++)
2207 fprintf (header_file
, " RS6000_BIF_%s,\n", bifs
[bif_order
[i
]].idname
);
2208 fprintf (header_file
, " RS6000_BIF_MAX,\n");
2209 fprintf (header_file
, " RS6000_OVLD_NONE,\n");
2210 for (int i
= 0; i
< num_ovld_stanzas
; i
++)
2211 fprintf (header_file
, " RS6000_OVLD_%s,\n", ovld_stanzas
[i
].stanza_id
);
2212 fprintf (header_file
, " RS6000_OVLD_MAX\n};\n\n");
2214 fprintf (header_file
,
2215 "extern GTY(()) tree rs6000_builtin_decls[RS6000_OVLD_MAX];\n\n");
2217 fprintf (header_file
,
2218 "enum rs6000_ovld_instances\n{\n RS6000_INST_NONE,\n");
2219 for (int i
= 0; i
<= curr_ovld
; i
++)
2220 fprintf (header_file
, " RS6000_INST_%s,\n", ovlds
[i
].ovld_id_name
);
2221 fprintf (header_file
, " RS6000_INST_MAX\n};\n\n");
2223 fprintf (header_file
, "#define MAX_OVLD_ARGS %d\n", max_ovld_args
);
2225 fprintf (header_file
, "enum restriction {\n");
2226 fprintf (header_file
, " RES_NONE,\n");
2227 fprintf (header_file
, " RES_BITS,\n");
2228 fprintf (header_file
, " RES_RANGE,\n");
2229 fprintf (header_file
, " RES_VAR_RANGE,\n");
2230 fprintf (header_file
, " RES_VALUES\n");
2231 fprintf (header_file
, "};\n\n");
2233 fprintf (header_file
, "enum bif_enable {\n");
2234 fprintf (header_file
, " ENB_ALWAYS,\n");
2235 fprintf (header_file
, " ENB_P5,\n");
2236 fprintf (header_file
, " ENB_P6,\n");
2237 fprintf (header_file
, " ENB_P6_64,\n");
2238 fprintf (header_file
, " ENB_ALTIVEC,\n");
2239 fprintf (header_file
, " ENB_CELL,\n");
2240 fprintf (header_file
, " ENB_VSX,\n");
2241 fprintf (header_file
, " ENB_P7,\n");
2242 fprintf (header_file
, " ENB_P7_64,\n");
2243 fprintf (header_file
, " ENB_P8,\n");
2244 fprintf (header_file
, " ENB_P8V,\n");
2245 fprintf (header_file
, " ENB_P9,\n");
2246 fprintf (header_file
, " ENB_P9_64,\n");
2247 fprintf (header_file
, " ENB_P9V,\n");
2248 fprintf (header_file
, " ENB_IEEE128_HW,\n");
2249 fprintf (header_file
, " ENB_DFP,\n");
2250 fprintf (header_file
, " ENB_CRYPTO,\n");
2251 fprintf (header_file
, " ENB_HTM,\n");
2252 fprintf (header_file
, " ENB_P10,\n");
2253 fprintf (header_file
, " ENB_P10_64,\n");
2254 fprintf (header_file
, " ENB_MMA\n");
2255 fprintf (header_file
, "};\n\n");
2257 fprintf (header_file
, "#define PPC_MAXRESTROPNDS 3\n");
2258 fprintf (header_file
, "struct GTY((user)) bifdata\n");
2259 fprintf (header_file
, "{\n");
2260 fprintf (header_file
, " const char *bifname;\n");
2261 fprintf (header_file
, " bif_enable enable;\n");
2262 fprintf (header_file
, " tree fntype;\n");
2263 fprintf (header_file
, " insn_code icode;\n");
2264 fprintf (header_file
, " int nargs;\n");
2265 fprintf (header_file
, " int bifattrs;\n");
2266 fprintf (header_file
, " int restr_opnd[PPC_MAXRESTROPNDS];\n");
2267 fprintf (header_file
, " restriction restr[PPC_MAXRESTROPNDS];\n");
2268 fprintf (header_file
, " int restr_val1[PPC_MAXRESTROPNDS];\n");
2269 fprintf (header_file
, " int restr_val2[PPC_MAXRESTROPNDS];\n");
2270 fprintf (header_file
, " const char *attr_string;\n");
2271 fprintf (header_file
, " rs6000_gen_builtins assoc_bif;\n");
2272 fprintf (header_file
, "};\n\n");
2274 fprintf (header_file
, "#define bif_init_bit\t\t(0x00000001)\n");
2275 fprintf (header_file
, "#define bif_set_bit\t\t(0x00000002)\n");
2276 fprintf (header_file
, "#define bif_extract_bit\t\t(0x00000004)\n");
2277 fprintf (header_file
, "#define bif_nosoft_bit\t\t(0x00000008)\n");
2278 fprintf (header_file
, "#define bif_ldvec_bit\t\t(0x00000010)\n");
2279 fprintf (header_file
, "#define bif_stvec_bit\t\t(0x00000020)\n");
2280 fprintf (header_file
, "#define bif_reve_bit\t\t(0x00000040)\n");
2281 fprintf (header_file
, "#define bif_pred_bit\t\t(0x00000080)\n");
2282 fprintf (header_file
, "#define bif_htm_bit\t\t(0x00000100)\n");
2283 fprintf (header_file
, "#define bif_htmspr_bit\t\t(0x00000200)\n");
2284 fprintf (header_file
, "#define bif_htmcr_bit\t\t(0x00000400)\n");
2285 fprintf (header_file
, "#define bif_mma_bit\t\t(0x00000800)\n");
2286 fprintf (header_file
, "#define bif_quad_bit\t\t(0x00001000)\n");
2287 fprintf (header_file
, "#define bif_pair_bit\t\t(0x00002000)\n");
2288 fprintf (header_file
, "#define bif_mmaint_bit\t\t(0x00004000)\n");
2289 fprintf (header_file
, "#define bif_no32bit_bit\t\t(0x00008000)\n");
2290 fprintf (header_file
, "#define bif_32bit_bit\t\t(0x00010000)\n");
2291 fprintf (header_file
, "#define bif_cpu_bit\t\t(0x00020000)\n");
2292 fprintf (header_file
, "#define bif_ldstmask_bit\t(0x00040000)\n");
2293 fprintf (header_file
, "#define bif_lxvrse_bit\t\t(0x00080000)\n");
2294 fprintf (header_file
, "#define bif_lxvrze_bit\t\t(0x00100000)\n");
2295 fprintf (header_file
, "#define bif_endian_bit\t\t(0x00200000)\n");
2296 fprintf (header_file
, "#define bif_ibmld_bit\t\t(0x00400000)\n");
2297 fprintf (header_file
, "\n");
2298 fprintf (header_file
,
2299 "#define bif_is_init(x)\t\t((x).bifattrs & bif_init_bit)\n");
2300 fprintf (header_file
,
2301 "#define bif_is_set(x)\t\t((x).bifattrs & bif_set_bit)\n");
2302 fprintf (header_file
,
2303 "#define bif_is_extract(x)\t((x).bifattrs & bif_extract_bit)\n");
2304 fprintf (header_file
,
2305 "#define bif_is_nosoft(x)\t((x).bifattrs & bif_nosoft_bit)\n");
2306 fprintf (header_file
,
2307 "#define bif_is_ldvec(x)\t\t((x).bifattrs & bif_ldvec_bit)\n");
2308 fprintf (header_file
,
2309 "#define bif_is_stvec(x)\t\t((x).bifattrs & bif_stvec_bit)\n");
2310 fprintf (header_file
,
2311 "#define bif_is_reve(x)\t\t((x).bifattrs & bif_reve_bit)\n");
2312 fprintf (header_file
,
2313 "#define bif_is_predicate(x)\t((x).bifattrs & bif_pred_bit)\n");
2314 fprintf (header_file
,
2315 "#define bif_is_htm(x)\t\t((x).bifattrs & bif_htm_bit)\n");
2316 fprintf (header_file
,
2317 "#define bif_is_htmspr(x)\t((x).bifattrs & bif_htmspr_bit)\n");
2318 fprintf (header_file
,
2319 "#define bif_is_htmcr(x)\t\t((x).bifattrs & bif_htmcr_bit)\n");
2320 fprintf (header_file
,
2321 "#define bif_is_mma(x)\t\t((x).bifattrs & bif_mma_bit)\n");
2322 fprintf (header_file
,
2323 "#define bif_is_quad(x)\t\t((x).bifattrs & bif_quad_bit)\n");
2324 fprintf (header_file
,
2325 "#define bif_is_pair(x)\t\t((x).bifattrs & bif_pair_bit)\n");
2326 fprintf (header_file
,
2327 "#define bif_is_mmaint(x)\t\t((x).bifattrs & bif_mmaint_bit)\n");
2328 fprintf (header_file
,
2329 "#define bif_is_no32bit(x)\t((x).bifattrs & bif_no32bit_bit)\n");
2330 fprintf (header_file
,
2331 "#define bif_is_32bit(x)\t((x).bifattrs & bif_32bit_bit)\n");
2332 fprintf (header_file
,
2333 "#define bif_is_cpu(x)\t\t((x).bifattrs & bif_cpu_bit)\n");
2334 fprintf (header_file
,
2335 "#define bif_is_ldstmask(x)\t((x).bifattrs & bif_ldstmask_bit)\n");
2336 fprintf (header_file
,
2337 "#define bif_is_lxvrse(x)\t((x).bifattrs & bif_lxvrse_bit)\n");
2338 fprintf (header_file
,
2339 "#define bif_is_lxvrze(x)\t((x).bifattrs & bif_lxvrze_bit)\n");
2340 fprintf (header_file
,
2341 "#define bif_is_endian(x)\t((x).bifattrs & bif_endian_bit)\n");
2342 fprintf (header_file
,
2343 "#define bif_is_ibmld(x)\t((x).bifattrs & bif_ibmld_bit)\n");
2344 fprintf (header_file
, "\n");
2346 /* #### Cannot mark this as a GC root because only pointer types can
2347 be marked as GTY((user)) and be GC roots. All trees in here are
2348 kept alive by other globals, so not a big deal. Alternatively,
2349 we could change the enum fields to ints and cast them in and out
2350 to avoid requiring a GTY((user)) designation, but that seems
2351 unnecessarily gross. */
2352 fprintf (header_file
,
2353 "extern bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n");
2355 fprintf (header_file
, "struct GTY((user)) ovlddata\n");
2356 fprintf (header_file
, "{\n");
2357 fprintf (header_file
, " const char *bifname;\n");
2358 fprintf (header_file
, " rs6000_gen_builtins bifid;\n");
2359 fprintf (header_file
, " tree fntype;\n");
2360 fprintf (header_file
, " ovlddata *next;\n");
2361 fprintf (header_file
, "};\n\n");
2363 fprintf (header_file
, "struct ovldrecord\n");
2364 fprintf (header_file
, "{\n");
2365 fprintf (header_file
, " const char *ovld_name;\n");
2366 fprintf (header_file
, " ovlddata *first_instance;\n");
2367 fprintf (header_file
, "};\n\n");
2369 fprintf (header_file
,
2370 "/* #### Cannot mark this as a GC root because only pointer\n"
2371 " types can be marked as GTY((user)) and be GC roots. All\n"
2372 " trees in here are kept alive by other globals, so not a big\n"
2373 " deal. Alternatively, we could change the enum fields to ints\n"
2374 " and cast them in and out to avoid requiring a GTY((user))\n"
2375 " designation, but that seems unnecessarily gross. */\n");
2376 fprintf (header_file
,
2377 "extern ovlddata rs6000_instance_info[RS6000_INST_MAX];\n");
2378 fprintf (header_file
, "extern ovldrecord rs6000_overload_info[];\n\n");
2380 fprintf (header_file
, "extern void rs6000_init_generated_builtins ();\n\n");
2381 fprintf (header_file
,
2382 "extern bool rs6000_builtin_is_supported (rs6000_gen_builtins);\n");
2383 fprintf (header_file
,
2384 "extern tree rs6000_builtin_decl (unsigned, "
2385 "bool ATTRIBUTE_UNUSED);\n\n");
2386 fprintf (header_file
,
2387 "extern void gt_ggc_mx (bifdata *bd);\n");
2388 fprintf (header_file
,
2389 "extern void gt_pch_nx (bifdata *bd);\n");
2390 fprintf (header_file
,
2391 "extern void gt_pch_nx (bifdata *bd, gt_pointer_operator op, "
2392 "void *cookie);\n");
2393 fprintf (header_file
,
2394 "extern void gt_ggc_mx (ovlddata *od);\n");
2395 fprintf (header_file
,
2396 "extern void gt_pch_nx (ovlddata *od);\n");
2397 fprintf (header_file
,
2398 "extern void gt_pch_nx (ovlddata *od, gt_pointer_operator op, "
2399 "void *cookie);\n");
2402 /* Callback functions used for generating trees for function types. */
2404 write_extern_fntype (char *str
)
2406 fprintf (header_file
, "extern GTY(()) tree %s;\n", str
);
2410 write_fntype (char *str
)
2412 fprintf (init_file
, "tree %s;\n", str
);
2415 /* Comparator for bsearch on the type map. */
2417 typemap_cmp (const void *key
, const void *entry
)
2419 return strcmp ((const char *)key
, ((const typemap
*)entry
)->key
);
2422 /* Write the type node corresponding to TOK. */
2424 write_type_node (char *tok
, bool indent
)
2427 fprintf (init_file
, " ");
2428 typemap
*entry
= (typemap
*) bsearch (tok
, type_map
, TYPE_MAP_SIZE
,
2429 sizeof (typemap
), typemap_cmp
);
2431 fatal ("Type map is inconsistent.");
2432 fprintf (init_file
, "%s_type_node", entry
->value
);
2435 /* Write an initializer for a function type identified by STR. */
2437 write_fntype_init (char *str
)
2441 /* Check whether we have a "tf" token in this string, representing
2442 a float128_type_node. It's possible that float128_type_node is
2443 undefined (occurs for -maltivec -mno-vsx, for example), so we
2444 must guard against that. */
2445 int tf_found
= strstr (str
, "tf") != NULL
;
2447 /* Similarly, look for decimal float tokens. */
2448 int dfp_found
= (strstr (str
, "dd") != NULL
2449 || strstr (str
, "td") != NULL
2450 || strstr (str
, "sd") != NULL
);
2452 /* Avoid side effects of strtok on the original string by using a copy. */
2453 char *buf
= strdup (str
);
2456 fprintf (init_file
, " if (float128_type_node)\n ");
2458 fprintf (init_file
, " if (dfloat64_type_node)\n ");
2460 fprintf (init_file
, " %s\n = build_function_type_list (", buf
);
2461 tok
= strtok (buf
, "_");
2462 write_type_node (tok
, tf_found
|| dfp_found
);
2463 tok
= strtok (0, "_");
2465 assert (!strcmp (tok
, "ftype"));
2467 tok
= strtok (0, "_");
2469 fprintf (init_file
, ",\n\t\t\t\t");
2471 /* Note: A function with no arguments ends with '_ftype_v'. */
2472 while (tok
&& strcmp (tok
, "v"))
2474 write_type_node (tok
, tf_found
|| dfp_found
);
2475 tok
= strtok (0, "_");
2476 fprintf (init_file
, ",\n\t\t\t\t");
2478 fprintf (init_file
, "NULL_TREE);\n");
2482 /* Write everything to the header file (rs6000-builtins.h). Return
2483 1 if successful, 0 otherwise. */
2485 write_header_file (void)
2487 write_autogenerated_header (header_file
);
2489 fprintf (header_file
, "#ifndef _RS6000_BUILTINS_H\n");
2490 fprintf (header_file
, "#define _RS6000_BUILTINS_H 1\n\n");
2494 /* Write function type list declarators to the header file. */
2495 rbt_inorder_callback (&fntype_rbt
, fntype_rbt
.rbt_root
, write_extern_fntype
);
2496 fprintf (header_file
, "\n");
2497 fprintf (header_file
, "\n#endif\n");
2502 /* Write the decl and initializer for rs6000_builtin_info[]. */
2504 write_bif_static_init (void)
2507 fprintf (init_file
, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n");
2508 fprintf (init_file
, " {\n");
2509 fprintf (init_file
, " { /* RS6000_BIF_NONE: */\n");
2510 fprintf (init_file
, " \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n");
2511 fprintf (init_file
, " 0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n");
2512 fprintf (init_file
, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n");
2513 fprintf (init_file
, " },\n");
2514 for (int i
= 0; i
<= curr_bif
; i
++)
2516 bifdata
*bifp
= &bifs
[bif_order
[i
]];
2517 fprintf (init_file
, " { /* RS6000_BIF_%s: */\n", bifp
->idname
);
2518 fprintf (init_file
, " /* bifname */\t\"%s\",\n",
2519 bifp
->proto
.bifname
);
2520 fprintf (init_file
, " /* enable*/\t%s,\n",
2521 enable_string
[bifp
->stanza
]);
2522 /* Type must be instantiated at run time. */
2523 fprintf (init_file
, " /* fntype */\t0,\n");
2524 fprintf (init_file
, " /* icode */\tCODE_FOR_%s,\n",
2526 fprintf (init_file
, " /* nargs */\t%d,\n",
2528 fprintf (init_file
, " /* bifattrs */\t0");
2529 if (bifp
->attrs
.isinit
)
2530 fprintf (init_file
, " | bif_init_bit");
2531 if (bifp
->attrs
.isset
)
2532 fprintf (init_file
, " | bif_set_bit");
2533 if (bifp
->attrs
.isextract
)
2534 fprintf (init_file
, " | bif_extract_bit");
2535 if (bifp
->attrs
.isnosoft
)
2536 fprintf (init_file
, " | bif_nosoft_bit");
2537 if (bifp
->attrs
.isldvec
)
2538 fprintf (init_file
, " | bif_ldvec_bit");
2539 if (bifp
->attrs
.isstvec
)
2540 fprintf (init_file
, " | bif_stvec_bit");
2541 if (bifp
->attrs
.isreve
)
2542 fprintf (init_file
, " | bif_reve_bit");
2543 if (bifp
->attrs
.ispred
)
2544 fprintf (init_file
, " | bif_pred_bit");
2545 if (bifp
->attrs
.ishtm
)
2546 fprintf (init_file
, " | bif_htm_bit");
2547 if (bifp
->attrs
.ishtmspr
)
2548 fprintf (init_file
, " | bif_htmspr_bit");
2549 if (bifp
->attrs
.ishtmcr
)
2550 fprintf (init_file
, " | bif_htmcr_bit");
2551 if (bifp
->attrs
.ismma
)
2552 fprintf (init_file
, " | bif_mma_bit");
2553 if (bifp
->attrs
.isquad
)
2554 fprintf (init_file
, " | bif_quad_bit");
2555 if (bifp
->attrs
.ispair
)
2556 fprintf (init_file
, " | bif_pair_bit");
2557 if (bifp
->attrs
.ismmaint
)
2558 fprintf (init_file
, " | bif_mmaint_bit");
2559 if (bifp
->attrs
.isno32bit
)
2560 fprintf (init_file
, " | bif_no32bit_bit");
2561 if (bifp
->attrs
.is32bit
)
2562 fprintf (init_file
, " | bif_32bit_bit");
2563 if (bifp
->attrs
.iscpu
)
2564 fprintf (init_file
, " | bif_cpu_bit");
2565 if (bifp
->attrs
.isldstmask
)
2566 fprintf (init_file
, " | bif_ldstmask_bit");
2567 if (bifp
->attrs
.islxvrse
)
2568 fprintf (init_file
, " | bif_lxvrse_bit");
2569 if (bifp
->attrs
.islxvrze
)
2570 fprintf (init_file
, " | bif_lxvrze_bit");
2571 if (bifp
->attrs
.isendian
)
2572 fprintf (init_file
, " | bif_endian_bit");
2573 if (bifp
->attrs
.isibmld
)
2574 fprintf (init_file
, " | bif_ibmld_bit");
2575 fprintf (init_file
, ",\n");
2576 fprintf (init_file
, " /* restr_opnd */\t{%d, %d, %d},\n",
2577 bifp
->proto
.restr_opnd
[0], bifp
->proto
.restr_opnd
[1],
2578 bifp
->proto
.restr_opnd
[2]);
2579 for (int j
= 0; j
< 3; j
++)
2580 if (!bifp
->proto
.restr_opnd
[j
])
2581 res
[j
] = "RES_NONE";
2582 else if (bifp
->proto
.restr
[j
] == RES_BITS
)
2583 res
[j
] = "RES_BITS";
2584 else if (bifp
->proto
.restr
[j
] == RES_RANGE
)
2585 res
[j
] = "RES_RANGE";
2586 else if (bifp
->proto
.restr
[j
] == RES_VALUES
)
2587 res
[j
] = "RES_VALUES";
2588 else if (bifp
->proto
.restr
[j
] == RES_VAR_RANGE
)
2589 res
[j
] = "RES_VAR_RANGE";
2592 fprintf (init_file
, " /* restr */\t{%s, %s, %s},\n",
2593 res
[0], res
[1], res
[2]);
2594 fprintf (init_file
, " /* restr_val1 */\t{%s, %s, %s},\n",
2595 bifp
->proto
.restr_val1
[0] ? bifp
->proto
.restr_val1
[0] : "0",
2596 bifp
->proto
.restr_val1
[1] ? bifp
->proto
.restr_val1
[1] : "0",
2597 bifp
->proto
.restr_val1
[2] ? bifp
->proto
.restr_val1
[2] : "0");
2598 fprintf (init_file
, " /* restr_val2 */\t{%s, %s, %s},\n",
2599 bifp
->proto
.restr_val2
[0] ? bifp
->proto
.restr_val2
[0] : "0",
2600 bifp
->proto
.restr_val2
[1] ? bifp
->proto
.restr_val2
[1] : "0",
2601 bifp
->proto
.restr_val2
[2] ? bifp
->proto
.restr_val2
[2] : "0");
2602 fprintf (init_file
, " /* attr_string */\t\"%s\",\n",
2603 (bifp
->kind
== FNK_CONST
? "= const"
2604 : (bifp
->kind
== FNK_PURE
? "= pure"
2605 : (bifp
->kind
== FNK_FPMATH
? "= fp, const"
2607 fprintf (init_file
, " /* assoc_bif */\tRS6000_BIF_%s%s\n",
2608 bifp
->attrs
.ismmaint
? bifp
->idname
: "NONE",
2609 bifp
->attrs
.ismmaint
? "_INTERNAL" : "");
2610 fprintf (init_file
, " },\n");
2612 fprintf (init_file
, " };\n\n");
2615 /* Write the decls and initializers for rs6000_overload_info[] and
2616 rs6000_instance_info[]. */
2618 write_ovld_static_init (void)
2621 "ovldrecord rs6000_overload_info[RS6000_OVLD_MAX "
2622 "- RS6000_OVLD_NONE] =\n");
2623 fprintf (init_file
, " {\n");
2624 fprintf (init_file
, " { /* RS6000_OVLD_NONE: */\n");
2625 fprintf (init_file
, " \"\", NULL\n");
2626 fprintf (init_file
, " },\n");
2627 for (int i
= 0; i
<= curr_ovld_stanza
; i
++)
2629 fprintf (init_file
, " { /* RS6000_OVLD_%s: */\n",
2630 ovld_stanzas
[i
].stanza_id
);
2631 fprintf (init_file
, " /* ovld_name */\t\"%s\",\n",
2632 ovld_stanzas
[i
].intern_name
);
2633 /* First-instance must currently be instantiated at run time. */
2634 fprintf (init_file
, " /* first_instance */\tNULL\n");
2635 fprintf (init_file
, " },\n");
2637 fprintf (init_file
, " };\n\n");
2639 fprintf (init_file
, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n");
2640 fprintf (init_file
, " {\n");
2641 fprintf (init_file
, " { /* RS6000_INST_NONE: */\n");
2642 fprintf (init_file
, " \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n");
2643 fprintf (init_file
, " },\n");
2644 for (int i
= 0; i
<= curr_ovld
; i
++)
2646 fprintf (init_file
, " { /* RS6000_INST_%s: */\n",
2647 ovlds
[i
].ovld_id_name
);
2648 fprintf (init_file
, " /* bifname */\t\"%s\",\n",
2649 ovlds
[i
].proto
.bifname
);
2650 fprintf (init_file
, " /* bifid */\tRS6000_BIF_%s,\n",
2651 ovlds
[i
].bif_id_name
);
2652 /* Type must be instantiated at run time. */
2653 fprintf (init_file
, " /* fntype */\t0,\n");
2654 fprintf (init_file
, " /* next */\t");
2656 && !strcmp (ovlds
[i
+1].proto
.bifname
, ovlds
[i
].proto
.bifname
))
2658 "&rs6000_instance_info[RS6000_INST_%s]\n",
2659 ovlds
[i
+1].ovld_id_name
);
2661 fprintf (init_file
, "NULL\n");
2662 fprintf (init_file
, " },\n");
2664 fprintf (init_file
, " };\n\n");
2667 /* Write code to initialize the built-in function table. */
2669 write_init_bif_table (void)
2671 for (int i
= 0; i
<= curr_bif
; i
++)
2674 " rs6000_builtin_info[RS6000_BIF_%s].fntype"
2676 bifs
[i
].idname
, bifs
[i
].fndecl
);
2678 /* Check whether we have a "tf" token in this string, representing
2679 a float128_type_node. It's possible that float128_type_node is
2680 undefined (occurs for -maltivec -mno-vsx, for example), so we
2681 must guard against that. */
2682 int tf_found
= strstr (bifs
[i
].fndecl
, "tf") != NULL
;
2684 /* Similarly, look for decimal float tokens. */
2685 int dfp_found
= (strstr (bifs
[i
].fndecl
, "sd") != NULL
2686 || strstr (bifs
[i
].fndecl
, "dd") != NULL
2687 || strstr (bifs
[i
].fndecl
, "td") != NULL
);
2691 fprintf (init_file
, " if (float128_type_node)\n");
2692 fprintf (init_file
, " {\n");
2696 fprintf (init_file
, " if (dfloat64_type_node)\n");
2697 fprintf (init_file
, " {\n");
2701 " rs6000_builtin_decls[(int)RS6000_BIF_%s] = t\n",
2704 " = add_builtin_function (\"%s\",\n",
2705 bifs
[i
].proto
.bifname
);
2710 " (int)RS6000_BIF_%s,"
2714 " NULL, NULL_TREE);\n");
2715 if (bifs
[i
].kind
== FNK_CONST
)
2717 fprintf (init_file
, " TREE_READONLY (t) = 1;\n");
2718 fprintf (init_file
, " TREE_NOTHROW (t) = 1;\n");
2720 else if (bifs
[i
].kind
== FNK_PURE
)
2722 fprintf (init_file
, " DECL_PURE_P (t) = 1;\n");
2723 fprintf (init_file
, " TREE_NOTHROW (t) = 1;\n");
2725 else if (bifs
[i
].kind
== FNK_FPMATH
)
2727 fprintf (init_file
, " TREE_NOTHROW (t) = 1;\n");
2728 fprintf (init_file
, " if (flag_rounding_math)\n");
2729 fprintf (init_file
, " {\n");
2730 fprintf (init_file
, " DECL_PURE_P (t) = 1;\n");
2731 fprintf (init_file
, " DECL_IS_NOVOPS (t) = 1;\n");
2732 fprintf (init_file
, " }\n");
2733 fprintf (init_file
, " else\n");
2734 fprintf (init_file
, " TREE_READONLY (t) = 1;\n");
2737 if (tf_found
|| dfp_found
)
2739 fprintf (init_file
, " }\n");
2740 fprintf (init_file
, " else\n");
2741 fprintf (init_file
, " {\n");
2742 fprintf (init_file
, " rs6000_builtin_decls"
2743 "[(int)RS6000_BIF_%s] = NULL_TREE;\n", bifs
[i
].idname
);
2744 fprintf (init_file
, " }\n");
2746 fprintf (init_file
, "\n");
2750 /* Write code to initialize the overload table. */
2752 write_init_ovld_table (void)
2754 fprintf (init_file
, " int base = RS6000_OVLD_NONE;\n\n");
2756 " /* The fndecl for an overload is arbitrarily the first one\n"
2757 " for the overload. We sort out the real types when\n"
2758 " processing the overload in the gcc front end. */\n");
2760 for (int i
= 0; i
<= curr_ovld
; i
++)
2763 " rs6000_instance_info[RS6000_INST_%s].fntype"
2765 ovlds
[i
].ovld_id_name
, ovlds
[i
].fndecl
);
2767 if (i
== 0 || ovlds
[i
].stanza
!= ovlds
[i
-1].stanza
)
2769 ovld_stanza
*stanza
= &ovld_stanzas
[ovlds
[i
].stanza
];
2770 fprintf (init_file
, "\n");
2772 /* Check whether we have a "tf" token in this string, representing
2773 a float128_type_node. It's possible that float128_type_node is
2774 undefined (occurs for -maltivec -mno-vsx, for example), so we
2775 must guard against that. */
2776 int tf_found
= strstr (ovlds
[i
].fndecl
, "tf") != NULL
;
2778 /* Similarly, look for decimal float tokens. */
2779 int dfp_found
= (strstr (ovlds
[i
].fndecl
, "sd") != NULL
2780 || strstr (ovlds
[i
].fndecl
, "dd") != NULL
2781 || strstr (ovlds
[i
].fndecl
, "td") != NULL
);
2785 fprintf (init_file
, " if (float128_type_node)\n");
2786 fprintf (init_file
, " {\n");
2790 fprintf (init_file
, " if (dfloat64_type_node)\n");
2791 fprintf (init_file
, " {\n");
2795 " rs6000_builtin_decls[(int)RS6000_OVLD_%s] = t\n",
2798 " = add_builtin_function (\"%s\",\n",
2799 stanza
->intern_name
);
2804 " (int)RS6000_OVLD_%s,"
2808 " NULL, NULL_TREE);\n");
2810 if (tf_found
|| dfp_found
)
2811 fprintf (init_file
, " }\n");
2813 fprintf (init_file
, "\n");
2816 " rs6000_overload_info[RS6000_OVLD_%s - base]"
2817 ".first_instance\n",
2820 " = &rs6000_instance_info[RS6000_INST_%s];\n\n",
2821 ovlds
[i
].ovld_id_name
);
2826 /* Write everything to the initialization file (rs6000-builtins.c).
2827 Return 1 if successful, 0 otherwise. */
2829 write_init_file (void)
2831 write_autogenerated_header (init_file
);
2833 fprintf (init_file
, "#include \"config.h\"\n");
2834 fprintf (init_file
, "#include \"system.h\"\n");
2835 fprintf (init_file
, "#include \"coretypes.h\"\n");
2836 fprintf (init_file
, "#include \"backend.h\"\n");
2837 fprintf (init_file
, "#include \"rtl.h\"\n");
2838 fprintf (init_file
, "#include \"tree.h\"\n");
2839 fprintf (init_file
, "#include \"langhooks.h\"\n");
2840 fprintf (init_file
, "#include \"insn-codes.h\"\n");
2841 fprintf (init_file
, "#include \"rs6000-builtins.h\"\n");
2842 fprintf (init_file
, "\n");
2844 fprintf (init_file
, "tree rs6000_builtin_decls[RS6000_OVLD_MAX];\n\n");
2846 write_bif_static_init ();
2847 write_ovld_static_init ();
2849 rbt_inorder_callback (&fntype_rbt
, fntype_rbt
.rbt_root
, write_fntype
);
2850 fprintf (init_file
, "\n");
2852 fprintf (init_file
, "void\n");
2853 fprintf (init_file
, "rs6000_init_generated_builtins ()\n");
2854 fprintf (init_file
, "{\n");
2855 fprintf (init_file
, " tree t;\n");
2856 rbt_inorder_callback (&fntype_rbt
, fntype_rbt
.rbt_root
, write_fntype_init
);
2857 fprintf (init_file
, "\n");
2860 " rs6000_builtin_decls[RS6000_BIF_NONE] = NULL_TREE;\n");
2862 " rs6000_builtin_decls[RS6000_BIF_MAX] = NULL_TREE;\n");
2864 " rs6000_builtin_decls[RS6000_OVLD_NONE] = NULL_TREE;\n\n");
2866 write_init_bif_table ();
2867 write_init_ovld_table ();
2869 fprintf (init_file
, "}\n\n");
2872 "void gt_ggc_mx (bifdata *bd)\n");
2874 "{\n gt_ggc_mx (bd->fntype);\n}\n\n");
2876 "void gt_pch_nx (bifdata *bd)\n");
2878 "{\n gt_pch_nx (bd->fntype);\n}\n\n");
2880 "void gt_pch_nx (bifdata *bd, gt_pointer_operator op, "
2883 "{\n op(&(bd->fntype), NULL, cookie);\n}\n\n");
2885 "void gt_ggc_mx (ovlddata *od)\n");
2887 "{\n gt_ggc_mx (od->fntype);\n}\n\n");
2889 "void gt_pch_nx (ovlddata *od)\n");
2891 "{\n gt_pch_nx (od->fntype);\n}\n\n");
2893 "void gt_pch_nx (ovlddata *od, gt_pointer_operator op, "
2896 "{\n op(&(od->fntype), NULL, cookie);\n}\n");
2901 /* Write everything to the include file (rs6000-vecdefines.h).
2902 Return 1 if successful, 0 otherwise. */
2904 write_defines_file (void)
2906 fprintf (defines_file
, "#ifndef _RS6000_VECDEFINES_H\n");
2907 fprintf (defines_file
, "#define _RS6000_VECDEFINES_H 1\n\n");
2908 fprintf (defines_file
, "#if defined(_ARCH_PPC64) && defined (_ARCH_PWR9)\n");
2909 fprintf (defines_file
, " #define _ARCH_PPC64_PWR9 1\n");
2910 fprintf (defines_file
, "#endif\n\n");
2911 for (int i
= 0; i
< num_ovld_stanzas
; i
++)
2912 if (strcmp (ovld_stanzas
[i
].extern_name
, "SKIP"))
2914 if (ovld_stanzas
[i
].ifdef
)
2915 fprintf (defines_file
, "#ifdef %s\n", ovld_stanzas
[i
].ifdef
);
2916 fprintf (defines_file
, "#define %s %s\n",
2917 ovld_stanzas
[i
].extern_name
,
2918 ovld_stanzas
[i
].intern_name
);
2919 if (ovld_stanzas
[i
].ifdef
)
2920 fprintf (defines_file
, "#endif\n");
2922 fprintf (defines_file
, "\n#endif\n");
2926 /* Close and delete output files after any failure, so that subsequent
2927 build dependencies will fail. */
2929 delete_output_files (void)
2931 /* Depending on whence we're called, some of these may already be
2932 closed. Don't check for errors. */
2933 fclose (header_file
);
2935 fclose (defines_file
);
2937 remove (header_path
);
2939 remove (defines_path
);
2942 /* Main program to convert flat files into built-in initialization code. */
2944 main (int argc
, const char **argv
)
2949 "Five arguments required: two input files and three output "
2956 ovld_path
= argv
[2];
2957 header_path
= argv
[3];
2958 init_path
= argv
[4];
2959 defines_path
= argv
[5];
2961 bif_file
= fopen (bif_path
, "r");
2964 fprintf (stderr
, "Cannot open input built-in file '%s'.\n", bif_path
);
2967 ovld_file
= fopen (ovld_path
, "r");
2970 fprintf (stderr
, "Cannot open input overload file '%s'.\n", ovld_path
);
2973 header_file
= fopen (header_path
, "w");
2976 fprintf (stderr
, "Cannot open header file '%s' for output.\n",
2980 init_file
= fopen (init_path
, "w");
2983 fprintf (stderr
, "Cannot open init file '%s' for output.\n", init_path
);
2986 defines_file
= fopen (defines_path
, "w");
2989 fprintf (stderr
, "Cannot open defines file '%s' for output.\n",
2994 /* Allocate some buffers. */
2995 for (int i
= 0; i
< MAXLINES
; i
++)
2996 lines
[i
] = (char *) malloc (LINELEN
);
2998 /* Initialize the balanced trees containing built-in function ids,
2999 overload function ids, and function type declaration ids. */
3001 rbt_new (&ovld_rbt
);
3002 rbt_new (&fntype_rbt
);
3004 /* Initialize another balanced tree that contains a map from built-in
3005 function ids to the order in which they were encountered. */
3006 rbt_new (&bifo_rbt
);
3008 /* Parse the built-in function file. */
3011 if (parse_bif () == PC_PARSEFAIL
)
3013 fprintf (stderr
, "Parsing of '%s' failed, aborting.\n", bif_path
);
3014 delete_output_files ();
3019 /* Create a mapping from function IDs in their final order to
3020 the order they appear in the built-in function file. */
3021 create_bif_order ();
3024 fprintf (stderr
, "\nFunction ID list:\n");
3025 rbt_dump (&bif_rbt
, bif_rbt
.rbt_root
);
3026 fprintf (stderr
, "\n");
3029 /* Parse the overload file. */
3030 num_ovld_stanzas
= 0;
3033 if (parse_ovld () == PC_PARSEFAIL
)
3035 fprintf (stderr
, "Parsing of '%s' failed, aborting.\n", ovld_path
);
3036 delete_output_files ();
3042 fprintf (stderr
, "\nFunction type decl list:\n");
3043 rbt_dump (&fntype_rbt
, fntype_rbt
.rbt_root
);
3044 fprintf (stderr
, "\n");
3047 /* Write the header file and the file containing initialization code. */
3048 if (!write_header_file ())
3050 fprintf (stderr
, "Output to '%s' failed, aborting.\n", header_path
);
3051 delete_output_files ();
3054 if (!write_init_file ())
3056 fprintf (stderr
, "Output to '%s' failed, aborting.\n", init_path
);
3057 delete_output_files ();
3061 /* Write the defines file to be included into altivec.h. */
3062 if (!write_defines_file ())
3064 fprintf (stderr
, "Output to '%s' failed, aborting.\n", defines_path
);
3065 delete_output_files ();
3069 /* Always close init_file last. This avoids race conditions in the
3070 build machinery. See comments in t-rs6000. */
3071 fclose (header_file
);
3072 fclose (defines_file
);