Bug 17982 - stop calling assemble_external before final assembly output time
Summary: stop calling assemble_external before final assembly output time
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.0
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: FIXME
: 18632 (view as bug list)
Depends on: 24777
Blocks:
  Show dependency treegraph
 
Reported: 2004-10-13 22:05 UTC by Andreas Schwab
Modified: 2015-02-06 08:11 UTC (History)
8 users (show)

See Also:
Host:
Target: ia64-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-09-10 19:00:52


Attachments
testcase.c:10: warning: y renamed after being referenced in assembly (101 bytes, application/octet-stream)
2008-11-24 04:32 UTC, KJK::Hyperion
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Schwab 2004-10-13 22:05:43 UTC
When an identifier has been used in an inline declaration subsequent renames 
of it are ignored.  That used to work with gcc 3.4 and still works on i386 and 
ppc at least.  This breaks building glibc. 
 
$ cat asm.c 
extern int foo (void); 
extern inline int 
bar (void) 
{ 
  return foo (); 
} 
extern __typeof (foo) foo __asm__ ("mumble"); 
int foobar (void) 
{ 
  return bar (); 
} 
$ gcc-4.0 -O -S asm.c 
asm.c:7: warning: asm declaration ignored due to conflict with previous rename 
$ grep mumble asm.s 
$ grep foo asm.s 
	.global foobar# 
	.proc foobar# 
foobar: 
	br.call.sptk.many b0 = foo# 
	.endp foobar#
Comment 1 Andrew Pinski 2004-10-13 23:03:26 UTC
DECL_ASSEMBLER_NAME_SET_P is true on ia64 for some reason which gets set when we call 
make_decl_rtl at c-decl.c:1757, why I don't know.
Comment 2 Andrew Pinski 2004-10-13 23:03:57 UTC
Confirmed.
Comment 3 Andrew Pinski 2004-10-13 23:18:19 UTC
The RTL is set because IA64 has ASM_OUTPUT_EXTERNAL defined.
I think is related to changes which Zack made to c-decl.c.
Comment 4 Andrew Pinski 2004-10-13 23:22:21 UTC
The call to make_decl_rtl is from assemble_external.
Comment 5 Zack Weinberg 2004-10-13 23:29:55 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename


Hmm.  Why are we calling assemble_external before EOF?

zw
Comment 6 Andrew Pinski 2004-10-13 23:49:13 UTC
1764      if (!skip_evaluation)
1765        assemble_external (ref);

#0  assemble_external (decl=0x41682934) at ../../gcc/varasm.c:1771
#1  0x00043c20 in build_external_ref (id=0x41686ac4, fun=1) at ../../gcc/c-typeck.c:1765
#2  0x0000534c in yyparse () at c-parse.y:626
#3  0x0000ac60 in c_parse_file () at c-parse.y:2903
#4  0x000a0728 in c_common_parse_file (set_yydebug=0) at ../../gcc/c-opts.c:1095
#5  0x0054dc6c in compile_file () at ../../gcc/toplev.c:985
#6  0x00550814 in do_compile () at ../../gcc/toplev.c:2069
#7  0x005508b0 in toplev_main (argc=3, argv=0xbffffd5c) at ../../gcc/toplev.c:2101
#8  0x000c69dc in main (argc=3, argv=0xbffffd5c) at ../../gcc/main.c:35

where the call to build_external_ref:
primary:
        IDENTIFIER
                {
                  if (yychar == YYEMPTY)
                    yychar = YYLEX;
                  $$.value = build_external_ref ($1, yychar == '(');
                  $$.original_code = ERROR_MARK;
                }

Comment 7 Andreas Schwab 2004-11-09 15:47:12 UTC
This is the change that broke this: 
 
2004-06-20  Zack Weinberg  <zack@codesourcery.com> 
 
	* c-common.h (has_c_linkage): New interface. 
	... 
Comment 8 H.J. Lu 2004-11-23 19:13:00 UTC
*** Bug 18632 has been marked as a duplicate of this bug. ***
Comment 9 H.J. Lu 2004-11-23 19:18:16 UTC
It also happens on x86_64 and i386 if -O1 or -O0 is used. It has nothing to
do with function inline.
Comment 10 Andrew Pinski 2004-11-23 19:22:34 UTC
Actually the example in comment #0 does not fail on x86 or ppc, only ia64 because of the reasons I 
outlined.  Now the testcase in PR 18632 has always failed, we just did not warn about it.
Comment 11 H.J. Lu 2004-11-23 21:13:50 UTC
Does this patch

--- gcc/c-pragma.c.rename       2004-11-09 12:03:42.000000000 -0800
+++ gcc/c-pragma.c      2004-11-23 13:03:26.020304351 -0800
@@ -473,8 +473,11 @@ maybe_apply_renaming_pragma (tree decl,
     return asmname;

   /* If the DECL_ASSEMBLER_NAME is already set, it does not change,
-     but we may warn about a rename that conflicts.  */
-  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+     but we may warn about a rename that conflicts.
+     FIXME: the DECL_ASSEMBLER_NAME can be set to DECL_NAME (decl)
+     without renaming pragma nor asm declaration involved.  */
+  if (DECL_ASSEMBLER_NAME_SET_P (decl)
+      && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
     {
       const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
       oldname = targetm.strip_name_encoding (oldname);

make any senses? At least, it works with my testcases. -O0 and -O1 still
complain with

[hjl@gnu-4 gcc]$ ./xgcc -B./ -c x.i
x.i:8: warning: foo renamed after being referenced in assembly
[hjl@gnu-4 gcc]$

It may be OK since foo has been referenced in assembly. But I am not sure
about languanges other than C.
Comment 12 Zack Weinberg 2004-11-23 22:19:59 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename

"hjl at lucon dot org" <gcc-bugzilla@gcc.gnu.org> writes:

> ------- Additional Comments From hjl at lucon dot org  2004-11-23 21:13 -------
> Does this patch
>
> --- gcc/c-pragma.c.rename       2004-11-09 12:03:42.000000000 -0800
> +++ gcc/c-pragma.c      2004-11-23 13:03:26.020304351 -0800
> @@ -473,8 +473,11 @@ maybe_apply_renaming_pragma (tree decl,
>      return asmname;
>
>    /* If the DECL_ASSEMBLER_NAME is already set, it does not change,
> -     but we may warn about a rename that conflicts.  */
> -  if (DECL_ASSEMBLER_NAME_SET_P (decl))
> +     but we may warn about a rename that conflicts.
> +     FIXME: the DECL_ASSEMBLER_NAME can be set to DECL_NAME (decl)
> +     without renaming pragma nor asm declaration involved.  */

This will not work.  At this point ia64 has already emitted an
external-reference directive for the old name into the assembly
stream.

The necessary fix is to prevent assemble_external from ever being
called before EOF.

zw
Comment 13 H.J. Lu 2004-11-23 23:42:44 UTC
I have verified that my modification works on Linux/ia64, Linux/ia32 and
Linux/x86_64. 
Comment 14 H.J. Lu 2004-11-24 02:01:28 UTC
A patch is posted at

http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01956.html
Comment 15 Nathanael C. Nerode 2004-11-27 00:30:19 UTC
HJ's latest patch probably doesn't fix the problem entirely :-(, but it is 
certainly correct to allow "renames" which don't change anything. 
 
Comment 16 Zack Weinberg 2004-11-27 20:25:22 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename


That's not what HJ's patch does, though.

zw
Comment 17 H.J. Lu 2004-11-27 20:44:56 UTC
DECL_ASSEMBLER_NAME_SET_P alone is not very reliable to check if a symbol
has been renamed or not. There are

/* The name of the object as the assembler will see it (but before any
   translations made by ASM_OUTPUT_LABELREF).  Often this is the same
   as DECL_NAME.  It is an IDENTIFIER_NODE.  */
#define DECL_ASSEMBLER_NAME(NODE) decl_assembler_name (NODE)

/* Returns nonzero if the DECL_ASSEMBLER_NAME for NODE has been set.  If zero, 
  the NODE might still have a DECL_ASSEMBLER_NAME -- it just hasn't been set
   yet.  */ #define DECL_ASSEMBLER_NAME_SET_P(NODE) \
  (DECL_CHECK (NODE)->decl.assembler_name != NULL_TREE)

and

/* The name of the object as the assembler will see it (but before any
   translations made by ASM_OUTPUT_LABELREF).  Often this is the same
   as DECL_NAME.  It is an IDENTIFIER_NODE.  */
tree
decl_assembler_name (tree decl)
{
  if (!DECL_ASSEMBLER_NAME_SET_P (decl))
    lang_hooks.set_decl_assembler_name (decl);
  return DECL_CHECK (decl)->decl.assembler_name;
}

Simply calling DECL_ASSEMBLER_NAME will make DECL_ASSEMBLER_NAME_SET_P to
return TRUE.
Comment 18 Zack Weinberg 2004-11-28 20:16:39 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename


You continue not to get it.

In this context, DECL_ASSEMBLER_NAME has been set because
assemble_external has been called on the symbol.  assemble_external is
*not* a no-op on ia64.  It emits a directive to the assembly output,
using the name of the symbol.  It is *not* safe to rename the symbol
after that has happened.  That you are not seeing a problem on
ia64-linux is either because GAS isn't as picky as the reference
assembler, or because your test case is not stringent enough.

zw
Comment 19 Andreas Schwab 2004-11-28 22:47:57 UTC
But the call to assemble_external has been there since the very beginning. 
Comment 20 Zack Weinberg 2004-11-29 16:38:45 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename


... so this has always been broken, is that what you're saying?

zw
Comment 21 Andreas Schwab 2004-11-29 17:07:05 UTC
Before your change it hasn't been a problem, apparently.  But if you think it 
was wrong to begin with then please try to fix it. 
Comment 22 Zack Weinberg 2004-11-29 17:15:15 UTC
Subject: Re:  [4.0 regression] asm declaration ignored due to conflict with previous rename


I'm hoping to have some time to work on this this week, but no
promises.

zw
Comment 23 H.J. Lu 2004-11-29 18:47:29 UTC
There are only 2 assemblers supported on ia64, GNU assembler and Intel
assembler. If GNU assembler is used, assemble_external is a no-op on Linux.
On HPUX, the actual undefined symbol references are outputed at the very
end. This patch

http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02511.html

will make Linux + Intel assembler to do the same. So, on ia64, it should be
OK to rename a symbol even after assemble_external is called as long as
it hasn't been actually used, in which case, you should get

x.i:8: warning: foo renamed after being referenced in assembly
Comment 24 GCC Commits 2004-12-08 19:13:44 UTC
Subject: Bug 17982

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	zack@gcc.gnu.org	2004-12-08 19:13:36

Modified files:
	gcc            : ChangeLog cgraphunit.c tree.h varasm.c 
	gcc/config/h8300: h8300.h 

Log message:
	PR 17982
	* varasm.c (pending_assemble_externals): New static.
	(assemble_external_real): Meat of assemble_external split out
	to this new function.
	(process_pending_assemble_externals): New function.
	(assemble_external): Use gcc_assert.  If flag_unit_at_a_time
	is true and the basic test passes, merely cons the decl onto
	the pending list to be handled later.
	* tree.h: Declare process_pending_assemble_externals.
	* cgraphunit.c (cgraph_optimize): Call it.
	
	* config/h8300/h8300.h: Do not define ASM_OUTPUT_EXTERNAL.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6750&r2=2.6751
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cgraphunit.c.diff?cvsroot=gcc&r1=1.90&r2=1.91
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree.h.diff?cvsroot=gcc&r1=1.664&r2=1.665
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/varasm.c.diff?cvsroot=gcc&r1=1.466&r2=1.467
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/h8300/h8300.h.diff?cvsroot=gcc&r1=1.179&r2=1.180

Comment 25 Andrew Pinski 2004-12-08 20:00:51 UTC
Fixed.
Comment 26 Zack Weinberg 2004-12-08 22:04:34 UTC
Uh, no, it's not fixed.  It is, however, papered over adequately for 4.0.  I'm
turning this into a 4.1 enhancement PR.

http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00491.html explains what needs to
happen for 4.1.
Comment 27 Zack Weinberg 2004-12-08 22:05:17 UTC
... and assigning to self.
Comment 28 Andrew Pinski 2005-07-05 02:10:37 UTC
Unassigning from Zack since he is gone now.
Comment 29 hjl@gcc.gnu.org 2006-12-12 03:59:06 UTC
Subject: Bug 17982

Author: hjl
Date: Tue Dec 12 03:58:52 2006
New Revision: 119764

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119764
Log:
2006-12-11  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/17982
	PR middle-end/20218
	* cgraphunit.c (cgraph_optimize): Remove call to
	process_pending_assemble_externals.

	* config/elfos.h (ASM_OUTPUT_EXTERNAL): New.

	* config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed.

	* config/ia64/ia64.c (ia64_asm_output_external): Rewritten.
	(ia64_hpux_add_extern_decl): Removed.
	(ia64_hpux_file_end): Likewise.
	(extern_func_list): Likewise.
	(extern_func_head): Likewise.

	* output.h (assemble_external): Update comments.
	(default_elf_asm_output_external): New.
	(maybe_assemble_visibility): New.

	* toplev.c (compile_file): Update comment.

	* varasm.c (assemble_external): Always put it on
	pending_assemble_externals.
	(maybe_assemble_visibility): Make it extern and return int.
	(default_elf_asm_output_external): New.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cgraphunit.c
    trunk/gcc/config/elfos.h
    trunk/gcc/config/ia64/hpux.h
    trunk/gcc/config/ia64/ia64.c
    trunk/gcc/output.h
    trunk/gcc/toplev.c
    trunk/gcc/varasm.c

Comment 30 Kazu Hirata 2006-12-16 02:47:41 UTC
Subject: Bug 17982

Author: kazu
Date: Sat Dec 16 02:47:27 2006
New Revision: 119959

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119959
Log:
	Backport from mainline:
	gcc/
	2006-12-11  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/17982
	PR middle-end/20218
	* cgraphunit.c (cgraph_optimize): Remove call to
	process_pending_assemble_externals.

	* config/elfos.h (ASM_OUTPUT_EXTERNAL): New.

	* config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed.

	* config/ia64/ia64.c (ia64_asm_output_external): Rewritten.
	(ia64_hpux_add_extern_decl): Removed.
	(ia64_hpux_file_end): Likewise.
	(extern_func_list): Likewise.
	(extern_func_head): Likewise.

	* output.h (assemble_external): Update comments.
	(default_elf_asm_output_external): New.
	(maybe_assemble_visibility): New.

	* toplev.c (compile_file): Update comment.

	* varasm.c (assemble_external): Always put it on
	pending_assemble_externals.
	(maybe_assemble_visibility): Make it extern and return int.
	(default_elf_asm_output_external): New.

Modified:
    branches/csl/sourcerygxx-4_1/ChangeLog.csl
    branches/csl/sourcerygxx-4_1/gcc/cgraphunit.c
    branches/csl/sourcerygxx-4_1/gcc/config/elfos.h
    branches/csl/sourcerygxx-4_1/gcc/config/ia64/hpux.h
    branches/csl/sourcerygxx-4_1/gcc/config/ia64/ia64.c
    branches/csl/sourcerygxx-4_1/gcc/output.h
    branches/csl/sourcerygxx-4_1/gcc/toplev.c
    branches/csl/sourcerygxx-4_1/gcc/varasm.c

Comment 31 KJK::Hyperion 2008-11-24 04:32:00 UTC
Created attachment 16755 [details]
testcase.c:10: warning: y renamed after being referenced in assembly

Compile test case with -funit-at-a-time

gcc -v:

Using built-in specs.
Target: mingw32
Configured with: ../gcc-4.1.3/configure --prefix=/gcc-4.1.3 --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --build=mingw32 --enable-languages=c,c++ --enable-checking=release --enable-threads=win32 --disable-win32-registry --disable-nls --disable-shared
Thread model: win32
gcc version 4.1.3 20071015 (prerelease)
Comment 32 KJK::Hyperion 2008-11-24 04:32:56 UTC
I've been told that this is related to the test case I just attached
Comment 33 Danny Smith 2008-11-24 06:41:07 UTC
(In reply to comment #32)
> I've been told that this is related to the test case I just attached

Your testcase is more closely related to PR 38054.

Danny
Comment 34 Steven Bosscher 2010-08-09 21:13:09 UTC
The FIXME here is this one in varasm.c:

-------------------------------
/* We delay assemble_external processing until
   the compilation unit is finalized.  This is the best we can do for
   right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay
   it all the way to final.  See PR 17982 for further discussion.  */
static GTY(()) tree pending_assemble_externals;
-------------------------------

According to http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00491.html:

The *proper* solution to this problem is to remove all calls to
assemble_external from the front ends and even the RTL expander; it
should only be done from final.c and varasm.c as we are emitting
assembly. 

$ grep assemble_external c* */*.[ch] ada/gcc-interface/*.[ch]
calls.c:          assemble_external (fndecl);
calls.c:  assemble_external_libcall (fun);
cp/cp-tree.h:   so that assemble_external will work properly.  So we have this flag to
objc/objc-act.c:      assemble_external (objc_get_class_decl);
objc/objc-act.c:  assemble_external (func);
objc/objc-act.c:  assemble_external (objc_assign_global_decl);
objc/objc-act.c:  assemble_external (objc_assign_strong_cast_decl);
objc/objc-act.c:              assemble_external (super_class);

I think the ones in calls.c are OK.  So only ObjC still calls assemble_external. Iain?
Comment 35 Iain Sandoe 2010-08-10 13:01:21 UTC
(In reply to comment #34)

> I think the ones in calls.c are OK.  So only ObjC still calls
> assemble_external. Iain?

AFAICT, assemble_external () [no longer?] emits any assembly nor does it call DECL_ASSEMBLER_NAME:

it seems to check for a weak function and add that to the weak functions list
and then (if the target defines ASM_OUTPUT_EXTERNAL) adds the decl to the pending list which is output from assemble_pending_externals () called from toplev.c.

varasm (assemble variable) says:

 /* Normally no need to say anything here for external references,
     since assemble_external is called by the language-specific code
     when a declaration is first seen.  */

  if (DECL_EXTERNAL (decl))
    return;

I would imagine that if this were replaced by:

  if (DECL_EXTERNAL (decl))
   {
    assemble_external (decl);
    return;
   }

we should be able to remove the calls in ObjC (I'll try this later).

OTOH, I wonder if we have a case of a solved problem with the bug left open....?

[BTW, I also have checking the status of 24777 on my TODO.]


Comment 36 Jeffrey A. Law 2015-02-06 08:11:57 UTC
This was fixed in 2012.