Makefile.in (build/genmddeps.o): Depend on $(READ_MD_H).

gcc/
	* 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.

From-SVN: r160577
This commit is contained in:
Richard Sandiford 2010-06-10 20:23:13 +00:00 committed by Richard Sandiford
parent 7f7c467fed
commit 600ab3fcfa
25 changed files with 490 additions and 408 deletions

View File

@ -1,3 +1,72 @@
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'.

View File

@ -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) \

View File

@ -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'");

View File

@ -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);

View File

@ -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);

View File

@ -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 ("\

View File

@ -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. */

View File

@ -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'");

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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'");

View File

@ -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;

View File

@ -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\

View File

@ -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 ();

View File

@ -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\

View File

@ -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)

View File

@ -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;

View File

@ -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. */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
*x = XEXP (queue_next, 0);
*lineno = queue_lineno;
queue_next = XEXP (queue_next, 1);
mode_maps = 0;
XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps);
XEXP (queue_head, 1) = 0;
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)
{
@ -1121,17 +1069,41 @@ read_rtx_1 (struct map_value **mode_maps)
gcc_unreachable ();
}
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;
}

View File

@ -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)

View File

@ -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);