summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog69
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/genattr.c2
-rw-r--r--gcc/genattrtab.c2
-rw-r--r--gcc/genautomata.c2
-rw-r--r--gcc/gencodes.c2
-rw-r--r--gcc/genconditions.c2
-rw-r--r--gcc/genconfig.c2
-rw-r--r--gcc/genconstants.c2
-rw-r--r--gcc/genemit.c2
-rw-r--r--gcc/genextract.c2
-rw-r--r--gcc/genflags.c2
-rw-r--r--gcc/genmddeps.c5
-rw-r--r--gcc/genopinit.c2
-rw-r--r--gcc/genoutput.c2
-rw-r--r--gcc/genpeep.c2
-rw-r--r--gcc/genpreds.c2
-rw-r--r--gcc/genrecog.c2
-rw-r--r--gcc/gensupport.c264
-rw-r--r--gcc/gensupport.h9
-rw-r--r--gcc/read-md.c291
-rw-r--r--gcc/read-md.h12
-rw-r--r--gcc/read-rtl.c211
-rw-r--r--gcc/rtl.def3
-rw-r--r--gcc/rtl.h2
25 files changed, 490 insertions, 408 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aeb277f8aef..e697a529387 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,74 @@
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
+ * Makefile.in (build/genmddeps.o): Depend on $(READ_MD_H).
+ * genmddeps.c: Include read-md.h.
+ (main): Call init_rtx_reader_args instead of init_md_reader_args.
+ * genattr.c (main): Likewise.
+ * genattrtab.c (main): Likewise.
+ * genautomata.c (main): Likewise.
+ * gencodes.c (main): Likewise.
+ * genconditions.c (main): Likewise.
+ * genconfig.c (main): Likewise.
+ * genconstants.c (main): Likewise.
+ * genemit.c (main): Likewise.
+ * genextract.c (main): Likewise.
+ * genflags.c (main): Likewise.
+ * genopinit.c (main): Likewise.
+ * genoutput.c (main): Likewise.
+ * genpeep.c (main): Likewise.
+ * genrecog.c (main): Likewise.
+ * genpreds.c (main): Likewise.
+ * gensupport.h (in_fname): Move to read-md.h.
+ (init_md_reader_args_cb): Rename to...
+ (init_rtx_reader_args_cb): ...this and return a bool.
+ (init_md_reader_args): Rename to...
+ (init_rtx_reader_args): ...this and return a bool.
+ (include_callback): Move to read-md.h.
+ * gensupport.c (in_fname, include_callback, base_dir, max_include_len)
+ (file_name_list, first_dir_md_include): Move to read-md.c
+ (first_bracket_include): Delete unused variable.
+ (last_dir_md_include): Move to read-md.c.
+ (process_include): Delete, moving code to read-md.c:handle_include.
+ (process_rtx): Don't handle INCLUDE.
+ (save_string): Delete.
+ (rtx_handle_directive): New function.
+ (init_md_reader_args_cb): Rename to...
+ (init_rtx_reader_args_cb): ...this and return a boolean success value.
+ Use read_md_args.
+ (init_md_reader_args): Rename to...
+ (init_rtx_reader_args): ...this and return a boolean success value.
+ * rtl.def (INCLUDE): Delete.
+ * rtl.h (read_rtx): Remove "int *" argument. Add "const char *"
+ argument.
+ * read-rtl.c (read_conditions): Don't gobble ')' here.
+ (read_mapping): Likewise.
+ (read_rtx): Remove LINENO argument. Add RTX_NAME argument.
+ Handle top-level non-rtx constructs here rather than in read_rtx_1.
+ Store the whole queue in *X. Remove call to init_md_reader.
+ (read_rtx_1): Rename to...
+ (read_rtx_code): ...this. Call read_nested_rtx to read subrtxes.
+ Don't handle top-level non-rtx constructs here. Don't handle (nil)
+ here.
+ (read_nested_rtx): New function. Handle (nil) here rather than
+ in read_rtx_code.
+ (read_rtx_variadic): Call read_nested_rtx to read subrtxes. Don't
+ gobble ')' here.
+ * read-md.h (directive_handler_t): New type.
+ (in_fname, include_callback): Moved from read-md.h.
+ (read_constants, init_md_reader): Delete.
+ (read_md_files): Declare.
+ * read-md.c (file_name_list, in_fname, base_dir, first_dir_md_include)
+ (last_dir_md_include_ptr, include_callback, max_include_len): Moved
+ from gensupport.c.
+ (read_constants): Rename to...
+ (handle_constants): ...this. Don't gobble ')' here.
+ (handle_include, handle_file, handle_toplevel_file)
+ (parse_include): New functions, mostly taken from gensupport.c.
+ (init_md_reader): Subsume into...
+ (read_md_files): ...this new function.
+
+2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
+
* read-md.h (read_char): Increment read_md_lineno after reading '\n'.
(unread_char): Decrement read_md_lineno after putting back '\n'.
* read-md.c (fatal_with_file_and_line): Push back any characters
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b8379d082b1..84f332ff597 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3829,7 +3829,7 @@ build/gengtype-parse.o : gengtype-parse.c gengtype.h $(BCONFIG_H) \
build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h \
rtl.def insn-notes.def errors.h double-int.h $(HASHTAB_H)
build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
- $(GTM_H) $(RTL_BASE_H) errors.h gensupport.h
+ $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) gensupport.h
build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h \
$(HASHTAB_H) machmode.def $(extra_modes_file)
build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
diff --git a/gcc/genattr.c b/gcc/genattr.c
index 78c510d3b13..84399b8a677 100644
--- a/gcc/genattr.c
+++ b/gcc/genattr.c
@@ -98,7 +98,7 @@ main (int argc, char **argv)
progname = "genattr";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genattr'");
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 545cd8ebce0..ac5c75e45d0 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -4417,7 +4417,7 @@ main (int argc, char **argv)
progname = "genattrtab";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
obstack_init (hash_obstack);
diff --git a/gcc/genautomata.c b/gcc/genautomata.c
index f7493c7071d..a268aa053da 100644
--- a/gcc/genautomata.c
+++ b/gcc/genautomata.c
@@ -9467,7 +9467,7 @@ main (int argc, char **argv)
progname = "genautomata";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
initiate_automaton_gen (argc, argv);
diff --git a/gcc/gencodes.c b/gcc/gencodes.c
index 5a6014cb1c3..4c59f8392b5 100644
--- a/gcc/gencodes.c
+++ b/gcc/gencodes.c
@@ -58,7 +58,7 @@ main (int argc, char **argv)
direct references to CODE_FOR_xxx in C code. */
insn_elision = 0;
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
puts ("\
diff --git a/gcc/genconditions.c b/gcc/genconditions.c
index 9ac7e83fd09..2d93c3470d6 100644
--- a/gcc/genconditions.c
+++ b/gcc/genconditions.c
@@ -214,7 +214,7 @@ main (int argc, char **argv)
progname = "genconditions";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
/* Read the machine description. */
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index a0a023dce47..027c92e50dc 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -264,7 +264,7 @@ main (int argc, char **argv)
progname = "genconfig";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genconfig'");
diff --git a/gcc/genconstants.c b/gcc/genconstants.c
index 1a0182c7a59..e5f083a36fd 100644
--- a/gcc/genconstants.c
+++ b/gcc/genconstants.c
@@ -52,7 +52,7 @@ main (int argc, char **argv)
{
progname = "genconstants";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
/* Initializing the MD reader has the side effect of loading up
diff --git a/gcc/genemit.c b/gcc/genemit.c
index 69a3a7d9258..98ec42fe0c3 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -833,7 +833,7 @@ main (int argc, char **argv)
progname = "genemit";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
/* Assign sequential codes to all entries in the machine description
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 289bc093235..2bf9779f381 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -410,7 +410,7 @@ main (int argc, char **argv)
progname = "genextract";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
/* Read the machine description. */
diff --git a/gcc/genflags.c b/gcc/genflags.c
index 6f0fdf1f941..f3cffe8746d 100644
--- a/gcc/genflags.c
+++ b/gcc/genflags.c
@@ -262,7 +262,7 @@ main (int argc, char **argv)
direct calls to their generators in C code. */
insn_elision = 0;
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genflags'");
diff --git a/gcc/genmddeps.c b/gcc/genmddeps.c
index fb5c3113e54..f9fdacb4a95 100644
--- a/gcc/genmddeps.c
+++ b/gcc/genmddeps.c
@@ -20,8 +20,9 @@
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
-#include "gensupport.h"
#include "errors.h"
+#include "read-md.h"
+#include "gensupport.h"
struct filedep
@@ -49,7 +50,7 @@ main (int argc, char **argv)
progname = "genmddeps";
include_callback = add_filedep;
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
*last = NULL;
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index d28baabba7f..d0ec274842a 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -472,7 +472,7 @@ main (int argc, char **argv)
progname = "genopinit";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
printf ("/* Generated automatically by the program `genopinit'\n\
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index c3ce33db65b..a8ab275bff9 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -1002,7 +1002,7 @@ main (int argc, char **argv)
progname = "genoutput";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
output_prologue ();
diff --git a/gcc/genpeep.c b/gcc/genpeep.c
index 0fec59f317c..b129f94b020 100644
--- a/gcc/genpeep.c
+++ b/gcc/genpeep.c
@@ -358,7 +358,7 @@ main (int argc, char **argv)
progname = "genpeep";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
printf ("/* Generated automatically by the program `genpeep'\n\
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index cd538457353..c69647042c7 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -1393,7 +1393,7 @@ main (int argc, char **argv)
progname = argv[0];
if (argc <= 1)
fatal ("no input file name");
- if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args_cb (argc, argv, parse_option))
return FATAL_EXIT_CODE;
while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index a5e069f2dac..26c2a95bbc5 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -2708,7 +2708,7 @@ main (int argc, char **argv)
memset (&split_tree, 0, sizeof split_tree);
memset (&peephole2_tree, 0, sizeof peephole2_tree);
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
next_insn_code = 0;
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index df0ad5f352b..1389658609c 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -35,12 +35,6 @@ int target_flags;
int insn_elision = 1;
-const char *in_fname;
-
-/* This callback will be invoked whenever an rtl include directive is
- processed. To be used for creation of the dependency file. */
-void (*include_callback) (const char *);
-
static struct obstack obstack;
struct obstack *rtl_obstack = &obstack;
@@ -52,8 +46,6 @@ static const char *predicable_false;
static htab_t condition_table;
-static char *base_dir = NULL;
-
/* We initially queue all patterns, process the define_insn and
define_cond_exec patterns, then return them one at a time. */
@@ -82,22 +74,6 @@ static struct queue_elem **other_tail = &other_queue;
static struct queue_elem *queue_pattern (rtx, struct queue_elem ***,
const char *, int);
-/* Current maximum length of directory names in the search path
- for include files. (Altered as we get more of them.) */
-
-size_t max_include_len;
-
-struct file_name_list
- {
- struct file_name_list *next;
- const char *fname;
- };
-
-struct file_name_list *first_dir_md_include = 0; /* First dir to search */
- /* First dir to search for <file> */
-struct file_name_list *first_bracket_include = 0;
-struct file_name_list *last_dir_md_include = 0; /* Last in chain */
-
static void remove_constraints (rtx);
static void process_rtx (rtx, int);
@@ -114,8 +90,6 @@ static const char *alter_output_for_insn (struct queue_elem *,
int, int);
static void process_one_cond_exec (struct queue_elem *);
static void process_define_cond_exec (void);
-static void process_include (rtx, int);
-static char *save_string (const char *, int);
static void init_predicate_table (void);
static void record_insn_name (int, const char *);
@@ -183,76 +157,6 @@ remove_constraints (rtx part)
}
}
-/* Process an include file assuming that it lives in gcc/config/{target}/
- if the include looks like (include "file"). */
-
-static void
-process_include (rtx desc, int lineno)
-{
- const char *filename = XSTR (desc, 0);
- const char *old_filename;
- int old_lineno;
- char *pathname;
- FILE *input_file, *old_file;
-
- /* If specified file name is absolute, skip the include stack. */
- if (! IS_ABSOLUTE_PATH (filename))
- {
- struct file_name_list *stackp;
-
- /* Search directory path, trying to open the file. */
- for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
- {
- static const char sep[2] = { DIR_SEPARATOR, '\0' };
-
- pathname = concat (stackp->fname, sep, filename, NULL);
- input_file = fopen (pathname, "r");
- if (input_file != NULL)
- goto success;
- free (pathname);
- }
- }
-
- if (base_dir)
- pathname = concat (base_dir, filename, NULL);
- else
- pathname = xstrdup (filename);
- input_file = fopen (pathname, "r");
- if (input_file == NULL)
- {
- free (pathname);
- error_with_line (lineno, "include file `%s' not found", filename);
- return;
- }
- success:
-
- /* Save old cursor; setup new for the new file. Note that "lineno" the
- argument to this function is the beginning of the include statement,
- while read_md_lineno has already been advanced. */
- old_file = read_md_file;
- old_filename = read_md_filename;
- old_lineno = read_md_lineno;
- read_md_file = input_file;
- read_md_filename = pathname;
- read_md_lineno = 1;
-
- if (include_callback)
- include_callback (pathname);
-
- /* Read the entire file. */
- while (read_rtx (&desc, &lineno))
- process_rtx (desc, lineno);
-
- /* Do not free pathname. It is attached to the various rtx queue
- elements. */
-
- read_md_file = old_file;
- read_md_filename = old_filename;
- read_md_lineno = old_lineno;
-
- fclose (input_file);
-}
-
/* Process a top level rtx in some way, queuing as appropriate. */
static void
@@ -281,10 +185,6 @@ process_rtx (rtx desc, int lineno)
queue_pattern (desc, &define_pred_tail, read_md_filename, lineno);
break;
- case INCLUDE:
- process_include (desc, lineno);
- break;
-
case DEFINE_INSN_AND_SPLIT:
{
const char *split_cond;
@@ -868,178 +768,46 @@ process_define_cond_exec (void)
for (elem = define_cond_exec_queue; elem ; elem = elem->next)
process_one_cond_exec (elem);
}
+
+/* A read_md_files callback for reading an rtx. */
-static char *
-save_string (const char *s, int len)
+static void
+rtx_handle_directive (int lineno, const char *rtx_name)
{
- char *result = XNEWVEC (char, len + 1);
+ rtx queue, x;
- memcpy (result, s, len);
- result[len] = 0;
- return result;
+ if (read_rtx (rtx_name, &queue))
+ for (x = queue; x; x = XEXP (x, 1))
+ process_rtx (XEXP (x, 0), lineno);
}
-
/* The entry point for initializing the reader. */
-int
-init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
+bool
+init_rtx_reader_args_cb (int argc, char **argv,
+ bool (*parse_opt) (const char *))
{
- int c, i, lineno;
- char *lastsl;
- rtx desc;
- bool no_more_options;
- bool already_read_stdin;
-
- /* Unlock the stdio streams. */
- unlock_std_streams ();
-
- /* First we loop over all the options. */
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- continue;
-
- c = argv[i][1];
- switch (c)
- {
- case 'I': /* Add directory to path for includes. */
- {
- struct file_name_list *dirtmp;
-
- dirtmp = XNEW (struct file_name_list);
- dirtmp->next = 0; /* New one goes on the end */
- if (first_dir_md_include == 0)
- first_dir_md_include = dirtmp;
- else
- last_dir_md_include->next = dirtmp;
- last_dir_md_include = dirtmp; /* Tail follows the last one */
- if (argv[i][1] == 'I' && argv[i][2] != 0)
- dirtmp->fname = argv[i] + 2;
- else if (i + 1 == argc)
- fatal ("directory name missing after -I option");
- else
- dirtmp->fname = argv[++i];
- if (strlen (dirtmp->fname) > max_include_len)
- max_include_len = strlen (dirtmp->fname);
- }
- break;
-
- case '\0':
- /* An argument consisting of exactly one dash is a request to
- read stdin. This will be handled in the second loop. */
- continue;
-
- case '-':
- /* An argument consisting of just two dashes causes option
- parsing to cease. */
- if (argv[i][2] == '\0')
- goto stop_parsing_options;
-
- default:
- /* The program may have provided a callback so it can
- accept its own options. */
- if (parse_opt && parse_opt (argv[i]))
- break;
-
- fatal ("invalid option `%s'", argv[i]);
- }
- }
-
- stop_parsing_options:
-
/* Prepare to read input. */
condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
init_predicate_table ();
obstack_init (rtl_obstack);
sequence_num = 0;
- no_more_options = false;
- already_read_stdin = false;
-
- /* Now loop over all input files. */
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] == '-')
- {
- if (argv[i][1] == '\0')
- {
- /* Read stdin. */
- if (already_read_stdin)
- fatal ("cannot read standard input twice");
-
- base_dir = NULL;
- read_md_file = stdin;
- read_md_filename = in_fname = "<stdin>";
- read_md_lineno = 1;
- already_read_stdin = true;
-
- while (read_rtx (&desc, &lineno))
- process_rtx (desc, lineno);
- fclose (read_md_file);
- continue;
- }
- else if (argv[i][1] == '-' && argv[i][2] == '\0')
- {
- /* No further arguments are to be treated as options. */
- no_more_options = true;
- continue;
- }
- else if (!no_more_options)
- continue;
- }
-
- /* If we get here we are looking at a non-option argument, i.e.
- a file to be processed. */
-
- in_fname = argv[i];
- lastsl = strrchr (in_fname, '/');
- if (lastsl != NULL)
- base_dir = save_string (in_fname, lastsl - in_fname + 1 );
- else
- base_dir = NULL;
-
- read_md_file = fopen (in_fname, "r");
- if (read_md_file == 0)
- {
- perror (in_fname);
- return FATAL_EXIT_CODE;
- }
- read_md_filename = in_fname;
- read_md_lineno = 1;
-
- while (read_rtx (&desc, &lineno))
- process_rtx (desc, lineno);
- fclose (read_md_file);
- }
-
- /* If we get to this point without having seen any files to process,
- read standard input now. */
- if (!in_fname)
- {
- base_dir = NULL;
- read_md_file = stdin;
- read_md_filename = in_fname = "<stdin>";
- read_md_lineno = 1;
-
- while (read_rtx (&desc, &lineno))
- process_rtx (desc, lineno);
- fclose (read_md_file);
- }
+ read_md_files (argc, argv, parse_opt, rtx_handle_directive);
/* Process define_cond_exec patterns. */
if (define_cond_exec_queue != NULL)
process_define_cond_exec ();
- return have_error ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
+ return !have_error;
}
/* Programs that don't have their own options can use this entry point
instead. */
-int
-init_md_reader_args (int argc, char **argv)
+bool
+init_rtx_reader_args (int argc, char **argv)
{
- return init_md_reader_args_cb (argc, argv, 0);
+ return init_rtx_reader_args_cb (argc, argv, 0);
}
/* The entry point for reading a single rtx from an md file. */
diff --git a/gcc/gensupport.h b/gcc/gensupport.h
index 3e916bef99f..f2fcce56ea3 100644
--- a/gcc/gensupport.h
+++ b/gcc/gensupport.h
@@ -23,10 +23,9 @@ along with GCC; see the file COPYING3. If not see
struct obstack;
extern struct obstack *rtl_obstack;
-extern const char *in_fname;
-extern int init_md_reader_args_cb (int, char **, bool (*)(const char *));
-extern int init_md_reader_args (int, char **);
+extern bool init_rtx_reader_args_cb (int, char **, bool (*)(const char *));
+extern bool init_rtx_reader_args (int, char **);
extern rtx read_md_rtx (int *, int *);
/* Set this to 0 to disable automatic elision of insn patterns which
@@ -84,8 +83,4 @@ extern void add_predicate (struct pred_data *);
#define FOR_ALL_PREDICATES(p) for (p = first_predicate; p; p = p->next)
-/* This callback will be invoked whenever an rtl include directive is
- processed. To be used for creation of the dependency file. */
-extern void (*include_callback) (const char *);
-
#endif /* GCC_GENSUPPORT_H */
diff --git a/gcc/read-md.c b/gcc/read-md.c
index 140292189fb..0071e28b471 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -34,6 +34,12 @@ struct ptr_loc {
int lineno;
};
+/* A singly-linked list of filenames. */
+struct file_name_list {
+ struct file_name_list *next;
+ const char *fname;
+};
+
/* Obstack used for allocating MD strings. */
struct obstack string_obstack;
@@ -62,10 +68,32 @@ const char *read_md_filename;
/* The current line number in READ_MD_FILE. */
int read_md_lineno;
+/* The name of the toplevel file that indirectly included READ_MD_FILE. */
+const char *in_fname;
+
+/* The directory part of IN_FNAME. NULL if IN_FNAME is a bare filename. */
+static char *base_dir;
+
+/* The first directory to search. */
+static struct file_name_list *first_dir_md_include;
+
+/* A pointer to the null terminator of the md include chain. */
+static struct file_name_list **last_dir_md_include_ptr = &first_dir_md_include;
+
+/* This callback will be invoked whenever an md include directive is
+ processed. To be used for creation of the dependency file. */
+void (*include_callback) (const char *);
+
+/* The current maximum length of directory names in the search path
+ for include files. (Altered as we get more of them.) */
+static size_t max_include_len;
+
/* A table of md_constant structures, hashed by name. Null if no
constant expansion should occur. */
static htab_t md_constants;
+static void handle_file (directive_handler_t);
+
/* Given an object that starts with a char * name field, return a hash
code for its name. */
@@ -597,8 +625,8 @@ scan_comma_elt (const char **pstr)
/* Process a define_constants directive, starting with the optional space
after the "define_constants". */
-void
-read_constants (void)
+static void
+handle_constants (void)
{
int c;
htab_t defs;
@@ -648,9 +676,6 @@ read_constants (void)
fatal_expected_char (')', c);
}
md_constants = defs;
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
}
/* For every constant definition, call CALLBACK with two arguments:
@@ -664,14 +689,264 @@ traverse_md_constants (htab_trav callback, void *info)
htab_traverse (md_constants, callback, info);
}
-/* Initialize this file's static data. */
+/* Process an "include" directive, starting with the optional space
+ after the "include". Read in the file and use HANDLE_DIRECTIVE
+ to process each unknown directive. LINENO is the line number on
+ which the "include" occured. */
-void
-init_md_reader (void)
+static void
+handle_include (int lineno, directive_handler_t handle_directive)
{
+ const char *filename;
+ const char *old_filename;
+ int old_lineno;
+ char *pathname;
+ FILE *input_file, *old_file;
+
+ filename = read_string (false);
+ input_file = NULL;
+
+ /* If the specified file name is absolute, skip the include stack. */
+ if (!IS_ABSOLUTE_PATH (filename))
+ {
+ struct file_name_list *stackp;
+
+ /* Search the directory path, trying to open the file. */
+ for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
+ {
+ static const char sep[2] = { DIR_SEPARATOR, '\0' };
+
+ pathname = concat (stackp->fname, sep, filename, NULL);
+ input_file = fopen (pathname, "r");
+ if (input_file != NULL)
+ break;
+ free (pathname);
+ }
+ }
+
+ /* If we haven't managed to open the file yet, try combining the
+ filename with BASE_DIR. */
+ if (input_file == NULL)
+ {
+ if (base_dir)
+ pathname = concat (base_dir, filename, NULL);
+ else
+ pathname = xstrdup (filename);
+ input_file = fopen (pathname, "r");
+ }
+
+ if (input_file == NULL)
+ {
+ free (pathname);
+ error_with_line (lineno, "include file `%s' not found", filename);
+ return;
+ }
+
+ /* Save the old cursor. Note that the LINENO argument to this
+ function is the beginning of the include statement, while
+ read_md_lineno has already been advanced. */
+ old_file = read_md_file;
+ old_filename = read_md_filename;
+ old_lineno = read_md_lineno;
+
+ if (include_callback)
+ include_callback (pathname);
+
+ read_md_file = input_file;
+ read_md_filename = pathname;
+ handle_file (handle_directive);
+
+ /* Restore the old cursor. */
+ read_md_file = old_file;
+ read_md_filename = old_filename;
+ read_md_lineno = old_lineno;
+
+ /* Do not free the pathname. It is attached to the various rtx
+ queue elements. */
+}
+
+/* Process the current file, assuming that read_md_file and
+ read_md_filename are valid. Use HANDLE_DIRECTIVE to handle
+ unknown directives. */
+
+static void
+handle_file (directive_handler_t handle_directive)
+{
+ struct md_name directive;
+ int c, lineno;
+
+ read_md_lineno = 1;
+ while ((c = read_skip_spaces ()) != EOF)
+ {
+ lineno = read_md_lineno;
+ if (c != '(')
+ fatal_expected_char ('(', c);
+
+ read_name (&directive);
+ if (strcmp (directive.string, "define_constants") == 0)
+ handle_constants ();
+ else if (strcmp (directive.string, "include") == 0)
+ handle_include (lineno, handle_directive);
+ else
+ handle_directive (lineno, directive.string);
+
+ c = read_skip_spaces ();
+ if (c != ')')
+ fatal_expected_char (')', c);
+ }
+ fclose (read_md_file);
+}
+
+/* Like handle_file, but for top-level files. Set up in_fname and
+ base_dir accordingly. */
+
+static void
+handle_toplevel_file (directive_handler_t handle_directive)
+{
+ char *lastsl;
+
+ in_fname = read_md_filename;
+ lastsl = strrchr (in_fname, '/');
+ if (lastsl != NULL)
+ base_dir = xstrndup (in_fname, lastsl - in_fname + 1);
+ else
+ base_dir = NULL;
+
+ handle_file (handle_directive);
+}
+
+/* Parse a -I option with argument ARG. */
+
+static void
+parse_include (const char *arg)
+{
+ struct file_name_list *dirtmp;
+
+ dirtmp = XNEW (struct file_name_list);
+ dirtmp->next = 0;
+ dirtmp->fname = arg;
+ *last_dir_md_include_ptr = dirtmp;
+ last_dir_md_include_ptr = &dirtmp->next;
+ if (strlen (dirtmp->fname) > max_include_len)
+ max_include_len = strlen (dirtmp->fname);
+}
+
+/* The main routine for reading .md files. Try to process all the .md
+ files specified on the command line and return true if no error occured.
+
+ ARGC and ARGV are the arguments to main.
+
+ PARSE_OPT, if nonnull, is passed all unknown command-line arguments.
+ It should return true if it recognizes the argument or false if a
+ generic error should be reported.
+
+ The parser calls HANDLE_DIRECTIVE for each unknown directive.
+ See the comment above the directive_handler_t definition for
+ details about the callback's interface. */
+
+bool
+read_md_files (int argc, char **argv, bool (*parse_opt) (const char *),
+ directive_handler_t handle_directive)
+{
+ int i;
+ bool no_more_options;
+ bool already_read_stdin;
+ int num_files;
+
+ /* Initialize global data. */
obstack_init (&string_obstack);
ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
obstack_init (&ptr_loc_obstack);
joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
obstack_init (&joined_conditions_obstack);
+
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
+ /* First we loop over all the options. */
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-')
+ {
+ /* An argument consisting of exactly one dash is a request to
+ read stdin. This will be handled in the second loop. */
+ if (argv[i][1] == '\0')
+ continue;
+
+ /* An argument consisting of just two dashes causes option
+ parsing to cease. */
+ if (argv[i][1] == '-' && argv[i][2] == '\0')
+ break;
+
+ if (argv[i][1] == 'I')
+ {
+ if (argv[i][2] != '\0')
+ parse_include (argv[i] + 2);
+ else if (++i < argc)
+ parse_include (argv[i]);
+ else
+ fatal ("directory name missing after -I option");
+ continue;
+ }
+
+ /* The program may have provided a callback so it can
+ accept its own options. */
+ if (parse_opt && parse_opt (argv[i]))
+ continue;
+
+ fatal ("invalid option `%s'", argv[i]);
+ }
+
+ /* Now loop over all input files. */
+ num_files = 0;
+ no_more_options = false;
+ already_read_stdin = false;
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ if (argv[i][1] == '\0')
+ {
+ /* Read stdin. */
+ if (already_read_stdin)
+ fatal ("cannot read standard input twice");
+
+ read_md_file = stdin;
+ read_md_filename = "<stdin>";
+ handle_toplevel_file (handle_directive);
+ already_read_stdin = true;
+ continue;
+ }
+ else if (argv[i][1] == '-' && argv[i][2] == '\0')
+ {
+ /* No further arguments are to be treated as options. */
+ no_more_options = true;
+ continue;
+ }
+ else if (!no_more_options)
+ continue;
+ }
+
+ /* If we get here we are looking at a non-option argument, i.e.
+ a file to be processed. */
+ read_md_filename = argv[i];
+ read_md_file = fopen (read_md_filename, "r");
+ if (read_md_file == 0)
+ {
+ perror (read_md_filename);
+ return false;
+ }
+ handle_toplevel_file (handle_directive);
+ num_files++;
+ }
+
+ /* If we get to this point without having seen any files to process,
+ read the standard input now. */
+ if (num_files == 0 && !already_read_stdin)
+ {
+ read_md_file = stdin;
+ read_md_filename = "<stdin>";
+ handle_toplevel_file (handle_directive);
+ }
+
+ return !have_error;
}
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 0ebebde057d..bb83468f537 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -41,10 +41,18 @@ struct md_constant {
char *value;
};
+/* A callback that handles a single .md-file directive, up to but not
+ including the closing ')'. It takes two arguments: the line number on
+ which the directive started, and the name of the directive. The next
+ unread character is the optional space after the directive name. */
+typedef void (*directive_handler_t) (int, const char *);
+
+extern const char *in_fname;
extern FILE *read_md_file;
extern int read_md_lineno;
extern const char *read_md_filename;
extern struct obstack string_obstack;
+extern void (*include_callback) (const char *);
/* Read the next character from the MD file. */
@@ -86,6 +94,6 @@ extern char *read_quoted_string (void);
extern char *read_string (int);
extern int n_comma_elts (const char *);
extern const char *scan_comma_elt (const char **);
-extern void read_constants (void);
extern void traverse_md_constants (htab_trav, void *);
-extern void init_md_reader (void);
+extern bool read_md_files (int, char **, bool (*) (const char *),
+ directive_handler_t);
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index a3a9b61753c..d49cbdabf7a 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -117,7 +117,8 @@ static void validate_const_int (const char *);
static int find_iterator (struct iterator_group *, const char *);
static struct mapping *read_mapping (struct iterator_group *, htab_t);
static void check_code_iterator (struct mapping *);
-static rtx read_rtx_1 (struct map_value **);
+static rtx read_rtx_code (const char *, struct map_value **);
+static rtx read_nested_rtx (struct map_value **);
static rtx read_rtx_variadic (struct map_value **, rtx);
/* The mode and code iterator structures. */
@@ -691,9 +692,6 @@ read_conditions (void)
add_c_test (expr, value);
}
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
}
static void
@@ -785,10 +783,6 @@ read_mapping (struct iterator_group *group, htab_t table)
}
while (c != ']');
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
-
return m;
}
@@ -812,74 +806,76 @@ check_code_iterator (struct mapping *iterator)
bellwether_codes[iterator->index] = bellwether;
}
-/* Read an rtx in printed representation from the MD file and store
- its core representation in *X. Also store the line number of the
- opening '(' in *LINENO. Return true on success or false if the
- end of file has been reached.
-
- read_rtx is not used in the compiler proper, but rather in
- the utilities gen*.c that construct C code from machine descriptions. */
+/* Read an rtx-related declaration from the MD file, given that it
+ starts with directive name RTX_NAME. Return true if it expands to
+ one or more rtxes (as defined by rtx.def). When returning true,
+ store the list of rtxes as an EXPR_LIST in *X. */
bool
-read_rtx (rtx *x, int *lineno)
+read_rtx (const char *rtx_name, rtx *x)
{
- static rtx queue_head, queue_next;
- static int queue_lineno;
- int c;
+ static rtx queue_head;
+ struct map_value *mode_maps;
+ struct iterator_traverse_data mtd;
/* Do one-time initialization. */
if (queue_head == 0)
{
- init_md_reader ();
initialize_iterators ();
queue_head = rtx_alloc (EXPR_LIST);
}
- if (queue_next == 0)
+ /* Handle various rtx-related declarations that aren't themselves
+ encoded as rtxes. */
+ if (strcmp (rtx_name, "define_conditions") == 0)
{
- struct map_value *mode_maps;
- struct iterator_traverse_data mtd;
- rtx from_file;
-
- c = read_skip_spaces ();
- if (c == EOF)
- return false;
- unread_char (c);
-
- queue_lineno = read_md_lineno;
- mode_maps = 0;
- from_file = read_rtx_1 (&mode_maps);
- if (from_file == 0)
- return false; /* This confuses a top level (nil) with end of
- file, but a top level (nil) would have
- crashed our caller anyway. */
-
- queue_next = queue_head;
- XEXP (queue_next, 0) = from_file;
- XEXP (queue_next, 1) = 0;
-
- mtd.queue = queue_next;
- mtd.mode_maps = mode_maps;
- mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
- htab_traverse (modes.iterators, apply_iterator_traverse, &mtd);
- htab_traverse (codes.iterators, apply_iterator_traverse, &mtd);
- if (mtd.unknown_mode_attr)
- fatal_with_file_and_line ("undefined attribute '%s' used for mode",
- mtd.unknown_mode_attr);
+ read_conditions ();
+ return false;
}
+ if (strcmp (rtx_name, "define_mode_attr") == 0)
+ {
+ read_mapping (&modes, modes.attrs);
+ return false;
+ }
+ if (strcmp (rtx_name, "define_mode_iterator") == 0)
+ {
+ read_mapping (&modes, modes.iterators);
+ return false;
+ }
+ if (strcmp (rtx_name, "define_code_attr") == 0)
+ {
+ read_mapping (&codes, codes.attrs);
+ return false;
+ }
+ if (strcmp (rtx_name, "define_code_iterator") == 0)
+ {
+ check_code_iterator (read_mapping (&codes, codes.iterators));
+ return false;
+ }
+
+ mode_maps = 0;
+ XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps);
+ XEXP (queue_head, 1) = 0;
- *x = XEXP (queue_next, 0);
- *lineno = queue_lineno;
- queue_next = XEXP (queue_next, 1);
+ mtd.queue = queue_head;
+ mtd.mode_maps = mode_maps;
+ mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
+ htab_traverse (modes.iterators, apply_iterator_traverse, &mtd);
+ htab_traverse (codes.iterators, apply_iterator_traverse, &mtd);
+ if (mtd.unknown_mode_attr)
+ fatal_with_file_and_line ("undefined attribute '%s' used for mode",
+ mtd.unknown_mode_attr);
+ *x = queue_head;
return true;
}
-/* Subroutine of read_rtx that reads one construct from the MD file but
- doesn't apply any iterators. */
+/* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of
+ either an rtx code or a code iterator. Parse the rest of the rtx and
+ return it. MODE_MAPS is as for iterator_traverse_data. */
static rtx
-read_rtx_1 (struct map_value **mode_maps)
+read_rtx_code (const char *code_name, struct map_value **mode_maps)
{
int i;
RTX_CODE real_code, bellwether_code;
@@ -897,55 +893,7 @@ read_rtx_1 (struct map_value **mode_maps)
rtx value; /* Value of this node. */
};
- again:
- c = read_skip_spaces (); /* Should be open paren. */
-
- if (c == EOF)
- return 0;
-
- if (c != '(')
- fatal_expected_char ('(', c);
-
- read_name (&name);
- if (strcmp (name.string, "nil") == 0)
- {
- /* (nil) stands for an expression that isn't there. */
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
- return 0;
- }
- if (strcmp (name.string, "define_constants") == 0)
- {
- read_constants ();
- goto again;
- }
- if (strcmp (name.string, "define_conditions") == 0)
- {
- read_conditions ();
- goto again;
- }
- if (strcmp (name.string, "define_mode_attr") == 0)
- {
- read_mapping (&modes, modes.attrs);
- goto again;
- }
- if (strcmp (name.string, "define_mode_iterator") == 0)
- {
- read_mapping (&modes, modes.iterators);
- goto again;
- }
- if (strcmp (name.string, "define_code_attr") == 0)
- {
- read_mapping (&codes, codes.attrs);
- goto again;
- }
- if (strcmp (name.string, "define_code_iterator") == 0)
- {
- check_code_iterator (read_mapping (&codes, codes.iterators));
- goto again;
- }
- real_code = (enum rtx_code) find_iterator (&codes, name.string);
+ real_code = (enum rtx_code) find_iterator (&codes, code_name);
bellwether_code = BELLWETHER_CODE (real_code);
/* If we end up with an insn expression then we free this space below. */
@@ -983,7 +931,7 @@ read_rtx_1 (struct map_value **mode_maps)
case 'e':
case 'u':
- XEXP (return_rtx, i) = read_rtx_1 (mode_maps);
+ XEXP (return_rtx, i) = read_nested_rtx (mode_maps);
break;
case 'V':
@@ -1017,7 +965,7 @@ read_rtx_1 (struct map_value **mode_maps)
fatal_expected_char (']', c);
unread_char (c);
list_counter++;
- obstack_ptr_grow (&vector_stack, read_rtx_1 (mode_maps));
+ obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps));
}
if (list_counter > 0)
{
@@ -1122,16 +1070,40 @@ read_rtx_1 (struct map_value **mode_maps)
}
c = read_skip_spaces ();
+ /* Syntactic sugar for AND and IOR, allowing Lisp-like
+ arbitrary number of arguments for them. */
+ if (c == '('
+ && (GET_CODE (return_rtx) == AND
+ || GET_CODE (return_rtx) == IOR))
+ return read_rtx_variadic (mode_maps, return_rtx);
+
+ unread_char (c);
+ return return_rtx;
+}
+
+/* Read a nested rtx construct from the MD file and return it.
+ MODE_MAPS is as for iterator_traverse_data. */
+
+static rtx
+read_nested_rtx (struct map_value **mode_maps)
+{
+ struct md_name name;
+ int c;
+ rtx return_rtx;
+
+ c = read_skip_spaces ();
+ if (c != '(')
+ fatal_expected_char ('(', c);
+
+ read_name (&name);
+ if (strcmp (name.string, "nil") == 0)
+ return_rtx = NULL;
+ else
+ return_rtx = read_rtx_code (name.string, mode_maps);
+
+ c = read_skip_spaces ();
if (c != ')')
- {
- /* Syntactic sugar for AND and IOR, allowing Lisp-like
- arbitrary number of arguments for them. */
- if (c == '(' && (GET_CODE (return_rtx) == AND
- || GET_CODE (return_rtx) == IOR))
- return read_rtx_variadic (mode_maps, return_rtx);
- else
- fatal_expected_char (')', c);
- }
+ fatal_expected_char (')', c);
return return_rtx;
}
@@ -1156,16 +1128,13 @@ read_rtx_variadic (struct map_value **mode_maps, rtx form)
PUT_MODE (q, GET_MODE (p));
XEXP (q, 0) = XEXP (p, 1);
- XEXP (q, 1) = read_rtx_1 (mode_maps);
+ XEXP (q, 1) = read_nested_rtx (mode_maps);
XEXP (p, 1) = q;
p = q;
c = read_skip_spaces ();
}
while (c == '(');
-
- if (c != ')')
- fatal_expected_char (')', c);
-
+ unread_char (c);
return form;
}
diff --git a/gcc/rtl.def b/gcc/rtl.def
index c9ef1af001a..8464d32e7f9 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -715,9 +715,6 @@ DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA)
descriptions. */
#ifdef GENERATOR_FILE
-/* Include a secondary machine-description file at this point. */
-DEF_RTL_EXPR(INCLUDE, "include", "s", RTX_EXTRA)
-
/* Pattern-matching operators: */
/* Use the function named by the second arg (the string)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5826496fd89..6be88d16ed3 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2357,7 +2357,7 @@ extern void init_varasm_once (void);
extern rtx make_debug_expr_from_rtl (const_rtx);
/* In read-rtl.c */
-extern bool read_rtx (rtx *, int *);
+extern bool read_rtx (const char *, rtx *);
/* In alias.c */
extern rtx canon_rtx (rtx);