Hi, with reference to the old dicussion on PR 32219:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32219

It seems that a patch was submitted to put the DECL_WEAK check before
the visibility check, but that patch was never approved or applied, due
to concerns in the wording of surrounding comments:
http://gcc.gnu.org/ml/gcc-patches/2010-03/msg00666.html

That patch does solve the segfault in the PR, and happens to also solve
the other weak-hidden + section-anchor issue Nathan's other patch solves
(simply because it works the same way by rejecting DECL_WEAK inside
binds_local_p).

However, my own testing of the PR patch on recent trunk indicates a
regression: it filters out the TLS wrapper functions for C++11
thread_local variables, causing them to be called by @PLT, and failing a
few tests that check for this.

Looking into the generated code for:

extern void weakfun() __attribute__((weak,visibility("hidden")));
void foo ()
{
  if (weakfun) weakfun();
}

Under -O1 -m32 -fPIC, the address load and test will look like:

(insn 5 2 6 2 (set (reg/f:SI 60)
   (plus:SI (reg:SI 3 bx)
      (const:SI (unspec:SI [
        (symbol_ref/i:SI ("f") [flags 0x43]  <function_decl f>)
                    ] UNSPEC_GOTOFF)))) {*leasi}
     (expr_list:REG_EQUAL (symbol_ref/i:SI ("f") <function_decl f>)
        (nil)))

(insn 6 5 7 2 (set (reg:CCZ 17 flags)
        (compare:CCZ (reg/f:SI 60)
            (const_int 0 [0]))) p.c:8 3 {*cmpsi_ccno_1}
     (nil))

(jump_insn 7 6 8 2 ...

However, the logic currently used in rtlanal.c:nonzero_address_p() only
test for "PIC-reg + <constant_p>", instead of more sophisticated
checking to expose the wrapped weak symbol_ref, thus confusing CSE to
eliminate the needed test.

The DECL_WEAK test upward movement in binds_local_p() works because when
bound non-local, x86 expand turns the address load into (mem (plus
(const (unspec ... UNSPEC_GOT)))) form, with the MEM helping to avoid
the above case.

Attached is a patch to make the nonzero_address_p() work for this case,
bootstrapped and tested on i686-linux without regressions.

I have the impression from the PR32219 discussion, that the solution
should be to make all weak-hidden-undefined symbols as potentially
non-local.  However, I don't think that is needed, no? As long as the
linker added zero value is in the same module, weak hidden semantics
should remain just the same...

Thanks,
Chung-Lin

2013-05-09  Chung-Lin Tang  <clt...@codesourcery.com>

        PR target/32219
        * rtlanal.c (nonzero_address_p): Robustify checking by look
        recursively into PIC constant offsets and (CONST (UNSPEC ...))
        expressions.
Index: rtlanal.c
===================================================================
--- rtlanal.c   (revision 198735)
+++ rtlanal.c   (working copy)
@@ -387,13 +387,22 @@ nonzero_address_p (const_rtx x)
       return false;
 
     case CONST:
-      return nonzero_address_p (XEXP (x, 0));
+      {
+       rtx base, offset;
+       /* Peel away any constant offsets from the base symbol.  */
+       split_const (CONST_CAST_RTX (x), &base, &offset);
+       return nonzero_address_p (base);
+      }
 
+    case UNSPEC:
+      /* Reach for a contained symbol.  */
+      return nonzero_address_p (XVECEXP (x, 0, 0));
+
     case PLUS:
       /* Handle PIC references.  */
       if (XEXP (x, 0) == pic_offset_table_rtx
               && CONSTANT_P (XEXP (x, 1)))
-       return true;
+       return nonzero_address_p (XEXP (x, 1));
       return false;
 
     case PRE_MODIFY:
Index: testsuite/gcc.dg/visibility-21.c
===================================================================
--- testsuite/gcc.dg/visibility-21.c    (revision 0)
+++ testsuite/gcc.dg/visibility-21.c    (revision 0)
@@ -0,0 +1,12 @@
+/* PR target/32219 */
+/* { dg-do run } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-O1 -fPIC" { target fpic } } */
+
+extern void f() __attribute__((weak,visibility("hidden")));
+int main()
+{
+  if (f)
+    f();
+  return 0;
+}

Reply via email to