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.

From-SVN: r230476
This commit is contained in:
Richard Sandiford 2015-11-17 18:41:55 +00:00 committed by Richard Sandiford
parent 4959a75288
commit 6bac43d760
4 changed files with 203 additions and 4 deletions

View File

@ -1,3 +1,13 @@
2015-11-17 Richard Sandiford <richard.sandiford@arm.com>
* 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 <richard.sandiford@arm.com>
* internal-fn.def (DEF_INTERNAL_INT_FN): New macro.

View File

@ -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

176
gcc/gencfn-macros.c Normal file
View File

@ -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;
}

View File

@ -21,10 +21,11 @@ along with GCC; see the file COPYING3. If not see
#ifndef hash_set_h
#define hash_set_h
template<typename Key, typename Traits = default_hash_traits<Key> >
template<typename KeyId, typename Traits = default_hash_traits<KeyId> >
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) {}