This is the mail archive of the gcc-patches@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]

RE: PATCH: flag_external and DECL_EXTERNAL documentation



>David Korn <dkorn@pixelpower.com> writes:
>> >From: Jason Merrill [mailto:jason@redhat.com]
>> >> In the back end I'm currently writing, whenever a function call is to
>> >> be generated I need to know whether the function is defined in the
>> >> current translation unit or not.
>> >The rs6000 port uses
>> >  ((TREE_ASM_WRITTEN || !TREE_PUBLIC) && ! DECL_WEAK).
>> 
>>   ...to set the SYMBOL_REF_FLAG, by any chance ?  There's a couple of
>> catches with that that I've discovered.  One is that TREE_ASM_WRITTEN
>> isn't set until the final pass begins outputting assembler, so 
>> this will only spot
>> public (global) functions, and not (what would be described in C as) 
>> module static functions.  You might like to search the archives for a 
>> thread or two with "tests TREE_ASM_WRITTEN too early" in the subject
line;
>> deciding that a function exists in the current translation unit turns out
>> to be quite tricky.
>
>So have you found any solution?  In my case, the assembler *requires*
>calls to locally-defined functions to use short jumps, so I'm even
>more desperate to find out how to detect those functions.

  Well, I explored this stuff when writing a patch to make rs6000 choose
intelligently whether to emit a long or short branch to function calls.  I
expanded on the basic mechanism to get the cases it would miss.  Here's what
I've got in my current patches, with running commentary: in the rs6000 port,
the SYMBOL_REF_FLAG is used to indicate that the symbol reference is to a
function that exists in the current compilation unit.

diff -c3prN /dev2/gcc/gcc/config/rs6000/rs6000.c
/gccdev/gcc/gcc/config/rs6000/rs6000.c
*** /dev2/gcc/gcc/config/rs6000/rs6000.c	Mon Jan 15 05:28:54 2001
--- /gccdev/gcc/gcc/config/rs6000/rs6000.c	Wed Jan 24 21:45:51 2001
*************** current_file_function_operand (op, mode)

  In the original version of this function, the test amounts to "Do we
already know that the function referred to by the symbol_ref exists in the
current module, or is it a recursive call to the function we are currently
compiling."  I decided that this condition should cause the symbol ref flag
to be set, since otherwise when the output of a function gets deferred by
the inliner, and there's a call to that function in a subsequent function
in the file, current_file_function_operand would return different values
during different passes of the compiler, causing insn recog. to fail.

*** 1201,1212 ****
       register rtx op;
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
!   return (GET_CODE (op) == SYMBOL_REF
! 	  && (SYMBOL_REF_FLAG (op)
! 	      || (op == XEXP (DECL_RTL (current_function_decl), 0)
! 	          && !DECL_WEAK (current_function_decl))));
! }
  
  
  /* Return 1 if this operand is a valid input for a move insn.  */
  
--- 1200,1217 ----
       register rtx op;
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
!   if (GET_CODE (op) != SYMBOL_REF)
!     return 0;
! 
!   if (op == XEXP (DECL_RTL (current_function_decl), 0)
! 	          && !DECL_WEAK (current_function_decl))
! 	{
!       SYMBOL_REF_FLAG (op) = 1;
!       return 1;
! 	}
  
+   return SYMBOL_REF_FLAG (op) != 0;
+ }
  
  /* Return 1 if this operand is a valid input for a move insn.  */

*************** rs6000_encode_section_info (decl)

  Here's the original bit of code that tested TREE_ASM_WRITTEN when
processing the sym_ref's name string.  It's way too soon to test this, since
it doesn't get set until we're outputting assembly code; at this stage, the
only thing we know for sure is that we're outputting a reference to the
function.  The ! TREE_PUBLIC test is still good: we may assume that a static
function *must* exist in the current compilation unit, since otherwise it
won't be found!  So I removed the irrelevant test here; we have to find
another way to spot the global functions.  This test should probably also
include (flag_pic != 0) for reasons that were discussed in one of the
earlier threads I referred to.  (And which I can't remember well enough to
explain here).

*** 5889,5897 ****
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        rtx sym_ref = XEXP (DECL_RTL (decl), 0);
!       if ((TREE_ASM_WRITTEN (decl) || ! TREE_PUBLIC (decl))
!           && !DECL_WEAK (decl))
! 	SYMBOL_REF_FLAG (sym_ref) = 1;
  
        if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
  	{
--- 5925,5933 ----
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        rtx sym_ref = XEXP (DECL_RTL (decl), 0);
! 
!       if (!TREE_PUBLIC (decl) && !DECL_WEAK (decl))
!       	SYMBOL_REF_FLAG (sym_ref) = 1;
  
        if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
  	{
diff -c3prN /dev2/gcc/gcc/config/rs6000/rs6000.h
/gccdev/gcc/gcc/config/rs6000/rs6000.h
*** /dev2/gcc/gcc/config/rs6000/rs6000.h	Fri Dec 22 20:39:59 2000
--- /gccdev/gcc/gcc/config/rs6000/rs6000.h	Sat Jan 13 03:39:12 2001

  Another irrelevant test of TREE_ASM_WRITTEN that I removed.  This is the
same as rs6000_encode_section_info; there's just a couple of different
versions used, one as inline macro, one as a function call, according to
which rs6000 architecture is being used.

*************** extern int rs6000_trunc_used;
*** 2538,2544 ****
  
  #define ENCODE_SECTION_INFO(DECL)  \
    if (TREE_CODE (DECL) == FUNCTION_DECL			\
!       && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL)) \
        && !DECL_WEAK (DECL)) \
      SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
  
--- 2556,2562 ----
  
  #define ENCODE_SECTION_INFO(DECL)  \
    if (TREE_CODE (DECL) == FUNCTION_DECL			\
!       && !TREE_PUBLIC (DECL) \
        && !DECL_WEAK (DECL)) \
      SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
  
*************** extern int toc_initialized;

  The earlier discussions came to the conclusion that
ASM_DECLARE_FUNCTION_NAME was a reasonable place to set the symbol ref. flag
for global functions, since if we're about to output the assembler .globl
command that makes the function visible, we can be fairly sure it exists in
the current translation unit - this is a kind of 'early warning' that we are
going to output assembler code and set TREE_ASM_WRITTEN later on.

*** 2620,2631 ****
  
     The csect for the function will have already been created by the
     `text_section' call previously done.  We do have to go back to that
!    csect, however.  */
  
  /* ??? What do the 16 and 044 in the .function line really mean?  */
  
  #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)		\
! { if (TREE_PUBLIC (DECL))					\
      {								\
        fputs ("\t.globl .", FILE);				\
        RS6000_OUTPUT_BASENAME (FILE, NAME);			\
--- 2638,2657 ----
  
     The csect for the function will have already been created by the
     `text_section' call previously done.  We do have to go back to that
!    csect, however.
! 
!    We also record the fact that the function exists in the current
!    compilation unit and so can be reached by a short branch by 
!    setting SYMBOL_REF_FLAG.  */
  
  /* ??? What do the 16 and 044 in the .function line really mean?  */
  
  #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)		\
! {                                                   \
!   rtx sym_ref = XEXP (DECL_RTL (DECL), 0);          \
!   if (!DECL_WEAK (DECL))                            \
!     	  SYMBOL_REF_FLAG (sym_ref) = 1;              \
!   if (TREE_PUBLIC (DECL))					\
      {								\
        fputs ("\t.globl .", FILE);				\
        RS6000_OUTPUT_BASENAME (FILE, NAME);			\
---------------------------------------------------------------------------

  That all seems to work for me, anyway; it avoids the potential confusion
caused by the inliner deferring asm output, and it seems to be correct as
far as I've tested it.  Note however that there may be complications with
pic and with DSOs that I haven't discovered, owing to the fact that neither
are relevant to my target/test platform.

>For now, I have resorted to a C-specific hack in 
>c-decl.c:grokdeclarator()
>which sets a flag when a function is declared "extern".

  Mm.  But of course, that doesn't really do what you want; there's nothing
to prevent a function in the current unit from having an extern declaration,
in fact that's a very common situation when your code is structured so that
every .c file has a corresponding .h that declares all its extern functions,
and the .c file includes its own .h.  So you can't assume that a function
actually is external to the current compilation unit just because it's
declared that way; nor can you assume it isn't.

  Since I've only tested those patches on rs6000 under a limited set of
conditions, I can't guarantee that they catch 100% of cases and are never
wrong.  In the context I'm using them, it isn't going to matter if I miss a
case and emit a long call to a function that is actually near enough for a
short call, but in your case it does matter.  I'd be very interested to see
how they function with your more rigid requirements; I think they might sort
your problem out, and as far as I understand the backend structure, they
should be applicable to any port.  Please keep me posted if you give it a
try, I'd be happy to look at any problems that emerge, and if none do, I'd
be grateful for the confirmation that my approach worked.

   cheers,
      DaveK
-- 
The Boulder Pledge: "Under no circumstances will I ever purchase anything 
offered to me as the result of an unsolicited email message. Nor will I 
forward chain letters, petitions, mass mailings, or virus warnings to large 
numbers of others. This is my contribution to the survival of the online
community."


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************

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