diff options
-rw-r--r-- | gcc/cgraphunit.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/visibility-22.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/visibility-23.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-1.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-2.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-3.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-4.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-5.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-6.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-7.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr32219-8.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr64317.c | 2 | ||||
-rw-r--r-- | gcc/varasm.c | 95 |
13 files changed, 260 insertions, 5 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f2c40d43d71..057eedb3429 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -803,8 +803,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 00000000000..52f59be3341 --- /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 00000000000..0fa9ef4c3e2 --- /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 00000000000..5bd80a0cd47 --- /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 00000000000..0cf2eb565c8 --- /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 00000000000..911f2a56d5d --- /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 00000000000..3d434393538 --- /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 00000000000..ee7442eb803 --- /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 00000000000..f261433538e --- /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 00000000000..12aaf7224d8 --- /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 00000000000..2e4fba07a05 --- /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 33f5b5d7002..32969fc689a 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 3f62fca04de..7b1ead0a3d1 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6802,13 +6802,101 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution) || resolution == LDPR_RESOLVED_EXEC); } +static bool +default_binds_local_p_2 (const_tree exp, int shlib) +{ + 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 not building shared library, common or initialized symbols + are also resolved locally, regardless they are weak or not. */ + if (vnode) + { + if ((!shlib && vnode->definition) + || vnode->in_other_partition + || resolution_local_p (vnode->resolution)) + resolved_locally = true; + if (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; + /* 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)) + || (TREE_CODE (exp) == FUNCTION_DECL + && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp)))) + local_p = 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 and it is resolved or defined locally, not compiling for PIC or + not weak. */ + else if ((DECL_VISIBILITY_SPECIFIED (exp) + || resolved_to_local_def) + && (resolved_locally + || !flag_pic + || !DECL_EXTERNAL (exp) + || !DECL_WEAK (exp)) + && 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 PIC, then assume that any global name can be overridden by + symbols resolved from other modules. */ + else if (shlib) + local_p = false; + /* Otherwise we're left with initialized (or non-common) global data + which is of necessity defined locally. */ + else + local_p = true; + + return local_p; +} + /* 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); + return default_binds_local_p_2 (exp, flag_shlib); } bool @@ -7449,9 +7537,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); } |