aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/doc/md.texi75
-rw-r--r--gcc/genattr.c2
-rw-r--r--gcc/genattrtab.c2
-rw-r--r--gcc/gencodes.c2
-rw-r--r--gcc/genconfig.c2
-rw-r--r--gcc/genemit.c2
-rw-r--r--gcc/genextract.c2
-rw-r--r--gcc/genflags.c2
-rw-r--r--gcc/genopinit.c2
-rw-r--r--gcc/genoutput.c2
-rw-r--r--gcc/genpeep.c2
-rw-r--r--gcc/genrecog.c2
-rw-r--r--gcc/gensupport.c243
-rw-r--r--gcc/gensupport.h1
-rw-r--r--gcc/rtl.def5
15 files changed, 334 insertions, 12 deletions
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 0d9bf91..f8ecb2a 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -38,6 +38,7 @@ See the next chapter for information on the C header file.
* Expander Definitions::Generating a sequence of several RTL insns
for a standard operation.
* Insn Splitting:: Splitting Instructions into Multiple Instructions.
+* Including Patterns:: Including Patterns in Machine Descriptions.
* Peephole Definitions::Defining machine-specific peephole optimizations.
* Insn Attributes:: Specifying the value of attributes for generated insns.
* Conditional Execution::Generating @code{define_insn} patterns for
@@ -3910,6 +3911,80 @@ functionality as two separate @code{define_insn} and @code{define_split}
patterns. It exists for compactness, and as a maintenance tool to prevent
having to ensure the two patterns' templates match.
+@node Including Patterns
+@section Including Patterns in Machine Descriptions.
+@cindex insn includes
+
+@findex include
+The @code{include} pattern tells the compiler tools where to
+look for patterns that are in files other than in the file
+@file{.md}. This is used only at build time and there is no preprocessing allowed.
+
+It looks like:
+
+@smallexample
+
+(include
+ @var{pathname})
+@end smallexample
+
+For example:
+
+@smallexample
+
+(include "filestuff")
+
+@end smallexample
+
+Where @var{pathname} is a string that specifies the the location of the file,
+specifies the include file to be in @file{gcc/config/target/filestuff}. The
+directory @file{gcc/config/target} is regarded as the default directory.
+
+
+Machine descriptions may be split up into smaller more manageable subsections
+and placed into subdirectories.
+
+By specifying:
+
+@smallexample
+
+(include "BOGUS/filestuff")
+
+@end smallexample
+
+the include file is specified to be in @file{gcc/config/@var{target}/BOGUS/filestuff}.
+
+Specifying an absolute path for the include file such as;
+@smallexample
+
+(include "/u2/BOGUS/filestuff")
+
+@end smallexample
+is permitted but is not encouraged.
+
+@subsection RTL Generation Tool Options for Directory Search
+@cindex directory options .md
+@cindex options, directory search
+@cindex search options
+
+The @option{-I@var{dir}} option specifies directories to search for machine descriptions.
+For example:
+
+@smallexample
+
+genrecog -I/p1/abc/proc1 -I/p2/abcd/pro2 target.md
+
+@end smallexample
+
+
+Add the directory @var{dir} to the head of the list of directories to be
+searched for header files. This can be used to override a system machine definition
+file, substituting your own version, since these directories are
+searched before the default machine description file directories. If you use more than
+one @option{-I} option, the directories are scanned in left-to-right
+order; the standard default directory come after.
+
+
@node Peephole Definitions
@section Machine-Specific Peephole Optimizers
@cindex peephole optimizer definitions
diff --git a/gcc/genattr.c b/gcc/genattr.c
index be86ca6..4f9c712 100644
--- a/gcc/genattr.c
+++ b/gcc/genattr.c
@@ -210,7 +210,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genattr'");
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index e3748a2..8b65fc8 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -6075,7 +6075,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
obstack_init (hash_obstack);
diff --git a/gcc/gencodes.c b/gcc/gencodes.c
index 735570a..89d4b75 100644
--- a/gcc/gencodes.c
+++ b/gcc/gencodes.c
@@ -56,7 +56,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
puts ("\
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index 27000be..01107ff 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -277,7 +277,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genconfig'");
diff --git a/gcc/genemit.c b/gcc/genemit.c
index 34d6711..7510719 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -789,7 +789,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
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 80602d7..7c11136 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -362,7 +362,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
/* Assign sequential codes to all entries in the machine description
diff --git a/gcc/genflags.c b/gcc/genflags.c
index cd30af1..4bf0511 100644
--- a/gcc/genflags.c
+++ b/gcc/genflags.c
@@ -230,7 +230,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
puts ("/* Generated automatically by the program `genflags'");
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 3907b20..85fa643 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -316,7 +316,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
printf ("/* Generated automatically by the program `genopinit'\n\
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 00b2903..73911ae 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -953,7 +953,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
output_prologue ();
diff --git a/gcc/genpeep.c b/gcc/genpeep.c
index 4f0861f..05c156a 100644
--- a/gcc/genpeep.c
+++ b/gcc/genpeep.c
@@ -385,7 +385,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
printf ("/* Generated automatically by the program `genpeep'\n\
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index f2e6b28..0e7356b 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -2689,7 +2689,7 @@ main (argc, argv)
if (argc <= 1)
fatal ("No input file name.");
- if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
next_insn_code = 0;
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 83be3c7..3660378 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -42,6 +42,8 @@ static int predicable_default;
static const char *predicable_true;
static const char *predicable_false;
+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. */
@@ -62,6 +64,23 @@ static struct queue_elem *other_queue;
static struct queue_elem **other_tail = &other_queue;
static void queue_pattern PARAMS ((rtx, struct queue_elem ***, 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 *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_include = 0; /* Last in chain */
+
static void remove_constraints PARAMS ((rtx));
static void process_rtx PARAMS ((rtx, int));
@@ -78,6 +97,9 @@ static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
int, int));
static void process_one_cond_exec PARAMS ((struct queue_elem *));
static void process_define_cond_exec PARAMS ((void));
+static int process_include PARAMS ((rtx, int));
+static char *save_string PARAMS ((const char *, int));
+static int init_include_reader PARAMS ((FILE *));
void
message_with_line VPARAMS ((int lineno, const char *msg, ...))
@@ -157,6 +179,142 @@ remove_constraints (part)
}
}
+/* The entry point for initializing the reader. */
+
+static int
+init_include_reader (inf)
+ FILE *inf;
+{
+ int c;
+
+ errors = 0;
+
+ /* Read the entire file. */
+ while (1)
+ {
+ rtx desc;
+ int lineno;
+
+ c = read_skip_spaces (inf);
+ if (c == EOF)
+ break;
+
+ ungetc (c, inf);
+ lineno = read_rtx_lineno;
+ desc = read_rtx (inf);
+ process_rtx (desc, lineno);
+ }
+ fclose (inf);
+
+ /* Process define_cond_exec patterns. */
+ if (define_cond_exec_queue != NULL)
+ process_define_cond_exec ();
+
+ return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
+}
+
+/* Process an include file assuming that it lives in gcc/config/{target}/
+ if the include looks line (include "file" ) */
+static int
+process_include (desc, lineno)
+ rtx desc;
+ int lineno;
+{
+ const char *filename = XSTR (desc, 0);
+ char *pathname = NULL;
+ FILE *input_file;
+ char *fname;
+ struct file_name_list *stackp;
+ int flen;
+
+ stackp = include;
+
+ /* If specified file name is absolute, just open it. */
+ if (IS_ABSOLUTE_PATHNAME (filename) || !stackp)
+ {
+ if (base_dir)
+ {
+ pathname = xmalloc (strlen (base_dir) + strlen (filename) + 1);
+ pathname = strcpy (pathname, base_dir);
+ strcat (pathname, filename);
+ strcat (pathname, "\0");
+ }
+ else
+ {
+ pathname = xstrdup (filename);
+ }
+ read_rtx_filename = pathname;
+ input_file = fopen (pathname, "r");
+
+ if (input_file == 0)
+ {
+ perror (pathname);
+ return FATAL_EXIT_CODE;
+ }
+ }
+ else if (stackp)
+ {
+
+ flen = strlen (filename);
+
+ fname = (char *) alloca (max_include_len + flen + 2);
+
+ /* + 2 above for slash and terminating null. */
+
+ /* Search directory path, trying to open the file.
+ Copy each filename tried into FNAME. */
+
+ for (; stackp; stackp = stackp->next)
+ {
+ if (stackp->fname)
+ {
+ strcpy (fname, stackp->fname);
+ strcat (fname, "/");
+ fname[strlen (fname) + flen] = 0;
+ }
+ else
+ {
+ fname[0] = 0;
+ }
+ strncat (fname, (const char *) filename, flen);
+ read_rtx_filename = fname;
+ input_file = fopen (fname, "r");
+ if (input_file != NULL)
+ break;
+ }
+ if (stackp == NULL)
+ {
+ if (strchr (fname, '/') == NULL || strchr (fname, '\\' ) || base_dir)
+ {
+ if (base_dir)
+ {
+ pathname =
+ xmalloc (strlen (base_dir) + strlen (filename) + 1);
+ pathname = strcpy (pathname, base_dir);
+ strcat (pathname, filename);
+ strcat (pathname, "\0");
+ }
+ else
+ pathname = xstrdup (filename);
+ }
+ read_rtx_filename = pathname;
+ input_file = fopen (pathname, "r");
+
+ if (input_file == 0)
+ {
+ perror (filename);
+ return FATAL_EXIT_CODE;
+ }
+ }
+
+ }
+
+ if (init_include_reader (input_file) == FATAL_EXIT_CODE)
+ message_with_line (lineno, "read errors found in include file %s\n", pathname);
+
+ return SUCCESS_EXIT_CODE;
+}
+
/* Process a top level rtx in some way, queueing as appropriate. */
static void
@@ -164,6 +322,8 @@ process_rtx (desc, lineno)
rtx desc;
int lineno;
{
+ const char *filename = XSTR (desc, 0);
+
switch (GET_CODE (desc))
{
case DEFINE_INSN:
@@ -178,6 +338,11 @@ process_rtx (desc, lineno)
queue_pattern (desc, &define_attr_tail, lineno);
break;
+ case INCLUDE:
+ if (process_include (desc, lineno) == FATAL_EXIT_CODE)
+ message_with_line (lineno, "include file at %s not found\n", filename);
+ break;
+
case DEFINE_INSN_AND_SPLIT:
{
const char *split_cond;
@@ -767,6 +932,74 @@ process_define_cond_exec ()
for (elem = define_cond_exec_queue; elem ; elem = elem->next)
process_one_cond_exec (elem);
}
+
+static char *
+save_string (s, len)
+ const char *s;
+ int len;
+{
+ register char *result = xmalloc (len + 1);
+
+ memcpy (result, s, len);
+ result[len] = 0;
+ return result;
+}
+
+
+/* The entry point for initializing the reader. */
+
+int
+init_md_reader_args (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ const char *in_fname;
+
+ max_include_len = 0;
+ in_fname = NULL;
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ if (in_fname == NULL)
+ in_fname = argv[i];
+ }
+ else
+ {
+ int c = argv[i][1];
+ switch (c)
+ {
+ case 'I': /* Add directory to path for includes. */
+ {
+ struct file_name_list *dirtmp;
+
+ dirtmp = (struct file_name_list *)
+ xmalloc (sizeof (struct file_name_list));
+ dirtmp->next = 0; /* New one goes on the end */
+ if (include == 0)
+ include = dirtmp;
+ else
+ last_include->next = dirtmp;
+ last_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;
+ default:
+ fatal ("Invalid option `%s'", argv[i]);
+
+ }
+ }
+ }
+ return init_md_reader (in_fname);
+}
/* The entry point for initializing the reader. */
@@ -776,6 +1009,14 @@ init_md_reader (filename)
{
FILE *input_file;
int c;
+ char *lastsl;
+
+ if (!IS_ABSOLUTE_PATHNAME (filename))
+ {
+ lastsl = strrchr (filename, '/');
+ if (lastsl != NULL)
+ base_dir = save_string (filename, lastsl - filename + 1 );
+ }
read_rtx_filename = filename;
input_file = fopen (filename, "r");
@@ -797,7 +1038,7 @@ init_md_reader (filename)
c = read_skip_spaces (input_file);
if (c == EOF)
- break;
+ break;
ungetc (c, input_file);
lineno = read_rtx_lineno;
diff --git a/gcc/gensupport.h b/gcc/gensupport.h
index 13a9253..96c8c87 100644
--- a/gcc/gensupport.h
+++ b/gcc/gensupport.h
@@ -21,6 +21,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct obstack;
extern struct obstack *rtl_obstack;
+extern int init_md_reader_args PARAMS ((int, char **));
extern int init_md_reader PARAMS ((const char *));
extern rtx read_md_rtx PARAMS ((int *, int *));
diff --git a/gcc/rtl.def b/gcc/rtl.def
index d85fb14..6c887bc 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -73,6 +73,11 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", 'x')
DEF_RTL_EXPR(NIL, "nil", "*", 'x')
+
+/* include a file */
+
+DEF_RTL_EXPR(INCLUDE, "include", "s", 'x')
+
/* ---------------------------------------------------------------------
Expressions used in constructing lists.
--------------------------------------------------------------------- */