code generation bug in x86 PIC

Richard Henderson rth@redhat.com
Sat Nov 25 16:40:00 GMT 2000


For openers, this has nothing at all to do with -fPIC.

The problem is that the hard register specification is being
ignored because the hard reg has the same name as the variable.
It would appear that we need another bit to differentiate this
from the normal case.

Frankly, the treatment of DECL_ASSEMBLER_NAME throughout the 
compiler is confusing to me.  Why would we normally set it at all
for a local variable?  Why should build_decl automatically set it?

Further, the C++ front end appears to handle this case in a completely
different way.  The code is close enough to hint at the common ancestor,
but in the intervening time appear to have diverged significantly.

Here I choose a bit that is not documented as used for a VAR_DECL
in cp-tree.h so that c-semantics.c (which is shared) should be able
to use it with impunity.

Minimal x86 test case (for visual inspection only) is

  void foo()
  {
    register void *esp __asm__ ("esp");
    esp = 0;
  }

Note that this test still doesn't work for C++, but I am confused
about how to go about getting it there, since there is code that
appears to want to DTRT, but doesn't.


r~



	* c-common.h (DECL_C_HARD_REGISTER): New.
	* c-decl.c (finish_decl): Set it for asm register variables.
	* c-semantics.c (emit_local_var): Test it when instantiating one.

Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.51
diff -c -p -d -r1.51 c-common.h
*** c-common.h	2000/11/25 19:28:41	1.51
--- c-common.h	2000/11/26 00:22:08
*************** extern int anon_aggr_type_p             
*** 686,691 ****
--- 686,695 ----
  #define CLEAR_DECL_C_BIT_FIELD(NODE) \
    (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 0)
  
+ /* In a VAR_DECL, nonzero if the decl is a register variable with
+    an explicit asm specification.  */
+ #define DECL_C_HARD_REGISTER(DECL)  DECL_LANG_FLAG_4 (VAR_DECL_CHECK (DECL))
+ 
  extern void emit_local_var                      PARAMS ((tree));
  extern void make_rtl_for_local_static           PARAMS ((tree));
  extern tree expand_cond                         PARAMS ((tree));
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.182
diff -c -p -d -r1.182 c-decl.c
*** c-decl.c	2000/11/26 00:16:18	1.182
--- c-decl.c	2000/11/26 00:22:09
*************** finish_decl (decl, init, asmspec_tree)
*** 3765,3771 ****
        else
  	{
  	  if (asmspec)
! 	    DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
  	  add_decl_stmt (decl);
  	}
  
--- 3765,3774 ----
        else
  	{
  	  if (asmspec)
! 	    {
! 	      DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
! 	      DECL_C_HARD_REGISTER (decl) = 1;
! 	    }
  	  add_decl_stmt (decl);
  	}
  
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-semantics.c,v
retrieving revision 1.14
diff -c -p -d -r1.14 c-semantics.c
*** c-semantics.c	2000/11/10 04:29:43	1.14
--- c-semantics.c	2000/11/26 00:22:09
*************** emit_local_var (decl)
*** 313,321 ****
    /* Create RTL for this variable.  */
    if (!DECL_RTL (decl))
      {
!       if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
! 	/* The user must have specified an assembler name for this
! 	   variable.  Set that up now.  */
  	rest_of_decl_compilation
  	  (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
  	   /*top_level=*/0, /*at_end=*/0);
--- 313,321 ----
    /* Create RTL for this variable.  */
    if (!DECL_RTL (decl))
      {
!       if (DECL_C_HARD_REGISTER (decl))
! 	/* The user specified an assembler name for this variable.
! 	   Set that up now.  */
  	rest_of_decl_compilation
  	  (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
  	   /*top_level=*/0, /*at_end=*/0);


More information about the Gcc-bugs mailing list