This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: gas/expr.c: 0b vs 0b0 vs 00b
- From: Alan Modra <amodra at gmail dot com>
- To: DJ Delorie <dj at redhat dot com>
- Cc: binutils at sourceware dot org
- Date: Wed, 12 Aug 2015 00:54:30 +0930
- Subject: Re: gas/expr.c: 0b vs 0b0 vs 00b
- Authentication-results: sourceware.org; auth=none
- References: <201508070539 dot t775dYYM024692 at greed dot delorie dot com>
On Fri, Aug 07, 2015 at 01:39:34AM -0400, DJ Delorie wrote:
>
> For targets with both NUMBERS_WITH_SUFFIX and LOCAL_LABELS_FB, there
> is a parse ambiquity between various binary constants:
>
> 0b backward reference
> 1b binary value, suffix
> 0b1 binary value, prefix
Actually 1b is a backward reference too. I think both 0b and 1b
without following binary digits ought to be treated as backward refs
on these targets, since if you want to write a binary 0 or 1 with an
explicit suffix that can be done as 0B or 1B.
> The third will be parsed as 0b followed by "junk". This patch checks
> for 0b followed by further binary digits and bypasses the b-as-suffix
> rule.
>
> I don't think a generic test case would work, since it would have to
> test expressions that are only valid on some targets. Would one
> target's test suffice, or should the test be duplicated across many
> targets?
I think a single target test is sufficient. I've been playing with
variants of the following.
.text
_start:
.byte 0f - _start
.byte 1f - _start
0:
.byte 0b - _start
1:
.byte 1b - _start
.byte 0b0, 0b1, 0B0, 0B1
.byte 0B, 1B
Here's a patch that extends yours a little. What do you think?
* expr.c (integer_constant): Return O_absent expression if eol.
(operand): For targets with both LOCAL_LABELS_FB and
NUMBERS_WITH_SUFFIX set, treat "0b" not followed by binary
digits as a local label reference. Correct handling of 0b prefix.
If a suffix is not allowed, error on 0B.
diff --git a/gas/expr.c b/gas/expr.c
index 106f06d..2dae6ba 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -285,6 +285,12 @@ integer_constant (int radix, expressionS *expressionP)
#define valuesize 32
#endif
+ if (is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ expressionP->X_op = O_absent;
+ return;
+ }
+
if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0)
{
int flt = 0;
@@ -832,32 +838,28 @@ operand (expressionS *expressionP, enum expr_mode mode)
break;
case 'b':
- if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX))
+ if (LOCAL_LABELS_FB && !flag_m68k_mri
+ && input_line_pointer[1] != '0'
+ && input_line_pointer[1] != '1')
{
- /* This code used to check for '+' and '-' here, and, in
- some conditions, fall through to call
- integer_constant. However, that didn't make sense,
- as integer_constant only accepts digits. */
- /* Some of our code elsewhere does permit digits greater
- than the expected base; for consistency, do the same
- here. */
- if (input_line_pointer[1] < '0'
- || input_line_pointer[1] > '9')
- {
- /* Parse this as a back reference to label 0. */
- input_line_pointer--;
- integer_constant (10, expressionP);
- break;
- }
- /* Otherwise, parse this as a binary number. */
+ /* Parse this as a back reference to label 0. */
+ input_line_pointer--;
+ integer_constant (10, expressionP);
+ break;
}
+ /* Otherwise, parse this as a binary number. */
/* Fall through. */
case 'B':
- input_line_pointer++;
+ if (input_line_pointer[1] == '0'
+ || input_line_pointer[1] == '1')
+ {
+ input_line_pointer++;
+ integer_constant (2, expressionP);
+ break;
+ }
if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)
- goto default_case;
- integer_constant (2, expressionP);
- break;
+ input_line_pointer++;
+ goto default_case;
case '0':
case '1':
--
Alan Modra
Australia Development Lab, IBM