[ARC] Improve parsing instruction operands.
authorClaudiu Zissulescu <claziss@gmail.com>
Tue, 7 Jan 2020 13:29:16 +0000 (15:29 +0200)
committerClaudiu Zissulescu <claziss@gmail.com>
Tue, 7 Jan 2020 13:29:31 +0000 (15:29 +0200)
We use gas' expression function to parse the operands of an
instruction in a generic way. There are situations when we have labels
and registers having the same name as well as the substraction sign
doesn't always stands for the arithmetical operation but for the
register range (e.g. enter instruction). This patch improves parsing
symbols found in a instruction operand, cleans up code and avoids
using default or undefined variables.

gas/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

* config/tc-arc.c (parse_reloc_symbol): New function.
(tokenize_arguments): Clean up, use parse_reloc_symbol function.
(md_operand): Set X_md to absent.
(arc_parse_name): Check for X_md.

gas/ChangeLog
gas/config/tc-arc.c

index 5a16b9144aaa2ec23f04b2aeaca3155ba1825946..1c61732fab3b7e693b2bf737dd4195b5c1548d41 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-07  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * onfig/tc-arc.c (parse_reloc_symbol): New function.
+       (tokenize_arguments): Clean up, use parse_reloc_symbol function.
+       (md_operand): Set X_md to absent.
+       (arc_parse_name): Check for X_md.
+
 2020-01-03  Sergey Belyashov  <sergey.belyashov@gmail.com>
 
        PR 25311
index ffccfda05664cd2eb1034a858179395c4f6a7c5d..ed1e3fb5dd5c9504c66e1f377f3d85a4f322a33b 100644 (file)
@@ -1092,6 +1092,102 @@ debug_exp (expressionS *t)
   fflush (stderr);
 }
 
+/* Helper for parsing an argument, used for sorting out the relocation
+   type.  */
+
+static void
+parse_reloc_symbol (expressionS *resultP)
+{
+  char *reloc_name, c, *sym_name;
+  size_t len;
+  int i;
+  const struct arc_reloc_op_tag *r;
+  expressionS right;
+  symbolS *base;
+
+  /* A relocation operand has the following form
+     @identifier@relocation_type.  The identifier is already in
+     tok!  */
+  if (resultP->X_op != O_symbol)
+    {
+      as_bad (_("No valid label relocation operand"));
+      resultP->X_op = O_illegal;
+      return;
+    }
+
+  /* Parse @relocation_type.  */
+  input_line_pointer++;
+  c = get_symbol_name (&reloc_name);
+  len = input_line_pointer - reloc_name;
+  if (len == 0)
+    {
+      as_bad (_("No relocation operand"));
+      resultP->X_op = O_illegal;
+      return;
+    }
+
+  /* Go through known relocation and try to find a match.  */
+  r = &arc_reloc_op[0];
+  for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
+    if (len == r->length
+       && memcmp (reloc_name, r->name, len) == 0)
+      break;
+  if (i < 0)
+    {
+      as_bad (_("Unknown relocation operand: @%s"), reloc_name);
+      resultP->X_op = O_illegal;
+      return;
+    }
+
+  *input_line_pointer = c;
+  SKIP_WHITESPACE_AFTER_NAME ();
+  /* Extra check for TLS: base.  */
+  if (*input_line_pointer == '@')
+    {
+      if (resultP->X_op_symbol != NULL
+         || resultP->X_op != O_symbol)
+       {
+         as_bad (_("Unable to parse TLS base: %s"),
+                 input_line_pointer);
+         resultP->X_op = O_illegal;
+         return;
+       }
+      input_line_pointer++;
+      c = get_symbol_name (&sym_name);
+      base = symbol_find_or_make (sym_name);
+      resultP->X_op = O_subtract;
+      resultP->X_op_symbol = base;
+      restore_line_pointer (c);
+      right.X_add_number = 0;
+    }
+
+  if ((*input_line_pointer != '+')
+      && (*input_line_pointer != '-'))
+    right.X_add_number = 0;
+  else
+    {
+      /* Parse the constant of a complex relocation expression
+        like @identifier@reloc +/- const.  */
+      if (! r->complex_expr)
+       {
+         as_bad (_("@%s is not a complex relocation."), r->name);
+         resultP->X_op = O_illegal;
+         return;
+       }
+      expression (&right);
+      if (right.X_op != O_constant)
+       {
+         as_bad (_("Bad expression: @%s + %s."),
+                 r->name, input_line_pointer);
+         resultP->X_op = O_illegal;
+         return;
+       }
+    }
+
+  resultP->X_md = r->op;
+  resultP->X_add_number = right.X_add_number;
+}
+
 /* Parse the arguments to an opcode.  */
 
 static int
@@ -1104,11 +1200,6 @@ tokenize_arguments (char *str,
   bfd_boolean saw_arg = FALSE;
   int brk_lvl = 0;
   int num_args = 0;
-  int i;
-  size_t len;
-  const struct arc_reloc_op_tag *r;
-  expressionS tmpE;
-  char *reloc_name, c;
 
   memset (tok, 0, sizeof (*tok) * ntok);
 
@@ -1170,95 +1261,21 @@ tokenize_arguments (char *str,
            goto err;
 
          /* Parse @label.  */
+         input_line_pointer++;
          tok->X_op = O_symbol;
          tok->X_md = O_absent;
          expression (tok);
-         if (*input_line_pointer != '@')
-           goto normalsymbol; /* This is not a relocation.  */
-
-       relocationsym:
-
-         /* A relocation operand has the following form
-            @identifier@relocation_type.  The identifier is already
-            in tok!  */
-         if (tok->X_op != O_symbol)
-           {
-             as_bad (_("No valid label relocation operand"));
-             goto err;
-           }
-
-         /* Parse @relocation_type.  */
-         input_line_pointer++;
-         c = get_symbol_name (&reloc_name);
-         len = input_line_pointer - reloc_name;
-         if (len == 0)
-           {
-             as_bad (_("No relocation operand"));
-             goto err;
-           }
-
-         /* Go through known relocation and try to find a match.  */
-         r = &arc_reloc_op[0];
-         for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
-           if (len == r->length
-               && memcmp (reloc_name, r->name, len) == 0)
-             break;
-         if (i < 0)
-           {
-             as_bad (_("Unknown relocation operand: @%s"), reloc_name);
-             goto err;
-           }
 
-         *input_line_pointer = c;
-         SKIP_WHITESPACE_AFTER_NAME ();
-         /* Extra check for TLS: base.  */
          if (*input_line_pointer == '@')
-           {
-             symbolS *base;
-             if (tok->X_op_symbol != NULL
-                 || tok->X_op != O_symbol)
-               {
-                 as_bad (_("Unable to parse TLS base: %s"),
-                         input_line_pointer);
-                 goto err;
-               }
-             input_line_pointer++;
-             char *sym_name;
-             c = get_symbol_name (&sym_name);
-             base = symbol_find_or_make (sym_name);
-             tok->X_op = O_subtract;
-             tok->X_op_symbol = base;
-             restore_line_pointer (c);
-             tmpE.X_add_number = 0;
-           }
-         if ((*input_line_pointer != '+')
-                  && (*input_line_pointer != '-'))
-           {
-             tmpE.X_add_number = 0;
-           }
-         else
-           {
-             /* Parse the constant of a complex relocation expression
-                like @identifier@reloc +/- const.  */
-             if (! r->complex_expr)
-               {
-                 as_bad (_("@%s is not a complex relocation."), r->name);
-                 goto err;
-               }
-             expression (&tmpE);
-             if (tmpE.X_op != O_constant)
-               {
-                 as_bad (_("Bad expression: @%s + %s."),
-                         r->name, input_line_pointer);
-                 goto err;
-               }
-           }
-
-         tok->X_md = r->op;
-         tok->X_add_number = tmpE.X_add_number;
+           parse_reloc_symbol (tok);
 
          debug_exp (tok);
 
+         if (tok->X_op == O_illegal
+              || tok->X_op == O_absent
+              || num_args == ntok)
+           goto err;
+
          saw_comma = FALSE;
          saw_arg = TRUE;
          tok++;
@@ -1282,9 +1299,8 @@ tokenize_arguments (char *str,
             identifier@relocation_type, if it is the case parse the
             relocation type as well.  */
          if (*input_line_pointer == '@')
-           goto relocationsym;
+           parse_reloc_symbol (tok);
 
-       normalsymbol:
          debug_exp (tok);
 
          if (tok->X_op == O_illegal
@@ -3336,16 +3352,18 @@ md_atof (int type, char *litP, int *sizeP)
 
 /* Called for any expression that can not be recognized.  When the
    function is called, `input_line_pointer' will point to the start of
-   the expression.  */
+   the expression.  We use it when we have complex operations like
+   @label1 - @label2.  */
 
 void
-md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
+md_operand (expressionS *expressionP)
 {
   char *p = input_line_pointer;
   if (*p == '@')
     {
       input_line_pointer++;
       expressionP->X_op = O_symbol;
+      expressionP->X_md = O_absent;
       expression (expressionP);
     }
 }
@@ -3364,7 +3382,8 @@ arc_parse_name (const char *name,
   if (!assembling_insn)
     return FALSE;
 
-  if (e->X_op == O_symbol)
+  if (e->X_op == O_symbol
+      && e->X_md == O_absent)
     return FALSE;
 
   sym = hash_find (arc_reg_hash, name);