From patchwork Fri Feb 13 00:04:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 439358 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5EA4F14017A for ; Fri, 13 Feb 2015 11:05:16 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=PiLNPBGRhjQetO64b Ldni+d56bGLP4AsAvsEH5qfYU2OhArsX3o5DObQK4FWj9aQFCTnEAI4jgO7/UD3P +ZR5nfp+Ikog+plGAGhbG7jzELm3uLi2EsuxsGJNJJxKsdBfxQdwYnstUWnO8Q17 8eC57wHA7ewwYtcxlukOcxgXNA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=DJjniPrDo+XzZY7e1F23ES7 swpg=; b=O1nbYhVyKhtHXdOR7Hyj4EZzxjGa0oay69nU8lwhBGfRx22ftSy+9ku Rtq3xguZfFYiiDXNHM8JIhNefHEHcBxh7InsuODjtp4JphwYumxHDP1qssJcCjzj GOzNDYtcXCqm4q5dUzu0yIwiPUkNZ30UNBm7nXxkbM8jvBQDIhOc= Received: (qmail 25217 invoked by alias); 13 Feb 2015 00:05:09 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 25205 invoked by uid 89); 13 Feb 2015 00:05:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 13 Feb 2015 00:05:06 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t1D050jk011346 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 12 Feb 2015 19:05:00 -0500 Received: from anchor.twiddle.net (vpn-232-190.phx2.redhat.com [10.3.232.190]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t1D04xn7013818; Thu, 12 Feb 2015 19:04:59 -0500 Message-ID: <54DD3FA9.3010609@redhat.com> Date: Thu, 12 Feb 2015 16:04:57 -0800 From: Richard Henderson User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: "H.J. Lu" CC: Jack Howarth , GCC Patches , Mike Stump , Iain Sandoe , Jan Hubicka Subject: Re: [PATCH] PR rtl-optimization/32219: optimizer causees wrong code in pic/hidden/weak symbol checking References: <20150206162314.GA12597@intel.com> <20150207122739.GA25185@gmail.com> <20150207155606.GA14159@gmail.com> <20150207164507.GA19402@gmail.com> <54DA75D2.40402@redhat.com> <54DC46BF.5060503@redhat.com> <54DCFE10.3050906@redhat.com> In-Reply-To: X-IsSubscribed: yes On 02/12/2015 03:05 PM, H.J. Lu wrote: > @@ -6830,9 +6830,15 @@ default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate) > bool resolved_locally = false; > if (symtab_node *node = symtab_node::get (exp)) > { > - /* When not building shared library and weak_dominate is true: > - weak, common or initialized symbols are resolved locally. */ > - if ((weak_dominate && !shlib && node->definition) > + /* When weak_dominate is true and not building shared library or > + non-default visibility is specified by user: weak, common or > + initialized symbols are resolved locally. > + */ > + if (((!shlib > + || (DECL_VISIBILITY_SPECIFIED (exp) > + && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)) > + && weak_dominate > + && node->definition) > || node->in_other_partition > || resolution_local_p (node->resolution)) > resolved_locally = true; Hum. I don't find that particularly easy to reason with either. How about this? I'm about half-way through regression testing on it. I re-instated the use of resolution_to_local_definition_p, and attempt to infer a proper value for that when lto isn't in use. I use this to eliminate only undef-weak early, rather than non-dominate weak. I re-instated the use of the existence of the local definition in the DECL_VISIBILITY test. But unlike before, I reason that this allows us to eliminate the second visibility check. We either have an assertion from the user (SPECIFIED), or we know we have a definition. We no longer rely on the DECL_EXTERNAL test in the middle eliminating symbols without a definition. I shuffled some of the "return false" tests around among themselves, attempting to put the simplest test first. No change in behavior there. (First patch is delta from the 5-patch bundle; second patch is the composite from trunk, to avoid confusion.) r~ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f2c40d4..942826d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -442,8 +442,10 @@ cgraph_node::finalize_function (tree decl, bool no_collect) node->local.redefined_extern_inline = true; } - notice_global_symbol (decl); + /* Set definition first before calling notice_global_symbol so that + it is available to notice_global_symbol. */ node->definition = true; + notice_global_symbol (decl); node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; /* With -fkeep-inline-functions we are keeping all inline functions except @@ -803,8 +805,10 @@ varpool_node::finalize_decl (tree decl) if (node->definition) return; - notice_global_symbol (decl); + /* Set definition first before calling notice_global_symbol so that + it is available to notice_global_symbol. */ node->definition = true; + notice_global_symbol (decl); if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) /* Traditionally we do not eliminate static variables when not optimizing and when not doing toplevel reoder. */ diff --git a/gcc/testsuite/gcc.dg/visibility-22.c b/gcc/testsuite/gcc.dg/visibility-22.c new file mode 100644 index 0000000..52f59be --- /dev/null +++ b/gcc/testsuite/gcc.dg/visibility-22.c @@ -0,0 +1,17 @@ +/* PR target/32219 */ +/* { dg-do run } */ +/* { dg-require-visibility "" } */ +/* { dg-options "-O2 -fPIC" { target fpic } } */ +/* This test requires support for undefined weak symbols. This support + is not available on hppa*-*-hpux*. The test is skipped rather than + xfailed to suppress the warning that would otherwise arise. */ +/* { dg-skip-if "" { "hppa*-*-hpux*" "*-*-aix*" "*-*-darwin*" } "*" { "" } } */ + +extern void foo () __attribute__((weak,visibility("hidden"))); +int +main() +{ + if (foo) + foo (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/visibility-23.c b/gcc/testsuite/gcc.dg/visibility-23.c new file mode 100644 index 0000000..0fa9ef4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/visibility-23.c @@ -0,0 +1,15 @@ +/* PR target/32219 */ +/* { dg-do compile } */ +/* { dg-require-visibility "" } */ +/* { dg-final { scan-hidden "foo" } } */ +/* { dg-options "-O2 -fPIC" { target fpic } } */ +/* { dg-skip-if "" { "hppa*-*-hpux*" "*-*-aix*" "*-*-darwin*" } "*" { "" } } */ + +extern void foo () __attribute__((weak,visibility("hidden"))); +int +main() +{ + if (foo) + foo (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c new file mode 100644 index 0000000..5bd80a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie" } */ + +/* Common symbol with -fpie. */ +int xxx; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c new file mode 100644 index 0000000..0cf2eb5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic" } */ + +/* Common symbol with -fpic. */ +int xxx; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-3.c b/gcc/testsuite/gcc.target/i386/pr32219-3.c new file mode 100644 index 0000000..911f2a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie" } */ + +/* Weak common symbol with -fpie. */ +__attribute__((weak)) +int xxx; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-4.c b/gcc/testsuite/gcc.target/i386/pr32219-4.c new file mode 100644 index 0000000..3d43439 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic" } */ + +/* Weak common symbol with -fpic. */ +__attribute__((weak)) +int xxx; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-5.c b/gcc/testsuite/gcc.target/i386/pr32219-5.c new file mode 100644 index 0000000..ee7442e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie" } */ + +/* Initialized symbol with -fpie. */ +int xxx = -1; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-6.c b/gcc/testsuite/gcc.target/i386/pr32219-6.c new file mode 100644 index 0000000..f261433 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-6.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic" } */ + +/* Initialized symbol with -fpic. */ +int xxx = -1; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-7.c b/gcc/testsuite/gcc.target/i386/pr32219-7.c new file mode 100644 index 0000000..12aaf72 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-7.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpie" } */ + +/* Weak initialized symbol with -fpie. */ +__attribute__((weak)) +int xxx = -1; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr32219-8.c b/gcc/testsuite/gcc.target/i386/pr32219-8.c new file mode 100644 index 0000000..2e4fba0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr32219-8.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic" } */ + +/* Weak initialized symbol with -fpic. */ +__attribute__((weak)) +int xxx = -1; + +int +foo () +{ + return xxx; +} + +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c index 33f5b5d..32969fc 100644 --- a/gcc/testsuite/gcc.target/i386/pr64317.c +++ b/gcc/testsuite/gcc.target/i386/pr64317.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { *-*-linux* && ia32 } } } */ /* { dg-options "-O2 -fpie" } */ /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */ -/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */ +/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */ /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */ long c; diff --git a/gcc/varasm.c b/gcc/varasm.c index 3f62fca..0211306 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6802,97 +6802,96 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution) || resolution == LDPR_RESOLVED_EXEC); } -/* Assume ELF-ish defaults, since that's pretty much the most liberal - wrt cross-module name binding. */ - -bool -default_binds_local_p (const_tree exp) -{ - return default_binds_local_p_1 (exp, flag_shlib); -} - -bool -default_binds_local_p_1 (const_tree exp, int shlib) +static bool +default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate) { - bool local_p; - bool resolved_locally = false; - bool resolved_to_local_def = false; - - /* With resolution file in hands, take look into resolutions. - We can't just return true for resolved_locally symbols, - because dynamic linking might overwrite symbols - in shared libraries. */ - if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp) - && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) - { - varpool_node *vnode = varpool_node::get (exp); - if (vnode && (resolution_local_p (vnode->resolution) || vnode->in_other_partition)) - resolved_locally = true; - if (vnode - && resolution_to_local_definition_p (vnode->resolution)) - resolved_to_local_def = true; - } - else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp)) - { - struct cgraph_node *node = cgraph_node::get (exp); - if (node - && (resolution_local_p (node->resolution) || node->in_other_partition)) - resolved_locally = true; - if (node - && resolution_to_local_definition_p (node->resolution)) - resolved_to_local_def = true; - } - /* A non-decl is an entry in the constant pool. */ if (!DECL_P (exp)) - local_p = true; + return true; + /* Weakrefs may not bind locally, even though the weakref itself is always static and therefore local. Similarly, the resolver for ifunc functions might resolve to a non-local function. FIXME: We can resolve the weakref case more curefuly by looking at the weakref alias. */ - else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)) + if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)) || (TREE_CODE (exp) == FUNCTION_DECL && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp)))) - local_p = false; + return false; + /* Static variables are always local. */ - else if (! TREE_PUBLIC (exp)) - local_p = true; - /* A variable is local if the user has said explicitly that it will - be. */ - else if ((DECL_VISIBILITY_SPECIFIED (exp) - || resolved_to_local_def) - && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) - local_p = true; - /* Variables defined outside this object might not be local. */ - else if (DECL_EXTERNAL (exp) && !resolved_locally) - local_p = false; - /* If defined in this object and visibility is not default, must be - local. */ - else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) - local_p = true; - /* Default visibility weak data can be overridden by a strong symbol - in another module and so are not local. */ - else if (DECL_WEAK (exp) - && !resolved_locally) - local_p = false; + if (! TREE_PUBLIC (exp)) + return true; + + /* With resolution file in hand, take look into resolutions. + We can't just return true for resolved_locally symbols, + because dynamic linking might overwrite symbols + in shared libraries. */ + bool resolved_locally = false; + bool defined_locally = false; + if (symtab_node *node = symtab_node::get (exp)) + { + if (node->definition || node->in_other_partition) + { + defined_locally = true; + resolved_locally = (weak_dominate && !shlib); + } + if (resolution_to_local_definition_p (node->resolution)) + defined_locally = resolved_locally = true; + else if (resolution_local_p (node->resolution)) + resolved_locally = true; + } + + /* Undefined weak symbols are never defined locally. */ + if (DECL_WEAK (exp) && !defined_locally) + return false; + + /* A symbol is local if the user has said explicitly that it will be, + or if we have a definition for the symbol. We cannot infer visibility + for undefined symbols. */ + if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT + && (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally)) + return true; + /* If PIC, then assume that any global name can be overridden by symbols resolved from other modules. */ - else if (shlib) - local_p = false; + if (shlib) + return false; + + /* Variables defined outside this object might not be local. */ + if (DECL_EXTERNAL (exp) && !resolved_locally) + return false; + + /* Non-dominant weak symbols are not defined locally. */ + if (DECL_WEAK (exp) && !resolved_locally) + return false; + /* Uninitialized COMMON variable may be unified with symbols resolved from other modules. */ - else if (DECL_COMMON (exp) - && !resolved_locally - && (DECL_INITIAL (exp) == NULL - || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node))) - local_p = false; + if (DECL_COMMON (exp) + && !resolved_locally + && (DECL_INITIAL (exp) == NULL + || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node))) + return false; + /* Otherwise we're left with initialized (or non-common) global data which is of necessity defined locally. */ - else - local_p = true; + return true; +} + +/* Assume ELF-ish defaults, since that's pretty much the most liberal + wrt cross-module name binding. */ + +bool +default_binds_local_p (const_tree exp) +{ + return default_binds_local_p_2 (exp, flag_shlib != 0, true); +} - return local_p; +bool +default_binds_local_p_1 (const_tree exp, int shlib) +{ + return default_binds_local_p_2 (exp, shlib != 0, false); } /* Return true when references to DECL must bind to current definition in @@ -6914,22 +6913,14 @@ decl_binds_to_current_def_p (const_tree decl) return false; if (!TREE_PUBLIC (decl)) return true; + /* When resolution is available, just use it. */ - if (TREE_CODE (decl) == VAR_DECL - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) + if (symtab_node *node = symtab_node::get (decl)) { - varpool_node *vnode = varpool_node::get (decl); - if (vnode - && vnode->resolution != LDPR_UNKNOWN) - return resolution_to_local_definition_p (vnode->resolution); - } - else if (TREE_CODE (decl) == FUNCTION_DECL) - { - struct cgraph_node *node = cgraph_node::get (decl); - if (node - && node->resolution != LDPR_UNKNOWN) + if (node->resolution != LDPR_UNKNOWN) return resolution_to_local_definition_p (node->resolution); } + /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks binds locally but still can be overwritten), DECL_COMMON (can be merged with a non-common definition somewhere in the same module) or @@ -7449,9 +7440,10 @@ default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED, { /* We output the name if and only if TREE_SYMBOL_REFERENCED is set in order to avoid putting out names that are never really - used. */ + used. Always output visibility specified in the source. */ if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - && targetm.binds_local_p (decl)) + && (DECL_VISIBILITY_SPECIFIED (decl) + || targetm.binds_local_p (decl))) maybe_assemble_visibility (decl); } diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 057eedb..942826d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -442,8 +442,10 @@ cgraph_node::finalize_function (tree decl, bool no_collect) node->local.redefined_extern_inline = true; } - notice_global_symbol (decl); + /* Set definition first before calling notice_global_symbol so that + it is available to notice_global_symbol. */ node->definition = true; + notice_global_symbol (decl); node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; /* With -fkeep-inline-functions we are keeping all inline functions except diff --git a/gcc/varasm.c b/gcc/varasm.c index 9f79416..0211306 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6828,37 +6828,42 @@ default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate) because dynamic linking might overwrite symbols in shared libraries. */ bool resolved_locally = false; + bool defined_locally = false; if (symtab_node *node = symtab_node::get (exp)) { - /* When not building shared library and weak_dominate is true: - weak, common or initialized symbols are resolved locally. */ - if ((weak_dominate && !shlib && node->definition) - || node->in_other_partition - || resolution_local_p (node->resolution)) + if (node->definition || node->in_other_partition) + { + defined_locally = true; + resolved_locally = (weak_dominate && !shlib); + } + if (resolution_to_local_definition_p (node->resolution)) + defined_locally = resolved_locally = true; + else if (resolution_local_p (node->resolution)) resolved_locally = true; } - /* Undefined (or non-dominant) weak symbols are not defined locally. */ - if (DECL_WEAK (exp) && !resolved_locally) + /* Undefined weak symbols are never defined locally. */ + if (DECL_WEAK (exp) && !defined_locally) return false; - /* A variable is local if the user has said explicitly that it will be. */ - if (DECL_VISIBILITY_SPECIFIED (exp) - && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) + /* A symbol is local if the user has said explicitly that it will be, + or if we have a definition for the symbol. We cannot infer visibility + for undefined symbols. */ + if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT + && (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally)) return true; + /* If PIC, then assume that any global name can be overridden by + symbols resolved from other modules. */ + if (shlib) + return false; + /* Variables defined outside this object might not be local. */ if (DECL_EXTERNAL (exp) && !resolved_locally) return false; - /* If defined in this object and visibility is not default, - must be local. */ - if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) - return true; - - /* If PIC, then assume that any global name can be overridden by - symbols resolved from other modules. */ - if (shlib) + /* Non-dominant weak symbols are not defined locally. */ + if (DECL_WEAK (exp) && !resolved_locally) return false; /* Uninitialized COMMON variable may be unified with symbols