loongarch gas resolving constant expressions

Message ID Z_880fh07f7qtwN7@squeak.grove.modra.org
State New
Headers
Series loongarch gas resolving constant expressions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed

Commit Message

Alan Modra April 16, 2025, 5:14 a.m. UTC
  The test added in commit 4fe96ddaf614 results in an asan complaint:
loongarch-parse.y:225:16: runtime error: left shift of negative value -1
To avoid the complaint, perform left shifts as unsigned (which gives
the same result on 2's complement machines).  Do the same for
addition, subtraction and multiplication.  Furthermore, warn on
divide/modulus by zero.

OK?
  

Comments

Lulu Cai April 17, 2025, 7:31 a.m. UTC | #1
On 4/16/25 1:14 PM, Alan Modra wrote:
> The test added in commit 4fe96ddaf614 results in an asan complaint:
> loongarch-parse.y:225:16: runtime error: left shift of negative value -1
> To avoid the complaint, perform left shifts as unsigned (which gives
> the same result on 2's complement machines).  Do the same for
> addition, subtraction and multiplication.  Furthermore, warn on
> divide/modulus by zero.
>
> OK?

We think it's OK. Thanks.

> diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y
> index 97055fe42c3..b75040c14b1 100644
> --- a/gas/config/loongarch-parse.y
> +++ b/gas/config/loongarch-parse.y
> @@ -207,29 +207,41 @@ emit_bin (int op)
>         switch (op)
>   	{
>   	case '*':
> -	  opr1 = opr1 * opr2;
> +	  opr1 = (valueT) opr1 * (valueT) opr2;
>   	  break;
>   	case '/':
> -	  opr1 = opr1 / opr2;
> +	  if (opr2 == 0)
> +	    {
> +	      as_warn (_("Divide by zero!"));
> +	      opr1 = 0;
> +	    }
> +	  else
> +	    opr1 = opr1 / opr2;
>   	  break;
>   	case '%':
> -	  opr1 = opr1 % opr2;
> +	  if (opr2 == 0)
> +	    {
> +	      as_warn (_("Divide by zero!"));
> +	      opr1 = 0;
> +	    }
> +	  else
> +	    opr1 = opr1 % opr2;
>   	  break;
>   	case '+':
> -	  opr1 = opr1 + opr2;
> +	  opr1 = (valueT) opr1 + (valueT) opr2;
>   	  break;
>   	case '-':
> -	  opr1 = opr1 - opr2;
> +	  opr1 = (valueT) opr1 - (valueT) opr2;
>   	  break;
>   	case LEFT_OP:
> -	  opr1 = opr1 << opr2;
> +	  opr1 = (valueT) opr1 << opr2;
>   	  break;
>   	case RIGHT_OP:
>   	  if (opr1 < 0)
> -	    as_warn(_("Right shift of negative numbers may be changed "
> -		  "from arithmetic right shift to logical right shift!"));
> -	  /* Algorithm right shift.  */
> -	  opr1 = (offsetT)opr1 >> (offsetT)opr2;
> +	    as_warn (_("Right shift of negative numbers may be changed "
> +		       "from arithmetic right shift to logical right shift!"));
> +	  /* Arithmetic right shift.  */
> +	  opr1 = opr1 >> opr2;
>   	  break;
>   	case '<':
>   	  opr1 = opr1 < opr2;
>
  

Patch

diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y
index 97055fe42c3..b75040c14b1 100644
--- a/gas/config/loongarch-parse.y
+++ b/gas/config/loongarch-parse.y
@@ -207,29 +207,41 @@  emit_bin (int op)
       switch (op)
 	{
 	case '*':
-	  opr1 = opr1 * opr2;
+	  opr1 = (valueT) opr1 * (valueT) opr2;
 	  break;
 	case '/':
-	  opr1 = opr1 / opr2;
+	  if (opr2 == 0)
+	    {
+	      as_warn (_("Divide by zero!"));
+	      opr1 = 0;
+	    }
+	  else
+	    opr1 = opr1 / opr2;
 	  break;
 	case '%':
-	  opr1 = opr1 % opr2;
+	  if (opr2 == 0)
+	    {
+	      as_warn (_("Divide by zero!"));
+	      opr1 = 0;
+	    }
+	  else
+	    opr1 = opr1 % opr2;
 	  break;
 	case '+':
-	  opr1 = opr1 + opr2;
+	  opr1 = (valueT) opr1 + (valueT) opr2;
 	  break;
 	case '-':
-	  opr1 = opr1 - opr2;
+	  opr1 = (valueT) opr1 - (valueT) opr2;
 	  break;
 	case LEFT_OP:
-	  opr1 = opr1 << opr2;
+	  opr1 = (valueT) opr1 << opr2;
 	  break;
 	case RIGHT_OP:
 	  if (opr1 < 0)
-	    as_warn(_("Right shift of negative numbers may be changed "
-		  "from arithmetic right shift to logical right shift!"));
-	  /* Algorithm right shift.  */
-	  opr1 = (offsetT)opr1 >> (offsetT)opr2;
+	    as_warn (_("Right shift of negative numbers may be changed "
+		       "from arithmetic right shift to logical right shift!"));
+	  /* Arithmetic right shift.  */
+	  opr1 = opr1 >> opr2;
 	  break;
 	case '<':
 	  opr1 = opr1 < opr2;