From c25c12b8aa19e3a23ea3511184b87d739555d4ae Mon Sep 17 00:00:00 2001 From: "J\"orn Rennecke" Date: Wed, 22 Nov 2000 01:22:02 +0000 Subject: [PATCH] rtl.h (traverse_md_constants): Declare. * rtl.h (traverse_md_constants): Declare. (struct md_constant): Define. * Makefile.in (HOST_RTL): Add hashtab.o . (OBJS): Add hashtab.o . (hashtab.o): New rule. (rtl.o): Depends on HASHTAB_H. * rtl.c (hashtab.h): #include. (md_constants): New static variable. (def_hash, def_name_eq_p, read_constants): New static functions. (traverse_md_constants): New function. (read_name): Do constant expansion. (read_rtx): Recognize define_constants. * gencodes.c (print_md_constant): New function. (main): Emit #defines for all constant definitions encountered. * md.texi (Constant Definitions): New node. * gensupport.c (xcalloc): New function. From-SVN: r37635 --- gcc/ChangeLog | 19 ++++++++ gcc/Makefile.in | 12 +++-- gcc/gencodes.c | 21 +++++++- gcc/gensupport.c | 15 ++++++ gcc/md.texi | 54 +++++++++++++++++++++ gcc/rtl.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++ gcc/rtl.h | 3 ++ 7 files changed, 242 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f95b9ba1849..a60a7e9ae70 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +Wed Nov 22 00:52:55 2000 J"orn Rennecke + + * rtl.h (traverse_md_constants): Declare. + (struct md_constant): Define. + * Makefile.in (HOST_RTL): Add hashtab.o . + (OBJS): Add hashtab.o . + (hashtab.o): New rule. + (rtl.o): Depends on HASHTAB_H. + * rtl.c (hashtab.h): #include. + (md_constants): New static variable. + (def_hash, def_name_eq_p, read_constants): New static functions. + (traverse_md_constants): New function. + (read_name): Do constant expansion. + (read_rtx): Recognize define_constants. + * gencodes.c (print_md_constant): New function. + (main): Emit #defines for all constant definitions encountered. + * md.texi (Constant Definitions): New node. + * gensupport.c (xcalloc): New function. + 2000-11-21 Richard Henderson * config/alpha/alpha.c (alpha_split_tfmode_frobsign): New. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 219b3df6209..a80b6af99e1 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -633,7 +633,7 @@ HOST_LIBS = $(USE_HOST_OBSTACK) $(USE_HOST_ALLOCA) $(USE_HOST_MALLOC) \ $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) $(HOST_CLIB) HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o \ - $(HOST_PREFIX)ggc-none.o gensupport.o + $(HOST_PREFIX)ggc-none.o gensupport.o hashtab.o HOST_PRINT = $(HOST_PREFIX)print-rtl.o HOST_ERRORS = $(HOST_PREFIX)errors.o @@ -735,7 +735,8 @@ OBJS = diagnostic.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \ mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o \ lists.o ggc-common.o $(GGC) stringpool.o simplify-rtx.o ssa.o bb-reorder.o \ - sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o + sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o \ + hashtab.o BACKEND = toplev.o libbackend.a @@ -1653,6 +1654,11 @@ $(MD_FILE): $(MD_DEPS) gensupport.o: gensupport.c $(RTL_H) $(OBSTACK_H) system.h errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gensupport.c +hashtab.o: $(srcdir)/../libiberty/hashtab.c $(CONFIG_H) + rm -f hashtab.c + $(LN_S) $(srcdir)/../libiberty/hashtab.c hashtab.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) hashtab.c + genconfig : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) @@ -1749,7 +1755,7 @@ gengenrtl.o : gengenrtl.c $(RTL_BASE_H) system.h real.h # and HOST_PREFIX_1 is `foobar', just to ensure these rules don't conflict # with the rules for rtl.o, alloca.o, etc. $(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) system.h $(RTL_H) \ - bitmap.h $(GGC_H) toplev.h + bitmap.h $(GGC_H) toplev.h $(HASHTAB_H) rm -f $(HOST_PREFIX)rtl.c sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(HOST_PREFIX)rtl.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c diff --git a/gcc/gencodes.c b/gcc/gencodes.c index 3c9bf9cc20c..04d6b45961c 100644 --- a/gcc/gencodes.c +++ b/gcc/gencodes.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ static int insn_code_number; static void gen_insn PARAMS ((rtx)); +static int print_md_constant PARAMS ((void **, void *)); static void gen_insn (insn) @@ -86,9 +87,11 @@ from the machine description file `md'. */\n\n"); printf (" CODE_FOR_nothing = %d };\n", insn_code_number + 1); - printf ("\n#define MAX_INSN_CODE ((int) CODE_FOR_nothing)\n"); + printf ("\n#define MAX_INSN_CODE ((int) CODE_FOR_nothing)\n\n"); - printf ("#endif /* MAX_INSN_CODE */\n"); + traverse_md_constants (print_md_constant, stdout); + + printf ("\n#endif /* MAX_INSN_CODE */\n"); fflush (stdout); return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); @@ -101,3 +104,17 @@ get_insn_name (code) { return NULL; } + +/* Called via traverse_md_constants; emit a #define for + the current constant definition. */ +static int +print_md_constant (slot, info) + void **slot; + void *info; +{ + struct md_constant *def = *slot; + FILE *file = info; + + fprintf (file, "#define %s %s\n", def->name, def->value); + return 1; +} diff --git a/gcc/gensupport.c b/gcc/gensupport.c index ce4869bccbe..cde2a220b4e 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -862,6 +862,21 @@ xstrdup (input) return output; } +PTR +xcalloc (nelem, elsize) + size_t nelem, elsize; +{ + PTR newmem; + + if (nelem == 0 || elsize == 0) + nelem = elsize = 1; + + newmem = calloc (nelem, elsize); + if (!newmem) + fatal ("virtual memory exhausted"); + return (newmem); +} + PTR xrealloc (old, size) PTR old; diff --git a/gcc/md.texi b/gcc/md.texi index 3b77c4b4020..82271596bb4 100644 --- a/gcc/md.texi +++ b/gcc/md.texi @@ -39,6 +39,8 @@ See the next chapter for information on the C header file. * Insn Attributes:: Specifying the value of attributes for generated insns. * Conditional Execution::Generating @code{define_insn} patterns for predication. +* Constant Definitions::Defining symbolic constants that can be used in the + md file. @end menu @node Patterns @@ -4690,3 +4692,55 @@ generates a new pattern "(@var{test2}) && (@var{test1})" "(%3) add %2,%1,%0") @end smallexample + +@node Constant Definitions +@section Constant Definitions +@cindex constant definitions +@findex define_constants + +Using literal constants inside instruction patterns reduces legibility and +can be a maintenance problem. + +To overcome this problem, you may use the @code{define_constants} +expression. It contains a vector of name-value pairs. From that +point on, wherever any of the names appears in the MD file, it is as +if the corresponding value had been written instead. You may use +@code{define_constants} multiple times; each appearance adds more +constants to the table. It is an error to redefine a constant with +a different value. + +To come back to the a29k load multiple example, instead of + +@smallexample +(define_insn "" + [(match_parallel 0 "load_multiple_operation" + [(set (match_operand:SI 1 "gpc_reg_operand" "=r") + (match_operand:SI 2 "memory_operand" "m")) + (use (reg:SI 179)) + (clobber (reg:SI 179))])] + "" + "loadm 0,0,%1,%2") +@end smallexample + +You could write: + +@smallexample +(define_constants [ + (R_BP 177) + (R_FC 178) + (R_CR 179) + (R_Q 180) +]) + +(define_insn "" + [(match_parallel 0 "load_multiple_operation" + [(set (match_operand:SI 1 "gpc_reg_operand" "=r") + (match_operand:SI 2 "memory_operand" "m")) + (use (reg:SI R_CR)) + (clobber (reg:SI R_CR))])] + "" + "loadm 0,0,%1,%2") +@end smallexample + +The constants that are defined with a define_constant are also output +in the insn-codes.h header file as #defines. diff --git a/gcc/rtl.c b/gcc/rtl.c index 7cc339d4c6a..48efc2640c9 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "obstack.h" #include "toplev.h" +#include "hashtab.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -290,10 +291,15 @@ const char * const reg_note_name[] = "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN" }; +static htab_t md_constants; + static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN; static void fatal_expected_char PARAMS ((FILE *, int, int)) ATTRIBUTE_NORETURN; static void read_name PARAMS ((char *, FILE *)); +static unsigned def_hash PARAMS ((const void *)); +static int def_name_eq_p PARAMS ((const void *, const void *)); +static void read_constants PARAMS ((FILE *infile, char *tmp_char)); /* Allocate an rtx vector of N elements. @@ -829,6 +835,25 @@ read_name (str, infile) read_rtx_lineno++; *p = 0; + + if (md_constants) + { + /* Do constant expansion. */ + struct md_constant *def; + + p = str; + do + { + struct md_constant tmp_def; + + tmp_def.name = p; + def = htab_find (md_constants, &tmp_def); + if (def) + p = def->value; + } while (def); + if (p != str) + strcpy (str, p); + } } /* Provide a version of a function to read a long long if the system does @@ -868,6 +893,98 @@ atoll(p) } #endif +/* Given a constant definition, return a hash code for its name. */ +static unsigned +def_hash (def) + const void *def; +{ + unsigned result, i; + const char *string = ((const struct md_constant *)def)->name; + + for (result = i = 0;*string++ != '\0'; i++) + result += ((unsigned char) *string << (i % CHAR_BIT)); + return result; +} + +/* Given two constant definitions, return true if they have the same name. */ +static int +def_name_eq_p (def1, def2) + const void *def1, *def2; +{ + return ! strcmp (((const struct md_constant *)def1)->name, + ((const struct md_constant *)def2)->name); +} + +/* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer suitable + to read a name or number into. Process a define_constants directive, + starting with the optional space after the "define_constants". */ +static void +read_constants (infile, tmp_char) + FILE *infile; + char *tmp_char; +{ + int c; + htab_t defs; + + c = read_skip_spaces (infile); + if (c != '[') + fatal_expected_char (infile, '[', c); + defs = md_constants; + if (! defs) + defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0); + /* Disable constant expansion during definition processing. */ + md_constants = 0; + while ( (c = read_skip_spaces (infile)) != ']') + { + struct md_constant *def; + void **entry_ptr; + + if (c != '(') + fatal_expected_char (infile, '(', c); + def = xmalloc (sizeof (struct md_constant)); + def->name = tmp_char; + read_name (tmp_char, infile); + entry_ptr = htab_find_slot (defs, def, TRUE); + if (! *entry_ptr) + def->name = xstrdup (tmp_char); + c = read_skip_spaces (infile); + ungetc (c, infile); + read_name (tmp_char, infile); + if (! *entry_ptr) + { + def->value = xstrdup (tmp_char); + *entry_ptr = def; + } + else + { + def = *entry_ptr; + if (strcmp (def->value, tmp_char)) + fatal_with_file_and_line (infile, + "redefinition of %s, was %s, now %s", + def->name, def->value, tmp_char); + } + c = read_skip_spaces (infile); + if (c != ')') + fatal_expected_char (infile, ')', c); + } + md_constants = defs; + c = read_skip_spaces (infile); + if (c != ')') + fatal_expected_char (infile, ')', c); +} + +/* For every constant definition, call CALLBACK with two arguments: + a pointer a pointer to the constant definition and INFO. + Stops when CALLBACK returns zero. */ +void +traverse_md_constants (callback, info) + htab_trav callback; + void *info; +{ + if (md_constants) + htab_traverse (md_constants, callback, info); +} + /* Read an rtx in printed representation from INFILE and return an actual rtx in core constructed accordingly. read_rtx is not used in the compiler proper, but rather in @@ -907,6 +1024,7 @@ read_rtx (infile) initialized = 1; } +again: c = read_skip_spaces (infile); /* Should be open paren. */ if (c != '(') fatal_expected_char (infile, '(', c); @@ -915,6 +1033,11 @@ read_rtx (infile) tmp_code = UNKNOWN; + if (! strcmp (tmp_char, "define_constants")) + { + read_constants (infile, tmp_char); + goto again; + } for (i = 0; i < NUM_RTX_CODE; i++) if (! strcmp (tmp_char, GET_RTX_NAME (i))) { diff --git a/gcc/rtl.h b/gcc/rtl.h index 762226cd3d4..c0f543d040b 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1946,6 +1946,9 @@ extern void init_varasm_once PARAMS ((void)); /* In rtl.c */ extern void init_rtl PARAMS ((void)); +extern void traverse_md_constants PARAMS ((int (*) (void **, void *), + void *)); +struct md_constant { char *name, *value; }; #ifdef BUFSIZ extern int read_skip_spaces PARAMS ((FILE *)); -- 2.30.2