[binutils-gdb] gas: also maintain signed-ness for O_big expressions
Jan Beulich
jbeulich@sourceware.org
Fri Jun 13 06:40:31 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=023b7811d644a8e3d60b802731a8987232ebb1a0
commit 023b7811d644a8e3d60b802731a8987232ebb1a0
Author: Jan Beulich <jbeulich@suse.com>
Date: Fri Jun 13 08:39:44 2025 +0200
gas: also maintain signed-ness for O_big expressions
Interestingly emit_leb128_expr() already assumes X_unsigned is properly
set for O_big. Adjust its conversion-to-bignum to respect the incoming
flag, and have convert_to_bignum() correctly set it on output.
It further can't be quite right that convert_to_bignum() depends on
anything other than the incoming expression. Therefore adjust
emit_expr_with_reloc() to be in line with the other invocation.
This also requires an adjustment for SH, which really should have been
part of 762acf217c40 ("gas: maintain O_constant signedness in more
cases").
Diff:
---
gas/config/tc-sh.c | 1 +
gas/expr.c | 4 ++++
gas/expr.h | 10 ++++++----
gas/read.c | 11 +++++++----
gas/testsuite/gas/all/octa.d | 8 ++++++++
gas/testsuite/gas/all/octa.s | 10 ++++++++++
6 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c
index 9620eef9e93..c37306f2f58 100644
--- a/gas/config/tc-sh.c
+++ b/gas/config/tc-sh.c
@@ -544,6 +544,7 @@ sh_optimize_expr (expressionS *l, operatorT op, expressionS *r)
add_to_result (l, symval_diff, symval_diff < 0);
l->X_op = O_constant;
l->X_add_symbol = 0;
+ l->X_unsigned = 0;
return 1;
}
return 0;
diff --git a/gas/expr.c b/gas/expr.c
index bf58fc3a768..78a247cde09 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -632,6 +632,7 @@ integer_constant (int radix, expressionS *expressionP)
/* Not a small number. */
expressionP->X_op = O_big;
expressionP->X_add_number = number; /* Number of littlenums. */
+ expressionP->X_unsigned = 1;
input_line_pointer--; /* -> char following number. */
}
}
@@ -707,6 +708,7 @@ mri_char_constant (expressionS *expressionP)
{
expressionP->X_op = O_big;
expressionP->X_add_number = i;
+ expressionP->X_unsigned = 1;
}
else
{
@@ -1164,6 +1166,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
if (generic_bignum[i])
break;
}
+
+ expressionP->X_unsigned = 0;
}
else if (op == O_logical_not)
{
diff --git a/gas/expr.h b/gas/expr.h
index 14787c41343..2be3d69683c 100644
--- a/gas/expr.h
+++ b/gas/expr.h
@@ -131,10 +131,12 @@ typedef struct expressionS
unsigned char X_op;
#endif
- /* Non-zero if X_add_number should be regarded as unsigned. This is
- only valid for O_constant expressions. It is only used when an
- O_constant must be extended into a bignum (i.e., it is not used
- when performing arithmetic on these values).
+ /* Non-zero if the expression value should be regarded as unsigned. This is
+ only valid for
+ - O_constant expressions, where it is only used when an O_constant must be
+ extended into a bignum (i.e., it is not used when performing arithmetic
+ on these values),
+ - O_big integer expressions, i.e. when X_add_number is positive.
FIXME: This field is not set very reliably. */
unsigned int X_unsigned : 1;
/* This is used to implement "word size + 1 bit" arithmetic, so that e.g.
diff --git a/gas/read.c b/gas/read.c
index c9cbd224a7d..1b483d683d5 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -1458,6 +1458,7 @@ convert_to_bignum (expressionS *exp, int sign)
generic_bignum[i++] = sign ? LITTLENUM_MASK : 0;
exp->X_op = O_big;
exp->X_add_number = i;
+ exp->X_unsigned = !sign;
}
/* For most MRI pseudo-ops, the line actually ends at the first
@@ -4651,8 +4652,8 @@ emit_expr_with_reloc (expressionS *exp,
pass to md_number_to_chars, handle it as a bignum. */
if (op == O_constant && nbytes > sizeof (valueT))
{
- extra_digit = exp->X_unsigned ? 0 : -1;
- convert_to_bignum (exp, !exp->X_unsigned);
+ extra_digit = exp->X_unsigned ? 0 : -exp->X_extrabit;
+ convert_to_bignum (exp, -extra_digit);
op = O_big;
}
@@ -5371,12 +5372,14 @@ emit_leb128_expr (expressionS *exp, int sign)
}
else if (op == O_constant
&& sign
- && (exp->X_add_number < 0) == !exp->X_extrabit)
+ && (exp->X_unsigned
+ ? exp->X_add_number < 0
+ : (exp->X_add_number < 0) != exp->X_extrabit))
{
/* We're outputting a signed leb128 and the sign of X_add_number
doesn't reflect the sign of the original value. Convert EXP
to a correctly-extended bignum instead. */
- convert_to_bignum (exp, exp->X_extrabit);
+ convert_to_bignum (exp, !exp->X_unsigned && exp->X_extrabit);
op = O_big;
}
diff --git a/gas/testsuite/gas/all/octa.d b/gas/testsuite/gas/all/octa.d
index e8eff2ce828..9c9120605d7 100644
--- a/gas/testsuite/gas/all/octa.d
+++ b/gas/testsuite/gas/all/octa.d
@@ -14,3 +14,11 @@ Contents of section .data:
[^ ]* (00000000 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 00000000) .*
[^ ]* (00000080 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 80000000) .*
[^ ]* (01000000 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 00000001) .*
+ [^ ]* (00000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000000) .*
+ [^ ]* (00000000 00000010 00000000 00000000|00000000 00000000 10000000 00000000) .*
+ [^ ]* (ffffffff ffffffef ffffffff ffffffff|ffffffff ffffffff efffffff ffffffff) .*
+ [^ ]* (01000000 00000010 00000000 00000000|00000000 00000000 10000000 00000001) .*
+ [^ ]* (01000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000001) .*
+ [^ ]* (feffffff ffffff0f 00000000 00000000|00000000 00000000 0fffffff fffffffe) .*
+ [^ ]* (02000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000002) .*
+ [^ ]* (fdffffff ffffff0f 00000000 00000000|00000000 00000000 0fffffff fffffffd) .*
diff --git a/gas/testsuite/gas/all/octa.s b/gas/testsuite/gas/all/octa.s
index faa21fa7ba0..037941f2e6d 100644
--- a/gas/testsuite/gas/all/octa.s
+++ b/gas/testsuite/gas/all/octa.s
@@ -9,3 +9,13 @@
.octa ~0xffffffff
.octa 0 - 0x80000000
.octa 0 - 0xffffffff
+
+ .octa ~0xfffffffffffffff
+ .octa -~0xfffffffffffffff
+ .octa ~-~0xfffffffffffffff
+ .octa -~-~0xfffffffffffffff
+
+ .octa -0xfffffffffffffff
+ .octa ~-0xfffffffffffffff
+ .octa -~-0xfffffffffffffff
+ .octa ~-~-0xfffffffffffffff
More information about the Binutils-cvs
mailing list