111
|
1 /* Generate macros based on the combined_fn enum.
|
145
|
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
111
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it under
|
|
7 the terms of the GNU General Public License as published by the Free
|
|
8 Software Foundation; either version 3, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GCC; see the file COPYING3. If not see
|
|
18 <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 /* Automatically generate code fragments related to combined_fn.
|
|
21
|
|
22 The program looks for math built-in functions that have float, double
|
|
23 and long double variants, such as {sqrtf, sqrt, sqrtl}, and that may
|
|
24 or may not have an associated internal function as well. It also looks
|
|
25 for integer built-in functions that have int, long, long long and
|
|
26 intmax_t variants, such as {clz, clzl, clzll, clzimax}, and that
|
|
27 again may or may not have an associated internal function as well.
|
|
28
|
|
29 When run with -c, the generator prints a list of macros such as:
|
|
30
|
|
31 CASE_CFN_SQRT
|
|
32
|
|
33 for each group of functions described above, with 'case CFN_*'
|
|
34 statements for each built-in and internal function in the group.
|
|
35 For example, there are both built-in and internal implementations
|
|
36 of SQRT, so "CASE_CFN_SQRT:" is equivalent to:
|
|
37
|
|
38 case CFN_BUILT_IN_SQRTF:
|
|
39 case CFN_BUILT_IN_SQRT:
|
|
40 case CFN_BUILT_IN_SQRTL:
|
|
41 case CFN_SQRT:
|
|
42
|
|
43 The macros for groups with no internal function drop the last line.
|
|
44
|
|
45 When run with -o, the generator prints a similar list of
|
|
46 define_operator_list directives, for use by match.pd. Each operator
|
|
47 list starts with the built-in functions, in order of ascending type width.
|
|
48 This is followed by an entry for the internal function, or "null" if there
|
|
49 is no internal function for the group. For example:
|
|
50
|
|
51 (define_operator_list SQRT
|
|
52 BUILT_IN_SQRTF
|
|
53 BUILT_IN_SQRT
|
|
54 BUILT_IN_SQRTL
|
|
55 IFN_SQRT)
|
|
56
|
|
57 and:
|
|
58
|
|
59 (define_operator_list CABS
|
|
60 BUILT_IN_CABSF
|
|
61 BUILT_IN_CABS
|
|
62 BUILT_IN_CABSL
|
|
63 null) */
|
|
64
|
|
65 #include "bconfig.h"
|
|
66 #include "system.h"
|
|
67 #include "coretypes.h"
|
|
68 #include "hash-table.h"
|
|
69 #include "hash-set.h"
|
|
70 #include "errors.h"
|
|
71
|
|
72 typedef hash_set <nofree_string_hash> string_set;
|
|
73
|
|
74 /* Add all names in null-terminated list NAMES to SET. */
|
|
75
|
|
76 static void
|
|
77 add_to_set (string_set *set, const char *const *names)
|
|
78 {
|
|
79 for (unsigned int i = 0; names[i]; ++i)
|
|
80 set->add (names[i]);
|
|
81 }
|
|
82
|
|
83 /* Return true if *BUILTINS contains BUILT_IN_<NAME><SUFFIX> for all
|
|
84 suffixes in null-terminated list SUFFIXES. */
|
|
85
|
|
86 static bool
|
|
87 is_group (string_set *builtins, const char *name, const char *const *suffixes)
|
|
88 {
|
|
89 for (unsigned int i = 0; suffixes[i]; ++i)
|
|
90 if (!builtins->contains (ACONCAT (("BUILT_IN_", name, suffixes[i], NULL))))
|
|
91 return false;
|
|
92 return true;
|
|
93 }
|
|
94
|
|
95 /* Print a macro for all combined functions related to NAME, with the
|
|
96 null-terminated list of suffixes in SUFFIXES. INTERNAL_P says whether
|
131
|
97 CFN_<NAME> also exists. FLOATN_P is a suffix to the operator name, blank
|
|
98 for normal operators, "_FN" for _Float<N>/_Float<N>X operators only, and
|
|
99 "_ALL" for both the traditional operators and the _Float<N>/_Float<N>X
|
|
100 operators. */
|
111
|
101
|
|
102 static void
|
|
103 print_case_cfn (const char *name, bool internal_p,
|
131
|
104 const char *const *suffixes, const char *floatn)
|
111
|
105 {
|
131
|
106 printf ("#define CASE_CFN_%s%s", name, floatn);
|
111
|
107 if (internal_p)
|
131
|
108 printf (" \\\n case CFN_%s%s", name, floatn);
|
111
|
109 for (unsigned int i = 0; suffixes[i]; ++i)
|
|
110 printf ("%s \\\n case CFN_BUILT_IN_%s%s",
|
|
111 internal_p || i > 0 ? ":" : "", name, suffixes[i]);
|
|
112 printf ("\n");
|
|
113 }
|
|
114
|
131
|
115 /* Print an operator list for all combined functions related to NAME, with the
|
|
116 null-terminated list of suffixes in SUFFIXES. INTERNAL_P says whether
|
|
117 CFN_<NAME> also exists. FLOATN_P is a suffix to the operator name, blank
|
|
118 for normal operators, "_FN" for _Float<N>/_Float<N>X operators only, and
|
|
119 "_ALL" for both the traditional operators and the _Float<N>/_Float<N>X
|
|
120 operators. */
|
111
|
121
|
|
122 static void
|
|
123 print_define_operator_list (const char *name, bool internal_p,
|
131
|
124 const char *const *suffixes,
|
|
125 const char *floatn)
|
111
|
126 {
|
131
|
127 printf ("(define_operator_list %s%s\n", name, floatn);
|
111
|
128 for (unsigned int i = 0; suffixes[i]; ++i)
|
|
129 printf (" BUILT_IN_%s%s\n", name, suffixes[i]);
|
|
130 if (internal_p)
|
|
131 printf (" IFN_%s)\n", name);
|
|
132 else
|
|
133 printf (" null)\n");
|
|
134 }
|
|
135
|
|
136 const char *const builtin_names[] = {
|
|
137 #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \
|
|
138 #ENUM,
|
|
139 #include "builtins.def"
|
|
140 NULL
|
|
141 };
|
|
142
|
|
143 const char *const internal_fn_flt_names[] = {
|
|
144 #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
|
|
145 #NAME,
|
|
146 #include "internal-fn.def"
|
|
147 NULL
|
|
148 };
|
|
149
|
|
150 const char *const internal_fn_int_names[] = {
|
|
151 #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
|
|
152 #NAME,
|
|
153 #include "internal-fn.def"
|
|
154 NULL
|
|
155 };
|
|
156
|
|
157 static const char *const flt_suffixes[] = { "F", "", "L", NULL };
|
131
|
158 static const char *const fltfn_suffixes[] = { "F16", "F32", "F64", "F128",
|
|
159 "F32X", "F64X", "F128X", NULL };
|
|
160 static const char *const fltall_suffixes[] = { "F", "", "L", "F16", "F32",
|
|
161 "F64", "F128", "F32X", "F64X",
|
|
162 "F128X", NULL };
|
111
|
163 static const char *const int_suffixes[] = { "", "L", "LL", "IMAX", NULL };
|
|
164
|
|
165 static const char *const *const suffix_lists[] = {
|
|
166 flt_suffixes,
|
|
167 int_suffixes,
|
|
168 NULL
|
|
169 };
|
|
170
|
|
171 int
|
|
172 main (int argc, char **argv)
|
|
173 {
|
|
174 /* Check arguments. */
|
|
175 progname = argv[0];
|
|
176 if (argc != 2
|
|
177 || argv[1][0] != '-'
|
|
178 || !strchr ("co", argv[1][1])
|
|
179 || argv[1][2])
|
|
180 fatal ("usage: %s [-c|-o] > file", progname);
|
|
181 int type = argv[1][1];
|
|
182
|
|
183 /* Collect the set of built-in and internal functions. */
|
|
184 string_set builtins;
|
|
185 string_set internal_fns;
|
|
186 add_to_set (&builtins, builtin_names);
|
|
187 add_to_set (&internal_fns, internal_fn_flt_names);
|
|
188 add_to_set (&internal_fns, internal_fn_int_names);
|
|
189
|
|
190 /* Check the functions. */
|
|
191 for (unsigned int i = 0; internal_fn_flt_names[i]; ++i)
|
|
192 {
|
|
193 const char *name = internal_fn_flt_names[i];
|
|
194 if (!is_group (&builtins, name, flt_suffixes))
|
|
195 error ("DEF_INTERNAL_FLT_FN (%s) has no associated built-in"
|
|
196 " functions", name);
|
|
197 }
|
|
198 for (unsigned int i = 0; internal_fn_int_names[i]; ++i)
|
|
199 {
|
|
200 const char *name = internal_fn_int_names[i];
|
|
201 if (!is_group (&builtins, name, int_suffixes))
|
|
202 error ("DEF_INTERNAL_INT_FN (%s) has no associated built-in"
|
|
203 " functions", name);
|
|
204 }
|
|
205
|
|
206 /* Go through the built-in functions in declaration order, outputting
|
|
207 definitions as appropriate. */
|
|
208 for (unsigned int i = 0; builtin_names[i]; ++i)
|
|
209 {
|
|
210 const char *name = builtin_names[i];
|
|
211 if (strncmp (name, "BUILT_IN_", 9) == 0)
|
|
212 {
|
|
213 const char *root = name + 9;
|
|
214 for (unsigned int j = 0; suffix_lists[j]; ++j)
|
131
|
215 {
|
|
216 const char *const *const suffix = suffix_lists[j];
|
|
217
|
|
218 if (is_group (&builtins, root, suffix))
|
|
219 {
|
|
220 bool internal_p = internal_fns.contains (root);
|
|
221
|
|
222 if (type == 'c')
|
|
223 print_case_cfn (root, internal_p, suffix, "");
|
|
224 else
|
|
225 print_define_operator_list (root, internal_p, suffix, "");
|
|
226
|
|
227 /* Support the _Float<N> and _Float<N>X math functions if
|
|
228 they exist. We put these out as a separate CFN or
|
|
229 operator macro, so code can add support or not as
|
|
230 needed. We also put out a combined CFN or operator
|
|
231 macro that includes both the traditional names and the
|
|
232 _Float<N> and _Float<N>X versions. */
|
|
233 if (suffix == flt_suffixes
|
|
234 && is_group (&builtins, root, fltfn_suffixes))
|
|
235 {
|
|
236 if (type == 'c')
|
|
237 {
|
|
238 print_case_cfn (root, false, fltfn_suffixes, "_FN");
|
|
239 print_case_cfn (root, false, fltall_suffixes, "_ALL");
|
|
240 }
|
|
241 else
|
|
242 {
|
|
243 print_define_operator_list (root, false,
|
|
244 fltfn_suffixes, "_FN");
|
|
245 print_define_operator_list (root, internal_p,
|
|
246 fltall_suffixes, "_ALL");
|
|
247 }
|
|
248 }
|
|
249 }
|
|
250 }
|
111
|
251 }
|
|
252 }
|
|
253
|
|
254 if (fflush (stdout) || fclose (stdout) || have_error)
|
|
255 return FATAL_EXIT_CODE;
|
|
256 return SUCCESS_EXIT_CODE;
|
|
257 }
|