OSDN Git Service

PR c/29955
[pf3gnuchains/gcc-fork.git] / gcc / read-rtl.c
index 79f4050..4fdda4b 100644 (file)
@@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "rtl.h"
 #include "obstack.h"
 #include "hashtab.h"
+#include "gensupport.h"
 
 static htab_t md_constants;
 
@@ -138,11 +139,13 @@ static void read_escape (FILE *);
 static hashval_t def_hash (const void *);
 static int def_name_eq_p (const void *, const void *);
 static void read_constants (FILE *infile, char *tmp_char);
+static void read_conditions (FILE *infile, char *tmp_char);
 static void validate_const_int (FILE *, const char *);
 static int find_macro (struct macro_group *, const char *, FILE *);
 static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
 static void check_code_macro (struct mapping *, FILE *);
 static rtx read_rtx_1 (FILE *, struct map_value **);
+static rtx read_rtx_variadic (FILE *, struct map_value **, rtx);
 
 /* The mode and code macro structures.  */
 static struct macro_group modes, codes;
@@ -434,7 +437,7 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value,
   /* Create a shallow copy of ORIGINAL.  */
   bellwether_code = BELLWETHER_CODE (GET_CODE (original));
   x = rtx_alloc (bellwether_code);
-  memcpy (x, original, RTX_SIZE (bellwether_code));
+  memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
 
   /* Change the mode or code itself.  */
   group = macro->group;
@@ -883,7 +886,7 @@ read_name (char *str, FILE *infile)
   p = str;
   while (1)
     {
-      if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
+      if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == EOF)
        break;
       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
          || c == '(' || c == '[')
@@ -1205,6 +1208,58 @@ traverse_md_constants (htab_trav callback, void *info)
   if (md_constants)
     htab_traverse (md_constants, callback, info);
 }
+\f
+/* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer
+   suitable to read a name or number into.  Process a
+   define_conditions directive, starting with the optional space after
+   the "define_conditions".  The directive looks like this:
+
+     (define_conditions [
+        (number "string")
+        (number "string")
+        ...
+     ])
+
+   It's not intended to appear in machine descriptions.  It is
+   generated by (the program generated by) genconditions.c, and
+   slipped in at the beginning of the sequence of MD files read by
+   most of the other generators.  */
+static void
+read_conditions (FILE *infile, char *tmp_char)
+{
+  int c;
+
+  c = read_skip_spaces (infile);
+  if (c != '[')
+    fatal_expected_char (infile, '[', c);
+
+  while ( (c = read_skip_spaces (infile)) != ']')
+    {
+      char *expr;
+      int value;
+
+      if (c != '(')
+       fatal_expected_char (infile, '(', c);
+
+      read_name (tmp_char, infile);
+      validate_const_int (infile, tmp_char);
+      value = atoi (tmp_char);
+
+      c = read_skip_spaces (infile);
+      if (c != '"')
+       fatal_expected_char (infile, '"', c);
+      expr = read_quoted_string (infile);
+
+      c = read_skip_spaces (infile);
+      if (c != ')')
+       fatal_expected_char (infile, ')', c);
+
+      add_c_test (expr, value);
+    }
+  c = read_skip_spaces (infile);
+  if (c != ')')
+    fatal_expected_char (infile, ')', c);
+}
 
 static void
 validate_const_int (FILE *infile, const char *string)
@@ -1354,16 +1409,23 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
     {
       struct map_value *mode_maps;
       struct macro_traverse_data mtd;
+      rtx from_file;
 
       c = read_skip_spaces (infile);
       if (c == EOF)
        return false;
       ungetc (c, infile);
 
-      queue_next = queue_head;
       queue_lineno = read_rtx_lineno;
       mode_maps = 0;
-      XEXP (queue_next, 0) = read_rtx_1 (infile, &mode_maps);
+      from_file = read_rtx_1 (infile, &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;
@@ -1412,6 +1474,10 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
 
  again:
   c = read_skip_spaces (infile); /* Should be open paren.  */
+
+  if (c == EOF)
+    return 0;
+  
   if (c != '(')
     fatal_expected_char (infile, '(', c);
 
@@ -1429,6 +1495,11 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
       read_constants (infile, tmp_char);
       goto again;
     }
+  if (strcmp (tmp_char, "define_conditions") == 0)
+    {
+      read_conditions (infile, tmp_char);
+      goto again;
+    }
   if (strcmp (tmp_char, "define_mode_attr") == 0)
     {
       read_mapping (&modes, modes.attrs, infile);
@@ -1626,7 +1697,49 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
 
   c = read_skip_spaces (infile);
   if (c != ')')
-    fatal_expected_char (infile, ')', 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 (infile, mode_maps, return_rtx);
+      else
+       fatal_expected_char (infile, ')', c);
+    }
 
   return return_rtx;
 }
+
+/* Mutually recursive subroutine of read_rtx which reads
+   (thing x1 x2 x3 ...) and produces RTL as if
+   (thing x1 (thing x2 (thing x3 ...)))  had been written.
+   When called, FORM is (thing x1 x2), and the file position
+   is just past the leading parenthesis of x3.  Only works
+   for THINGs which are dyadic expressions, e.g. AND, IOR.  */
+static rtx
+read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form)
+{
+  char c = '(';
+  rtx p = form, q;
+
+  do
+    {
+      ungetc (c, infile);
+
+      q = rtx_alloc (GET_CODE (p));
+      PUT_MODE (q, GET_MODE (p));
+
+      XEXP (q, 0) = XEXP (p, 1);
+      XEXP (q, 1) = read_rtx_1 (infile, mode_maps);
+      
+      XEXP (p, 1) = q;
+      p = q;
+      c = read_skip_spaces (infile);
+    }
+  while (c == '(');
+
+  if (c != ')')
+    fatal_expected_char (infile, ')', c);
+
+  return form;
+}