1 /* Generate macros based on the combined_fn enum.
2 Copyright (C) 2015-2021 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
20 /* Automatically generate code fragments related to combined_fn.
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.
29 When run with -c, the generator prints a list of macros such as:
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:
38 case CFN_BUILT_IN_SQRTF:
39 case CFN_BUILT_IN_SQRT:
40 case CFN_BUILT_IN_SQRTL:
43 The macros for groups with no internal function drop the last line.
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:
51 (define_operator_list SQRT
59 (define_operator_list CABS
67 #include "coretypes.h"
68 #include "hash-table.h"
72 typedef hash_set
<nofree_string_hash
> string_set
;
74 /* Add all names in null-terminated list NAMES to SET. */
77 add_to_set (string_set
*set
, const char *const *names
)
79 for (unsigned int i
= 0; names
[i
]; ++i
)
83 /* Return true if *BUILTINS contains BUILT_IN_<NAME><SUFFIX> for all
84 suffixes in null-terminated list SUFFIXES. */
87 is_group (string_set
*builtins
, const char *name
, const char *const *suffixes
)
89 for (unsigned int i
= 0; suffixes
[i
]; ++i
)
90 if (!builtins
->contains (ACONCAT (("BUILT_IN_", name
, suffixes
[i
], NULL
))))
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
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
103 print_case_cfn (const char *name
, bool internal_p
,
104 const char *const *suffixes
, const char *floatn
)
106 printf ("#define CASE_CFN_%s%s", name
, floatn
);
108 printf (" \\\n case CFN_%s%s", name
, floatn
);
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
]);
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
123 print_define_operator_list (const char *name
, bool internal_p
,
124 const char *const *suffixes
,
127 printf ("(define_operator_list %s%s\n", name
, floatn
);
128 for (unsigned int i
= 0; suffixes
[i
]; ++i
)
129 printf (" BUILT_IN_%s%s\n", name
, suffixes
[i
]);
131 printf (" IFN_%s)\n", name
);
136 const char *const builtin_names
[] = {
137 #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \
139 #include "builtins.def"
143 const char *const internal_fn_flt_names
[] = {
144 #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
146 #include "internal-fn.def"
150 const char *const internal_fn_int_names
[] = {
151 #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
153 #include "internal-fn.def"
157 static const char *const flt_suffixes
[] = { "F", "", "L", NULL
};
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",
163 static const char *const int_suffixes
[] = { "", "L", "LL", "IMAX", NULL
};
165 static const char *const *const suffix_lists
[] = {
172 main (int argc
, char **argv
)
174 /* Check arguments. */
178 || !strchr ("co", argv
[1][1])
180 fatal ("usage: %s [-c|-o] > file", progname
);
181 int type
= argv
[1][1];
183 /* Collect the set of built-in and internal functions. */
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
);
190 /* Check the functions. */
191 for (unsigned int i
= 0; internal_fn_flt_names
[i
]; ++i
)
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"
198 for (unsigned int i
= 0; internal_fn_int_names
[i
]; ++i
)
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"
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
)
210 const char *name
= builtin_names
[i
];
211 if (startswith (name
, "BUILT_IN_"))
213 const char *root
= name
+ 9;
214 for (unsigned int j
= 0; suffix_lists
[j
]; ++j
)
216 const char *const *const suffix
= suffix_lists
[j
];
218 if (is_group (&builtins
, root
, suffix
))
220 bool internal_p
= internal_fns
.contains (root
);
223 print_case_cfn (root
, internal_p
, suffix
, "");
225 print_define_operator_list (root
, internal_p
, suffix
, "");
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
))
238 print_case_cfn (root
, false, fltfn_suffixes
, "_FN");
239 print_case_cfn (root
, false, fltall_suffixes
, "_ALL");
243 print_define_operator_list (root
, false,
244 fltfn_suffixes
, "_FN");
245 print_define_operator_list (root
, internal_p
,
246 fltall_suffixes
, "_ALL");
254 if (fflush (stdout
) || fclose (stdout
) || have_error
)
255 return FATAL_EXIT_CODE
;
256 return SUCCESS_EXIT_CODE
;