From 6bac43d760cdced2775cb17add346f757ee6f045 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 17 Nov 2015 18:41:55 +0000 Subject: [PATCH] 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 ", 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. From-SVN: r230476 --- gcc/ChangeLog | 10 +++ gcc/Makefile.in | 18 ++++- gcc/gencfn-macros.c | 176 ++++++++++++++++++++++++++++++++++++++++++++ gcc/hash-set.h | 3 +- 4 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 gcc/gencfn-macros.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4bdf15a985f..38b7fe8f340 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-11-17 Richard Sandiford + + * 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. + 2015-11-17 Richard Sandiford * internal-fn.def (DEF_INTERNAL_INT_FN): New macro. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 5c294df7b8a..ba8108d198c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -876,7 +876,7 @@ endif # Shorthand variables for dependency lists. DUMPFILE_H = $(srcdir)/../libcpp/include/line-map.h dumpfile.h VEC_H = vec.h statistics.h $(GGC_H) -HASH_TABLE_H = $(HASHTAB_H) hash-table.h +HASH_TABLE_H = $(HASHTAB_H) hash-table.h $(GGC_H) EXCEPT_H = except.h $(HASHTAB_H) TARGET_DEF = target.def target-hooks-macros.h target-insns.def C_TARGET_DEF = c-family/c-target.def target-hooks-macros.h @@ -1570,6 +1570,7 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \ tm-preds.h tm-constrs.h checksum-options gimple-match.c generic-match.c \ tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \ genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \ + case-cfn-macros.h \ xgcc$(exeext) cpp$(exeext) $(FULL_DRIVER_NAME) \ $(EXTRA_PROGRAMS) gcc-cross$(exeext) \ $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \ @@ -2247,6 +2248,14 @@ s-constrs-h: $(MD_DEPS) build/genpreds$(build_exeext) $(SHELL) $(srcdir)/../move-if-change tmp-constrs.h tm-constrs.h $(STAMP) s-constrs-h +s-case-cfn-macros: build/gencfn-macros$(build_exeext) + $(RUN_GEN) build/gencfn-macros$(build_exeext) -c \ + > tmp-case-cfn-macros.h + $(SHELL) $(srcdir)/../move-if-change tmp-case-cfn-macros.h \ + case-cfn-macros.h + $(STAMP) s-case-cfn-macros +case-cfn-macros.h: s-case-cfn-macros; @true + target-hooks-def.h: s-target-hooks-def-h; @true # make sure that when we build info files, the used tm.texi is up to date. $(srcdir)/doc/tm.texi: s-tm-texi; @true @@ -2434,7 +2443,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_H) multilib.h \ $(ALL_GTFILES_H) gtype-desc.c gtype-desc.h gcov-iov.h \ options.h target-hooks-def.h insn-opinit.h \ common/common-target-hooks-def.h pass-instances.def \ - c-family/c-target-hooks-def.h params.list + c-family/c-target-hooks-def.h params.list case-cfn-macros.h # # How to compile object files to run on the build machine. @@ -2581,6 +2590,8 @@ build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ build/genmatch.o : genmatch.c $(BCONFIG_H) $(SYSTEM_H) \ coretypes.h errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \ tree.def builtins.def +build/gencfn-macros.o : gencfn-macros.c $(BCONFIG_H) $(SYSTEM_H) \ + coretypes.h errors.h $(HASH_TABLE_H) hash-set.h builtins.def internal-fn.def # Compile the programs that generate insn-* from the machine description. # They are compiled with $(COMPILER_FOR_BUILD), and associated libraries, @@ -2597,7 +2608,7 @@ genprogmd = $(genprogrtl) mddeps constants enums $(genprogmd:%=build/gen%$(build_exeext)): $(BUILD_MD) # All these programs need to report errors. -genprogerr = $(genprogmd) genrtl modes gtype hooks +genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros $(genprogerr:%=build/gen%$(build_exeext)): $(BUILD_ERRORS) # Remaining build programs. @@ -2607,6 +2618,7 @@ genprog = $(genprogerr) check checksum condmd match build/genautomata$(build_exeext) : BUILD_LIBS += -lm build/genrecog$(build_exeext) : build/hash-table.o build/inchash.o +build/gencfn-macros$(build_exeext) : build/hash-table.o build/ggc-none.o # For stage1 and when cross-compiling use the build libcpp which is # built with NLS disabled. For stage2+ use the host library and 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 +. */ + +/* 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 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_ 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_ 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; +} diff --git a/gcc/hash-set.h b/gcc/hash-set.h index e85af2a1745..679d2b6df64 100644 --- a/gcc/hash-set.h +++ b/gcc/hash-set.h @@ -21,10 +21,11 @@ along with GCC; see the file COPYING3. If not see #ifndef hash_set_h #define hash_set_h -template > +template > class hash_set { public: + typedef typename Traits::value_type Key; explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO) : m_table (n, ggc, true, HASH_SET_ORIGIN PASS_MEM_STAT) {} -- 2.30.2