[binutils-gdb] gas: apply md_register_arithmetic also to unary '+'

Jan Beulich jbeulich@sourceware.org
Fri Mar 17 09:07:43 GMT 2023


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=529b6c24ff2481b55123703cd25569ca8de717cc

commit 529b6c24ff2481b55123703cd25569ca8de717cc
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Mar 17 10:07:05 2023 +0100

    gas: apply md_register_arithmetic also to unary '+'
    
    Even a unary '+' has to be considered arithmetic; at least on x86 in
    Intel Syntax mode otherwise bogus insn operands may be accepted.
    Convert this specific case to binary + (i.e. 0 + <register>). (An
    implication is that md_operator(,1,) would need to deal with arch-
    specific equivalents of unary '+' is a similar way, if such an arch-
    specific variant would be specified in the first place.)
    
    To avoid duplicating what make_expr_symbol() does to construct a
    constant-zero expression, simply make its previously local variable a
    file-scope static one. This way there's also no need to invoke
    clean_up_expression().

Diff:
---
 gas/expr.c | 25 +++++++++++++++----------
 gas/expr.h |  2 +-
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/gas/expr.c b/gas/expr.c
index ae24c281ba6..afb346ebab3 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -48,15 +48,16 @@ struct expr_symbol_line {
 };
 
 static struct expr_symbol_line *expr_symbol_lines;
+
+static const expressionS zero = { .X_op = O_constant };
 

 /* Build a dummy symbol to hold a complex expression.  This is how we
    build expressions up out of other expressions.  The symbol is put
    into the fake section expr_section.  */
 
 symbolS *
-make_expr_symbol (expressionS *expressionP)
+make_expr_symbol (const expressionS *expressionP)
 {
-  expressionS zero;
   symbolS *symbolP;
   struct expr_symbol_line *n;
 
@@ -73,11 +74,6 @@ make_expr_symbol (expressionS *expressionP)
 	as_bad (_("bignum invalid"));
       else
 	as_bad (_("floating point number invalid"));
-      zero.X_op = O_constant;
-      zero.X_add_number = 0;
-      zero.X_unsigned = 0;
-      zero.X_extrabit = 0;
-      clean_up_expression (&zero);
       expressionP = &zero;
     }
 
@@ -750,6 +746,10 @@ current_location (expressionS *expressionp)
     }
 }
 
+#ifndef md_register_arithmetic
+# define md_register_arithmetic 1
+#endif
+
 /* In:	Input_line_pointer points to 1st char of operand, which may
 	be a space.
 
@@ -1127,6 +1127,14 @@ operand (expressionS *expressionP, enum expr_mode mode)
 		  expressionP->X_op = O_logical_not;
 		expressionP->X_add_number = 0;
 	      }
+	    else if (!md_register_arithmetic && expressionP->X_op == O_register)
+	      {
+		/* Convert to binary '+'.  */
+		expressionP->X_op_symbol = make_expr_symbol (expressionP);
+		expressionP->X_add_symbol = make_expr_symbol (&zero);
+		expressionP->X_add_number = 0;
+		expressionP->X_op = O_add;
+	      }
 	  }
 	else
 	  as_warn (_("Unary operator %c ignored because bad operand follows"),
@@ -1890,9 +1898,6 @@ expr (int rankarg,		/* Larger # is higher rank.  */
 	  ;
 	}
       else
-#endif
-#ifndef md_register_arithmetic
-# define md_register_arithmetic 1
 #endif
       if (op_left == O_add && right.X_op == O_constant
 	  && (md_register_arithmetic || resultP->X_op != O_register))
diff --git a/gas/expr.h b/gas/expr.h
index 8de272f2805..52574bd0115 100644
--- a/gas/expr.h
+++ b/gas/expr.h
@@ -182,7 +182,7 @@ extern void add_to_result (expressionS *, offsetT, int);
 extern void subtract_from_result (expressionS *, offsetT, int);
 extern segT expr (int, expressionS *, enum expr_mode);
 extern unsigned int get_single_number (void);
-extern symbolS *make_expr_symbol (expressionS * expressionP);
+extern symbolS *make_expr_symbol (const expressionS * expressionP);
 extern int expr_symbol_where (symbolS *, const char **, unsigned int *);
 extern void current_location (expressionS *);
 extern symbolS *expr_build_uconstant (offsetT);


More information about the Binutils-cvs mailing list