.macro bug in gas for IA64

Nick Clifton nickc@redhat.com
Wed Mar 12 14:17:00 GMT 2003
Hi Jim,

> get_line_sb inserts characters until it sees an end-of-line
> character, and then returns to buffer_and_nest.  buffer_and_nest
> then inserts a newline character.  We can get the right behaviour for
> IA-64 if buffer_and_nest inserts the original end-of-line character.
> Also, get_line_sb has to stop skipping multiple end-of-line
> characters.  That gives me the first following patch.  The fact that
> 0 is an end of line character makes this a little ugly, but
> otherwise it seems OK.

I like this first patch, but I am a little confused by part of it:

> *************** get_line_sb (line)
> *** 2285,2299 ****
>         sb_add_char (line, *input_line_pointer++);
>       }
>   
> !   while (input_line_pointer < buffer_limit
>   	 && is_end_of_line[(unsigned char) *input_line_pointer])
>       {
> !       if (input_line_pointer[-1] == '\n')
> ! 	bump_line_counters ();
> !       ++input_line_pointer;
>       }
> ! 
> !   return 1;
>   }
>   
>   /* Define a macro.  This is an interface to macro.c.  */
> --- 2285,2305 ----
>         sb_add_char (line, *input_line_pointer++);
>       }
>   
> !   /* Don't skip multiple end-of-line characters, because that breaks support
> !      for the IA-64 stop bit (;;) which looks like two consecutive end-of-line
> !      characters but isn't.  Return the end-of-line character so that the
> !      caller can insert it if necessary.  */
> !   if (input_line_pointer < buffer_limit
>   	 && is_end_of_line[(unsigned char) *input_line_pointer])
>       {
> !       char c = *input_line_pointer++;
> !       if (c != 0)
> ! 	return c;
> !       else
> ! 	return '\n';
>       }
> !   else
> !     return '\n';
>   }

It seems to me that the patched version will return the character
*after* the end-of-line character, but only if there were characters
left in the input buffer.  To get the behaviour you desire, I think
that all that you need to do is to return *input_line_pointer.  Here
is a slightly modified version of your patch which does this.  What do
you think ?

Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.58
diff -c -3 -p -w -r1.58 read.c
*** gas/read.c	11 Jan 2003 06:24:12 -0000	1.58
--- gas/read.c	12 Mar 2003 14:11:09 -0000
*************** s_lsym (ignore)
*** 2235,2247 ****
    demand_empty_rest_of_line ();
  }
  
! /* Read a line into an sb.  */
  
  static int
  get_line_sb (line)
       sb *line;
  {
    char quote1, quote2, inquote;
  
    if (input_line_pointer[-1] == '\n')
      bump_line_counters ();
--- 2235,2249 ----
    demand_empty_rest_of_line ();
  }
  
! /* Read a line into an sb.  Returns the character that ended the line
!    or zero if there are no more lines.  */
  
  static int
  get_line_sb (line)
       sb *line;
  {
    char quote1, quote2, inquote;
+   unsigned char c;
  
    if (input_line_pointer[-1] == '\n')
      bump_line_counters ();
*************** get_line_sb (line)
*** 2269,2299 ****
  
    inquote = '\0';
  
!   while (!is_end_of_line[(unsigned char) *input_line_pointer]
! 	 || (inquote != '\0' && *input_line_pointer != '\n'))
      {
!       if (inquote == *input_line_pointer)
  	inquote = '\0';
        else if (inquote == '\0')
  	{
! 	  if (*input_line_pointer == quote1)
  	    inquote = quote1;
! 	  else if (*input_line_pointer == quote2)
  	    inquote = quote2;
  	}
  
!       sb_add_char (line, *input_line_pointer++);
      }
  
!   while (input_line_pointer < buffer_limit
! 	 && is_end_of_line[(unsigned char) *input_line_pointer])
!     {
!       if (input_line_pointer[-1] == '\n')
! 	bump_line_counters ();
!       ++input_line_pointer;
!     }
! 
!   return 1;
  }
  
  /* Define a macro.  This is an interface to macro.c.  */
--- 2271,2299 ----
  
    inquote = '\0';
  
!   while ((c = * input_line_pointer ++) != 0
! 	 && (!is_end_of_line[c]
! 	     || (inquote != '\0' && c != '\n')))
      {
!       if (inquote == c)
  	inquote = '\0';
        else if (inquote == '\0')
  	{
! 	  if (c == quote1)
  	    inquote = quote1;
! 	  else if (c == quote2)
  	    inquote = quote2;
  	}
  
!       sb_add_char (line, c);
      }
  
!   /* Don't skip multiple end-of-line characters, because that breaks support
!      for the IA-64 stop bit (;;) which looks like two consecutive end-of-line
!      characters but isn't.  Instead just skip one end of line character and
!      return the character skipped so that the caller can re-insert it if
!      necessary.   */
!   return c;
  }
  
  /* Define a macro.  This is an interface to macro.c.  */
Index: gas/macro.c
===================================================================
RCS file: /cvs/src/src/gas/macro.c,v
retrieving revision 1.20
diff -c -3 -p -w -r1.20 macro.c
*** gas/macro.c	3 Jan 2003 21:47:20 -0000	1.20
--- gas/macro.c	12 Mar 2003 14:12:21 -0000
*************** buffer_and_nest (from, to, ptr, get_line
*** 222,229 ****
  	    }
  	}
  
!       /* Add a CR to the end and keep running.  */
!       sb_add_char (ptr, '\n');
        line_start = ptr->len;
        more = get_line (ptr);
      }
--- 222,229 ----
  	    }
  	}
  
!       /* Add the original end-of-line char to the end and keep running.  */
!       sb_add_char (ptr, more);
        line_start = ptr->len;
        more = get_line (ptr);
      }


I tested it with this test case:

  .macro foo ; add r0 = r1, r2 ; .endm
  .macro bar ; add r0 = r1, r2 ;; ; .endm

        foo
	bar

and got this output:

   0:   0d 00 04 04 00 20       [MFI]       add r0=r1,r2
   6:   00 00 00 02 00 00                   nop.f 0x0
   c:   10 10 00 80                         add r0=r1,r2;;

I am not an IA-64 instruction set expert, but this looks about right
to me.

Cheers
        Nick



More information about the Binutils mailing list