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