diff --git a/gcc/defaults.h b/gcc/defaults.h index 057b646..5beddea 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -1426,96 +1426,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_VTABLE_USES_DESCRIPTORS 0 #endif -#ifndef HAVE_simple_return -#define HAVE_simple_return 0 -static inline rtx -gen_simple_return () -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_return -#define HAVE_return 0 -static inline rtx -gen_return () -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_epilogue -#define HAVE_epilogue 0 -static inline rtx -gen_epilogue () -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_mem_thread_fence -#define HAVE_mem_thread_fence 0 -static inline rtx -gen_mem_thread_fence (rtx) -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_memory_barrier -#define HAVE_memory_barrier 0 -static inline rtx -gen_memory_barrier () -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_mem_signal_fence -#define HAVE_mem_signal_fence 0 -static inline rtx -gen_mem_signal_fence (rtx) -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_load_multiple -#define HAVE_load_multiple 0 -static inline rtx -gen_load_multiple (rtx, rtx, rtx) -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_store_multiple -#define HAVE_store_multiple 0 -static inline rtx -gen_store_multiple (rtx, rtx, rtx) -{ - gcc_unreachable (); - return NULL; -} -#endif - -#ifndef HAVE_tablejump -#define HAVE_tablejump 0 -static inline rtx -gen_tablejump (rtx, rtx) -{ - gcc_unreachable (); - return NULL; -} -#endif - #endif /* GCC_INSN_FLAGS_H */ #endif /* ! GCC_DEFAULTS_H */ diff --git a/gcc/genflags.c b/gcc/genflags.c index 0da15f1..2a70b56 100644 --- a/gcc/genflags.c +++ b/gcc/genflags.c @@ -26,10 +26,65 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "rtl.h" #include "obstack.h" +#include "hash-map.h" #include "errors.h" #include "read-md.h" #include "gensupport.h" +/* Structure which holds data, required for generating stub gen_* function. */ +struct stub_info_t +{ + /* Instruction name. */ + const char *name; + /* Number of arguments (i.e., instruction operands). */ + int opno; + /* Set to true when generator is output, so no stub is needed. */ + bool done; +}; + +/* These instructions require default stub function. Stubs are never called. + They allow to reduce the amount of conditionally-compiled code: if a stub is + defined there is no need to guard the call by #ifdef (plain if statement can + be used instead). */ + +#define DEF_STUB(name, opno) { name, opno, false } + +static stub_info_t stubs[] = { + DEF_STUB ("simple_return", 0), + DEF_STUB ("return", 0), + DEF_STUB ("epilogue", 0), + DEF_STUB ("mem_thread_fence", 1), + DEF_STUB ("memory_barrier", 0), + DEF_STUB ("mem_signal_fence", 1), + DEF_STUB ("load_multiple", 3), + DEF_STUB ("store_multiple", 3), + DEF_STUB ("tablejump", 2) +}; + +#undef DEF_STUB + +/* Helper traits for using null-terminated strings as keys in hash map. + FIXME: Unify various "string hashers" and move them to hash-map-traits.h. */ +struct gflg_string_hasher : default_hashmap_traits +{ + typedef const char *value_type; + typedef const char *compare_type; + + static inline hashval_t hash (const char *s) + { + return htab_hash_string (s); + } + + static inline bool equal_keys (const char *p1, const char *p2) + { + return strcmp (p1, p2) == 0; + } +}; + +/* Mapping from insn name to corresponding stub_info_t entry. */ +static hash_map + stubs_map (ARRAY_SIZE (stubs), false, false); + /* Obstack to remember insns with. */ static struct obstack obstack; @@ -42,8 +97,18 @@ static int max_opno; static void max_operand_1 (rtx); static int num_operands (rtx); static void gen_proto (rtx); +static void gen_dummy (const char *, int, bool); static void gen_macro (const char *, int, int); static void gen_insn (int, rtx); +static void gen_stub (const char *, int); + +/* Remember that either real generator or dummy called NAME has been output. */ +static inline void +mark_as_done (const char *name) +{ + if (stub_info_t **stub = stubs_map.get (name)) + (*stub)->done = true; +} /* Count the number of match_operand's found. */ @@ -119,6 +184,27 @@ gen_macro (const char *name, int real, int expect) printf ("(%c))\n", i + 'A'); } +/* Print out a dummy for generator for instruction NAME with NUM arguments + which either does nothing, or aborts (depending on UNREACHABLE). */ + +static void +gen_dummy (const char *name, int num, bool unreachable) +{ + printf ("static inline rtx\ngen_%s (", name); + + if (num > 0) + { + for (int i = 0; i < num-1; i++) + fputs ("rtx, ", stdout); + fputs ("rtx", stdout); + } + + puts (")\n{"); + if (unreachable) + puts (" gcc_unreachable ();"); + puts (" return NULL;\n}"); +} + /* Print out prototype information for a generator function. If the insn pattern has been elided, print out a dummy generator that does nothing. */ @@ -170,20 +256,9 @@ gen_proto (rtx insn) /* Some back ends want to take the address of generator functions, so we cannot simply use #define for these dummy definitions. */ if (truth == 0) - { - printf ("static inline rtx\ngen_%s", name); - if (num > 0) - { - putchar ('('); - for (i = 0; i < num-1; i++) - printf ("rtx ARG_UNUSED (%c), ", 'a' + i); - printf ("rtx ARG_UNUSED (%c))\n", 'a' + i); - } - else - puts ("(void)"); - puts ("{\n return 0;\n}"); - } + gen_dummy (name, num, /*unreachable=*/false); + mark_as_done (name); } static void @@ -244,6 +319,19 @@ gen_insn (int line_no, rtx insn) } obstack_grow (&obstack, &insn, sizeof (rtx)); + + if (truth) + mark_as_done (name); +} + +/* Print out stub generator and flag for missing insn. */ + +static void +gen_stub (const char *name, int num) +{ + gen_dummy (name, num, /*unreachable=*/true); + printf ("#define HAVE_%s 0\n", name); + printf ("#define CODE_FOR_%s CODE_FOR_nothing\n", name); } int @@ -257,6 +345,9 @@ main (int argc, char **argv) progname = "genflags"; obstack_init (&obstack); + for (unsigned i = 0; i < ARRAY_SIZE (stubs); i++) + stubs_map.put (stubs[i].name, &stubs[i]); + /* We need to see all the possibilities. Elided insns may have direct calls to their generators in C code. */ insn_elision = 0; @@ -290,6 +381,11 @@ main (int argc, char **argv) for (insn_ptr = insns; *insn_ptr; insn_ptr++) gen_proto (*insn_ptr); + /* Output missing stubs. */ + for (unsigned i = 0; i < ARRAY_SIZE (stubs); i++) + if (!stubs[i].done) + gen_stub (stubs[i].name, stubs[i].opno); + puts ("\n#endif /* GCC_INSN_FLAGS_H */"); if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))