aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/Makefile.in12
-rw-r--r--gcc/gencodes.c21
-rw-r--r--gcc/gensupport.c15
-rw-r--r--gcc/md.texi54
-rw-r--r--gcc/rtl.c123
-rw-r--r--gcc/rtl.h3
7 files changed, 242 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f95b9ba..a60a7e9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+Wed Nov 22 00:52:55 2000 J"orn Rennecke <amylaar@redhat.com>
+
+ * 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 <rth@redhat.com>
* config/alpha/alpha.c (alpha_split_tfmode_frobsign): New.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 219b3df..a80b6af 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 3c9bf9c..04d6b45 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 ce4869b..cde2a22 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -863,6 +863,21 @@ xstrdup (input)
}
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;
size_t size;
diff --git a/gcc/md.texi b/gcc/md.texi
index 3b77c4b..8227159 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 7cc339d..48efc26 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 762226c..c0f543d 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 *));