#include "obstack.h"
#include "errors.h"
#include "hashtab.h"
+#include "read-md.h"
#include "gensupport.h"
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;
static int sequence_num;
-static int errors;
static int predicable_default;
static const char *predicable_true;
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. */
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);
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 *);
\f
-void
-message_with_line (int lineno, const char *msg, ...)
-{
- va_list ap;
-
- va_start (ap, msg);
-
- fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
- vfprintf (stderr, msg, ap);
- fputc ('\n', stderr);
-
- va_end (ap);
-}
-
/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
the gensupport programs. */
}
}
-/* 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;
-
- /* 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);
- message_with_line (lineno, "include file `%s' not found", filename);
- errors = 1;
- 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_rtx_lineno has already been advanced. */
- old_filename = read_rtx_filename;
- old_lineno = read_rtx_lineno;
- read_rtx_filename = pathname;
- read_rtx_lineno = 1;
-
- if (include_callback)
- include_callback (pathname);
-
- /* Read the entire file. */
- while (read_rtx (input_file, &desc, &lineno))
- process_rtx (desc, lineno);
-
- /* Do not free pathname. It is attached to the various rtx queue
- elements. */
-
- read_rtx_filename = old_filename;
- read_rtx_lineno = old_lineno;
-
- fclose (input_file);
-}
-
/* Process a top level rtx in some way, queuing as appropriate. */
static void
switch (GET_CODE (desc))
{
case DEFINE_INSN:
- queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
+ queue_pattern (desc, &define_insn_tail, read_md_filename, lineno);
break;
case DEFINE_COND_EXEC:
- queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
+ queue_pattern (desc, &define_cond_exec_tail, read_md_filename, lineno);
break;
case DEFINE_ATTR:
- queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
+ case DEFINE_ENUM_ATTR:
+ queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
break;
case DEFINE_PREDICATE:
case DEFINE_REGISTER_CONSTRAINT:
case DEFINE_MEMORY_CONSTRAINT:
case DEFINE_ADDRESS_CONSTRAINT:
- queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
- break;
-
- case INCLUDE:
- process_include (desc, lineno);
+ queue_pattern (desc, &define_pred_tail, read_md_filename, lineno);
break;
case DEFINE_INSN_AND_SPLIT:
split_cond = XSTR (desc, 4);
if (split_cond[0] == '&' && split_cond[1] == '&')
{
- copy_rtx_ptr_loc (split_cond + 2, split_cond);
+ copy_md_ptr_loc (split_cond + 2, split_cond);
split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
}
XSTR (split, 1) = split_cond;
/* Queue them. */
insn_elem
- = queue_pattern (desc, &define_insn_tail, read_rtx_filename,
+ = queue_pattern (desc, &define_insn_tail, read_md_filename,
lineno);
split_elem
- = queue_pattern (split, &other_tail, read_rtx_filename, lineno);
+ = queue_pattern (split, &other_tail, read_md_filename, lineno);
insn_elem->split = split_elem;
break;
}
default:
- queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
+ queue_pattern (desc, &other_tail, read_md_filename, lineno);
break;
}
}
case SET_ATTR_ALTERNATIVE:
if (strcmp (XSTR (sub, 0), "predicable") == 0)
{
- message_with_line (elem->lineno,
- "multiple alternatives for `predicable'");
- errors = 1;
+ error_with_line (elem->lineno,
+ "multiple alternatives for `predicable'");
return 0;
}
break;
/* ??? It would be possible to handle this if we really tried.
It's not easy though, and I'm not going to bother until it
really proves necessary. */
- message_with_line (elem->lineno,
- "non-constant value for `predicable'");
- errors = 1;
+ error_with_line (elem->lineno,
+ "non-constant value for `predicable'");
return 0;
default:
to do this. Delay this until we've got the basics solid. */
if (strchr (value, ',') != NULL)
{
- message_with_line (elem->lineno,
- "multiple alternatives for `predicable'");
- errors = 1;
+ error_with_line (elem->lineno, "multiple alternatives for `predicable'");
return 0;
}
if (strcmp (value, predicable_false) == 0)
return 0;
- message_with_line (elem->lineno,
- "unknown value `%s' for `predicable' attribute",
- value);
- errors = 1;
+ error_with_line (elem->lineno,
+ "unknown value `%s' for `predicable' attribute", value);
return 0;
}
if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
goto found;
- message_with_line (define_cond_exec_queue->lineno,
- "attribute `predicable' not defined");
- errors = 1;
+ error_with_line (define_cond_exec_queue->lineno,
+ "attribute `predicable' not defined");
return;
found:
p_true = strchr (p_false, ',');
if (p_true == NULL || strchr (++p_true, ',') != NULL)
{
- message_with_line (elem->lineno,
- "attribute `predicable' is not a boolean");
- errors = 1;
+ error_with_line (elem->lineno, "attribute `predicable' is not a boolean");
if (p_false)
free (p_false);
return;
break;
case CONST:
- message_with_line (elem->lineno,
- "attribute `predicable' cannot be const");
- errors = 1;
+ error_with_line (elem->lineno, "attribute `predicable' cannot be const");
if (p_false)
free (p_false);
return;
default:
- message_with_line (elem->lineno,
- "attribute `predicable' must have a constant default");
- errors = 1;
+ error_with_line (elem->lineno,
+ "attribute `predicable' must have a constant default");
if (p_false)
free (p_false);
return;
predicable_default = 0;
else
{
- message_with_line (elem->lineno,
- "unknown value `%s' for `predicable' attribute",
- value);
- errors = 1;
+ error_with_line (elem->lineno,
+ "unknown value `%s' for `predicable' attribute", value);
if (p_false)
free (p_false);
}
if (n_alternatives (c) != 1)
{
- message_with_line (lineno,
- "too many alternatives for operand %d",
- XINT (pattern, 0));
- errors = 1;
+ error_with_line (lineno, "too many alternatives for operand %d",
+ XINT (pattern, 0));
return NULL;
}
if (XVECLEN (ce_elem->data, 0) != 1)
{
- message_with_line (ce_elem->lineno,
- "too many patterns in predicate");
- errors = 1;
+ error_with_line (ce_elem->lineno, "too many patterns in predicate");
return;
}
XVECEXP (split, 2, i) = pattern;
}
/* Add the new split to the queue. */
- queue_pattern (split, &other_tail, read_rtx_filename,
+ queue_pattern (split, &other_tail, read_md_filename,
insn_elem->split->lineno);
}
}
struct queue_elem *elem;
identify_predicable_attribute ();
- if (errors)
+ if (have_error)
return;
for (elem = define_cond_exec_queue; elem ; elem = elem->next)
process_one_cond_exec (elem);
}
+\f
+/* 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);
}
-\f
/* 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 *))
{
- FILE *input_file;
- 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);
- errors = 0;
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_rtx_filename = in_fname = "<stdin>";
- read_rtx_lineno = 1;
- input_file = stdin;
- already_read_stdin = true;
-
- while (read_rtx (input_file, &desc, &lineno))
- process_rtx (desc, lineno);
- fclose (input_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_rtx_filename = in_fname;
- read_rtx_lineno = 1;
- input_file = fopen (in_fname, "r");
- if (input_file == 0)
- {
- perror (in_fname);
- return FATAL_EXIT_CODE;
- }
- while (read_rtx (input_file, &desc, &lineno))
- process_rtx (desc, lineno);
- fclose (input_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_rtx_filename = in_fname = "<stdin>";
- read_rtx_lineno = 1;
- input_file = stdin;
-
- while (read_rtx (input_file, &desc, &lineno))
- process_rtx (desc, lineno);
- fclose (input_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 errors ? 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);
}
\f
/* The entry point for reading a single rtx from an md file. */
elem = *queue;
*queue = elem->next;
desc = elem->data;
- read_rtx_filename = elem->filename;
+ read_md_filename = elem->filename;
*lineno = elem->lineno;
*seqnr = sequence_num;
htab_traverse (condition_table, callback, info);
}
-
-/* Given a string, return the number of comma-separated elements in it.
- Return 0 for the null string. */
-int
-n_comma_elts (const char *s)
-{
- int n;
-
- if (*s == '\0')
- return 0;
-
- for (n = 1; *s; s++)
- if (*s == ',')
- n++;
-
- return n;
-}
-
-/* Given a pointer to a (char *), return a pointer to the beginning of the
- next comma-separated element in the string. Advance the pointer given
- to the end of that element. Return NULL if at end of string. Caller
- is responsible for copying the string if necessary. White space between
- a comma and an element is ignored. */
-
-const char *
-scan_comma_elt (const char **pstr)
-{
- const char *start;
- const char *p = *pstr;
-
- if (*p == ',')
- p++;
- while (ISSPACE(*p))
- p++;
-
- if (*p == '\0')
- return NULL;
-
- start = p;
-
- while (*p != ',' && *p != '\0')
- p++;
-
- *pstr = p;
- return start;
-}
-
/* Helper functions for define_predicate and define_special_predicate
processing. Shared between genrecog.c and genpreds.c. */