If check fails, genrecog needs to stop and report error, so can let the
issue be found in time. The implementation is referenced from "gcc/doc/
md.log":

  [...]

  whitespace
       Whitespace characters are ignored and can be inserted at any
       position except the first.  This enables each alternative for
       different operands to be visually aligned in the machine
       description even if they have different number of constraints and
       modifiers.

  [...]

  '0', '1', '2', ... '9'
       [...]
       If a digit is used together with letters within the same
       alternative, the digit should come last.

       This number is allowed to be more than a single digit.  If multiple
       digits are encountered consecutively, they are interpreted as a
       single decimal integer. [...]

       [...]

       [...]                               Moreover, the digit must be a
       smaller number than the number of the operand that uses it in the
       constraint.

  [...]

  The overall constraint for an operand is made from the letters for this
  operand from the first alternative, a comma, the letters for this
  operand from the second alternative, a comma, and so on until the last
  alternative.

  [...]

The patch passes test:

 - genrecog can report the related issue when cross compiling xtensa.
   And after the related xtensa issue is fixed, genrecog will not report
   error, either.

 - For x86_64-unknown-linux-gnu building all-gcc, it is OK, too.


2015-02-26  Chen Gang  <gang.chen.5...@gmail.com>

        * genrecog.c (validate_pattern): Check matching constraint in
        MATCH_OPERAND and use 'opnu' for all 'XINT (pattern, 0)'.
---
 gcc/genrecog.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 81a0e79..4b508e8 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -503,7 +503,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int 
set_code)
 
        if (code == MATCH_OPERAND)
          {
-           const char constraints0 = XSTR (pattern, 2)[0];
+           int opnu = XINT (pattern, 0);
+           const char *constraints = XSTR (pattern, 2);
+           const char constraints0 = constraints[0];
 
            if (!constraints_supported_in_insn_p (insn))
              {
@@ -525,17 +527,46 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int 
set_code)
                    /* If we've only got an output reload for this operand,
                       we'd better have a matching input operand.  */
                    else if (constraints0 == '='
-                            && find_matching_operand (insn, XINT (pattern, 0)))
+                            && find_matching_operand (insn, opnu))
                      ;
                    else
                      error_with_line (pattern_lineno,
                                       "operand %d missing in-out reload",
-                                      XINT (pattern, 0));
+                                      opnu);
                  }
                else if (constraints0 != '=' && constraints0 != '+')
                  error_with_line (pattern_lineno,
                                   "operand %d missing output reload",
-                                  XINT (pattern, 0));
+                                  opnu);
+             }
+
+           /* For matching constraint in MATCH_OPERAND, the digit must be a
+              smaller number than the number of the operand that uses it in the
+              constraint.  */
+           while (1)
+             {
+               int val;
+
+               while (constraints[0]
+                      && (constraints[0] < '0' || constraints[0] > '9'))
+                 constraints++;
+               if (!constraints[0])
+                 break;
+
+               sscanf (constraints, "%d", &val);
+               while ((constraints[0] >= '0' && constraints[0] <= '9'))
+                 constraints++;
+
+               while (constraints[0] == ' ')
+                 constraints++;
+               if (constraints[0] && constraints[0] != ',')
+                 continue;
+
+               if (val >= opnu)
+                 error_with_line (pattern_lineno,
+                                  "constraint digit %d is not smaller than"
+                                  " operand %d",
+                                  val, opnu);
              }
          }
 
-- 
1.9.3

Reply via email to