This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: Fix ARM's .unreq pseudo op
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Sat, 14 Jul 2007 17:17:56 +0100
- Subject: PATCH: Fix ARM's .unreq pseudo op
Hi Guys,
A bug was recently reported against the ARM assembler whereby
attempting to re-create a previously deleted register alias would
fail because the assembler had silently created an upper case and
lower case version of the alias:
% cat foo.s
foo .req r0
.unreq foo
foo .req r1
% as foo.s
Warning: ignoring redefinition of register alias 'FOO'
I am checking in the attached patch and testcase to fix this problem
and make sure that it does not resurface.
Cheers
Nick
gas/ChangeLog
2007-07-14 Nick Clifton <nickc@redhat.com>
* config/tc-arm.c (create_register_alias): Return a boolean rather
than an integer.
Check the return value of insert_reg_alias and do not continue to
create aliases once an insertion has failed.
(s_unreq): Delete the all-upper-case and all-lower-case
alternatives as well.
gas/testsuite/ChangeLog
2007-07-14 Nick Clifton <nickc@redhat.com>
* gas/arm/arm.s: Add tests for re-aliasing a previously removed
alias.
* gas/arm/arm.l: Add new expected warning message.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.334
diff -c -3 -p -r1.334 tc-arm.c
*** gas/config/tc-arm.c 3 Jul 2007 11:01:04 -0000 1.334
--- gas/config/tc-arm.c 14 Jul 2007 16:09:13 -0000
*************** insert_neon_reg_alias (char *str, int nu
*** 2013,2021 ****
new_register_name .req existing_register_name
If we find one, or if it looks sufficiently like one that we want to
! handle any error here, return non-zero. Otherwise return zero. */
! static int
create_register_alias (char * newname, char *p)
{
struct reg_entry *old;
--- 2013,2021 ----
new_register_name .req existing_register_name
If we find one, or if it looks sufficiently like one that we want to
! handle any error here, return TRUE. Otherwise return FALSE. */
! static bfd_boolean
create_register_alias (char * newname, char *p)
{
struct reg_entry *old;
*************** create_register_alias (char * newname, c
*** 2026,2042 ****
collapsed to single spaces. */
oldname = p;
if (strncmp (oldname, " .req ", 6) != 0)
! return 0;
oldname += 6;
if (*oldname == '\0')
! return 0;
old = hash_find (arm_reg_hsh, oldname);
if (!old)
{
as_warn (_("unknown register '%s' -- .req ignored"), oldname);
! return 1;
}
/* If TC_CASE_SENSITIVE is defined, then newname already points to
--- 2026,2042 ----
collapsed to single spaces. */
oldname = p;
if (strncmp (oldname, " .req ", 6) != 0)
! return FALSE;
oldname += 6;
if (*oldname == '\0')
! return FALSE;
old = hash_find (arm_reg_hsh, oldname);
if (!old)
{
as_warn (_("unknown register '%s' -- .req ignored"), oldname);
! return TRUE;
}
/* If TC_CASE_SENSITIVE is defined, then newname already points to
*************** create_register_alias (char * newname, c
*** 2056,2076 ****
/* Create aliases under the new name as stated; an all-lowercase
version of the new name; and an all-uppercase version of the new
name. */
! insert_reg_alias (nbuf, old->number, old->type);
!
! for (p = nbuf; *p; p++)
! *p = TOUPPER (*p);
! if (strncmp (nbuf, newname, nlen))
! insert_reg_alias (nbuf, old->number, old->type);
! for (p = nbuf; *p; p++)
! *p = TOLOWER (*p);
! if (strncmp (nbuf, newname, nlen))
! insert_reg_alias (nbuf, old->number, old->type);
! return 1;
}
/* Create a Neon typed/indexed register alias using directives, e.g.:
--- 2056,2089 ----
/* Create aliases under the new name as stated; an all-lowercase
version of the new name; and an all-uppercase version of the new
name. */
! if (insert_reg_alias (nbuf, old->number, old->type) != NULL)
! {
! for (p = nbuf; *p; p++)
! *p = TOUPPER (*p);
! if (strncmp (nbuf, newname, nlen))
! {
! /* If this attempt to create an additional alias fails, do not bother
! trying to create the all-lower case alias. We will fail and issue
! a second, duplicate error message. This situation arises when the
! programmer does something like:
! foo .req r0
! Foo .req r1
! The second .req creates the "Foo" alias but then fails to create
! the artifical FOO alias because it has already been created by the
! first .req. */
! if (insert_reg_alias (nbuf, old->number, old->type) == NULL)
! return TRUE;
! }
! for (p = nbuf; *p; p++)
! *p = TOLOWER (*p);
! if (strncmp (nbuf, newname, nlen))
! insert_reg_alias (nbuf, old->number, old->type);
! }
! return TRUE;
}
/* Create a Neon typed/indexed register alias using directives, e.g.:
*************** s_unreq (int a ATTRIBUTE_UNUSED)
*** 2270,2280 ****
--- 2283,2327 ----
name);
else
{
+ char * p;
+ char * nbuf;
+
hash_delete (arm_reg_hsh, name);
free ((char *) reg->name);
if (reg->neon)
free (reg->neon);
free (reg);
+
+ /* Also locate the all upper case and all lower case versions.
+ Do not complain if we cannot find one or the other as it
+ was probably deleted above. */
+
+ nbuf = strdup (name);
+ for (p = nbuf; *p; p++)
+ *p = TOUPPER (*p);
+ reg = hash_find (arm_reg_hsh, nbuf);
+ if (reg)
+ {
+ hash_delete (arm_reg_hsh, nbuf);
+ free ((char *) reg->name);
+ if (reg->neon)
+ free (reg->neon);
+ free (reg);
+ }
+
+ for (p = nbuf; *p; p++)
+ *p = TOLOWER (*p);
+ reg = hash_find (arm_reg_hsh, nbuf);
+ if (reg)
+ {
+ hash_delete (arm_reg_hsh, nbuf);
+ free ((char *) reg->name);
+ if (reg->neon)
+ free (reg->neon);
+ free (reg);
+ }
+
+ free (nbuf);
}
}
Index: gas/testsuite/gas/arm/req.l
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/req.l,v
retrieving revision 1.2
diff -c -3 -p -r1.2 req.l
*** gas/testsuite/gas/arm/req.l 18 May 2005 05:40:10 -0000 1.2
--- gas/testsuite/gas/arm/req.l 14 Jul 2007 16:09:13 -0000
***************
*** 1,3 ****
--- 1,4 ----
[^:]*: Assembler messages:
[^:]*:18: Error: ARM register expected -- `add foo,foo,foo'
[^:]*:21: Warning: ignoring attempt to undefine built-in register 'r0'
+ [^:]*:41: Warning: ignoring redefinition of register alias 'FOO'
Index: gas/testsuite/gas/arm/req.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/req.s,v
retrieving revision 1.2
diff -c -3 -p -r1.2 req.s
*** gas/testsuite/gas/arm/req.s 18 May 2005 05:40:10 -0000 1.2
--- gas/testsuite/gas/arm/req.s 14 Jul 2007 16:09:13 -0000
*************** test_dot_req_and_unreq:
*** 19,25 ****
# Attempt to remove the builtin alias for r0.
.unreq r0
!
# That is ignored, so this should still work.
add r0, r0, r0
!
--- 19,41 ----
# Attempt to remove the builtin alias for r0.
.unreq r0
!
# That is ignored, so this should still work.
add r0, r0, r0
!
! # Now attempt to re-alias foo. There used to be a bug whereby the
! # first creation of an alias called foo would also create an alias
! # called FOO, but the .unreq of foo would not delete FOO. Thus a
! # second attempt at aliasing foo (to something different than
! # before) would fail because the assembler would complain that FOO
! # already existed.
! foo .req r1
!
! add foo, foo, foo
!
! # Check that the upper case alias was also recreated.
! add FOO, FOO, FOO
!
! # Check that a second attempt to alias foo, using a mixed case
! # verison of the name, will fail.
! Foo .req r2