This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC 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]

End-of-unit changes in decl visibility


Short version: is there an easy way to tell which decls might change
visibility at the end of compilation?

An example test case is g++.old-deja/g++.abi/ptrflags.C, which is failing
for MIPS o32 abicalls:

    struct B;
    [...]
    int main ()
    {
      [...]
      if (! expect (8 | 0, typeid (B *)))
        return 11;
      if (! expect (8 | 1, typeid (B const *)))
        return 12;
      if (! expect (8 | 2, typeid (B volatile *)))
        return 13;
      [...]
    }

main() is compiled on the assumption that the typeinfo for B *, etc.,
are comdat, presumably because B could be completed later in the file.
But B never is completed, so the typeinfos end up being local.

This causes problems for o32 abicalls because the access sequences used
for global symbols don't work for local symbols, and vice versa.[*]

Now the MIPS symbol handling code predates SYMBOL_REF_DECL and uses
SYMBOL_REF_FLAG/TARGET_ENCODE_SECTION_INFO to choose between local
and global accesses.  An easy fix for -funit-at-a-time is to check the
SYMBOL_REF_DECL directly.  But the only way I can think of dealing with
the -fno-unit-at-a-time case is to detect which symbols _might_ change
visibility and force them into the constant pool.  Question is, what's
the best condition to use?

The patch below seems to work, and has survived bootstrap & regression
test on mips64{,el}-linux-gnu.  But the condition in mips_symbolic_constant_p
seems like an awful hack...

Richard

[*] Note that "local" doesn't correspond to SYMBOL_REF_LOCAL.


	* config/mips/mips.c (mips_classify_symbol): Directly check the
	visibility of SYMBOL_REF_DECLS, don't rely on SYMBOL_REF_FLAG.
	(mips_symbolic_constant_p): When targetting o32 abicalls, reject
	symbols whose visibility might change later.
	(mips_const_insns): Handle SYMBOL_REFs and LABEL_REFs like CONSTs.
	(mips_encode_section_info): Remove TARGET_ABICALLS handling.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.343
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.343 mips.c
*** config/mips/mips.c	7 Nov 2003 08:14:32 -0000	1.343
--- config/mips/mips.c	15 Nov 2003 09:35:54 -0000
*************** mips_classify_symbol (rtx x)
*** 831,837 ****
      return SYMBOL_SMALL_DATA;
  
    if (TARGET_ABICALLS)
!     return (SYMBOL_REF_FLAG (x) ? SYMBOL_GOT_LOCAL : SYMBOL_GOT_GLOBAL);
  
    return SYMBOL_GENERAL;
  }
--- 831,862 ----
      return SYMBOL_SMALL_DATA;
  
    if (TARGET_ABICALLS)
!     {
!       /* There are three cases to consider:
! 
! 	    - o32 PIC (either with or without explicit relocs)
! 	    - n32/n64 PIC without explicit relocs
! 	    - n32/n64 PIC with explicit relocs
! 
! 	 In the first case, both local and global accesses will use an
! 	 R_MIPS_GOT16 relocation.  We must correctly predict which of
! 	 the two semantics (local or global) the assembler and linker
! 	 will apply.  The choice doesn't depend on the symbol's
! 	 visibility, so we deliberately ignore decl_visibility and
! 	 binds_local_p here.
! 
! 	 In the second case, the assembler will not use R_MIPS_GOT16
! 	 relocations, but it chooses between local and global accesses
! 	 in the same way as for o32 PIC.
! 
! 	 In the third case we have more freedom since both forms of
! 	 access will work for any kind of symbol.  However, there seems
! 	 little point in doing things differently.  */
!       if (SYMBOL_REF_DECL (x) == 0 || TREE_PUBLIC (SYMBOL_REF_DECL (x)))
! 	return SYMBOL_GOT_GLOBAL;
!       else
! 	return SYMBOL_GOT_LOCAL;
!     }
  
    return SYMBOL_GENERAL;
  }
*************** mips_symbolic_constant_p (rtx x, enum mi
*** 867,878 ****
    HOST_WIDE_INT offset;
  
    mips_split_const (x, &x, &offset);
    if (UNSPEC_ADDRESS_P (x))
      *symbol_type = UNSPEC_ADDRESS_TYPE (x);
-   else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
-     *symbol_type = mips_classify_symbol (x);
    else
!     return false;
  
    if (offset == 0)
      return true;
--- 892,927 ----
    HOST_WIDE_INT offset;
  
    mips_split_const (x, &x, &offset);
+ 
    if (UNSPEC_ADDRESS_P (x))
      *symbol_type = UNSPEC_ADDRESS_TYPE (x);
    else
!     {
!       if (GET_CODE (x) != SYMBOL_REF && GET_CODE (x) != LABEL_REF)
! 	return false;
! 
!       /* If a front end creates artifical comdat decls, it might change
! 	 them to local static data at the end of compilation.  For example,
! 	 the C++ front end does this for typeinfo structures when the
! 	 referenced type was never completed.
! 
! 	 Unfortunately, this cases trouble for o32 abicalls, since we
! 	 need to use different access sequences for local and global
! 	 symbols.  Deal with this by declaring such symbols to be
! 	 illegitimate, thus forcing them into the constant pool.  */
!       if (!flag_unit_at_a_time
! 	  && TARGET_ABICALLS
! 	  && TARGET_EXPLICIT_RELOCS
! 	  && !TARGET_NEWABI
! 	  && GET_CODE (x) == SYMBOL_REF
! 	  && SYMBOL_REF_DECL (x) != 0
! 	  && DECL_P (SYMBOL_REF_DECL (x))
! 	  && DECL_ARTIFICIAL (SYMBOL_REF_DECL (x))
! 	  && DECL_COMDAT (SYMBOL_REF_DECL (x)))
! 	return false;
! 
!       *symbol_type = mips_classify_symbol (x);
!     }
  
    if (offset == 0)
      return true;
*************** mips_const_insns (rtx x)
*** 1198,1203 ****
--- 1247,1254 ----
        return (!TARGET_MIPS16 && x == CONST0_RTX (GET_MODE (x)) ? 1 : 0);
  
      case CONST:
+     case SYMBOL_REF:
+     case LABEL_REF:
        if (CONST_GP_P (x))
  	return 1;
  
*************** mips_const_insns (rtx x)
*** 1222,1231 ****
  	}
        return 0;
  
-     case SYMBOL_REF:
-     case LABEL_REF:
-       return mips_symbol_insns (mips_classify_symbol (x));
- 
      default:
        return 0;
      }
--- 1273,1278 ----
*************** mips_encode_section_info (tree decl, rtx
*** 7083,7117 ****
          SYMBOL_REF_FLAG (symbol) = 0;
        else if (TREE_CODE (decl) == STRING_CST
                 && ! flag_writable_strings)
-         SYMBOL_REF_FLAG (symbol) = 0;
-       else
-         SYMBOL_REF_FLAG (symbol) = 1;
-     }
- 
-   else if (TARGET_ABICALLS)
-     {
-       /* Mark the symbol if we should treat it as SYMBOL_GOT_LOCAL.
-          There are three cases to consider:
- 
-             - o32 PIC (either with or without explicit relocs)
-             - n32/n64 PIC without explicit relocs
-             - n32/n64 PIC with explicit relocs
- 
-          In the first case, both local and global accesses will use an
-          R_MIPS_GOT16 relocation.  We must correctly predict which of
-          the two semantics (local or global) the assembler and linker
-          will apply.  The choice doesn't depend on the symbol's
-          visibility, so we deliberately ignore decl_visibility and
-          binds_local_p here.
- 
-          In the second case, the assembler will not use R_MIPS_GOT16
-          relocations, but it chooses between local and global accesses
-          in the same way as for o32 PIC.
- 
-          In the third case we have more freedom since both forms of
-          access will work for any kind of symbol.  However, there seems
-          little point in doing things differently.  */
-       if (DECL_P (decl) && TREE_PUBLIC (decl))
          SYMBOL_REF_FLAG (symbol) = 0;
        else
          SYMBOL_REF_FLAG (symbol) = 1;
--- 7130,7135 ----


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