summaryrefslogtreecommitdiff
path: root/gcc/gencfn-macros.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-17 18:41:55 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-17 18:41:55 +0000
commit28544f39ce4353ea672c3c75c00a6420214038fa (patch)
tree5e9bc873dd49d3dfdd8631708321cbf4a109a760 /gcc/gencfn-macros.c
parentc9452b7c625f99aa3aebbdc5011ddd9055255670 (diff)
downloadgcc-28544f39ce4353ea672c3c75c00a6420214038fa.tar.gz
Add gencfn-macros.c
This patch automatically generates case macros such as: CASE_CFN_SQRT for each {F,,L} floating-point built-in function and each {,L,LL,IMAX} integer built-in function. The macros match the same built-in functions as CASE_FLT_FN and CASE_INT_FN but in addition include the associated internal function, if any. The idea is to make sure that users of combined_fn don't need to know which built-in functions have internal-function equivalents. If we add a new function to internal-fn.def, all combined_fn users should pick it up automatically. The generator wants to use "hash_set <nofree_string_hash>", so the patch follows hash_map in using the types given by the traits as the key. This is a no-op for current users of hash_set. Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. gcc/ * Makefile.in (HASH_TABLE_H): Add GGC_H. (MOSTLYCLEANFILES, generated_files): Add case-fn-macros.h. (s-case-cfn-macros, case-cfn-macros.h, build/gencfn-macros.o) (build/gencfn-macros$(build_exeext): New rules. (genprogerr): Add cfn-macros. * hash-set.h (hash_set): Use the traits value_type as the key. * gencfn-macros.c: New file. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230476 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gencfn-macros.c')
-rw-r--r--gcc/gencfn-macros.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/gcc/gencfn-macros.c b/gcc/gencfn-macros.c
new file mode 100644
index 00000000000..5ee3af0eb5c
--- /dev/null
+++ b/gcc/gencfn-macros.c
@@ -0,0 +1,176 @@
+/* Generate macros based on the combined_fn enum.
+ Copyright (C) 2015 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. */
+
+#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. */
+
+static void
+print_case_cfn (const char *name, bool internal_p,
+ const char *const *suffixes)
+{
+ printf ("#define CASE_CFN_%s", name);
+ if (internal_p)
+ printf (" \\\n case CFN_%s", name);
+ 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");
+}
+
+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 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] != '-'
+ || argv[1][1] != 'c'
+ || argv[1][2])
+ fatal ("usage: %s -c > file", progname);
+
+ /* 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)
+ if (is_group (&builtins, root, suffix_lists[j]))
+ {
+ bool internal_p = internal_fns.contains (root);
+ print_case_cfn (root, internal_p, suffix_lists[j]);
+ }
+ }
+ }
+
+ if (fflush (stdout) || fclose (stdout) || have_error)
+ return FATAL_EXIT_CODE;
+ return SUCCESS_EXIT_CODE;
+}