This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]