summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/i386/i386.c15
-rw-r--r--gcc/output.h1
-rw-r--r--gcc/testsuite/gcc.dg/pr65780-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr65780-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-9.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr64317.c2
-rw-r--r--gcc/varasm.c31
8 files changed, 77 insertions, 15 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1f20ff394c8..72e6bc27f62 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -51793,6 +51793,19 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
return 2;
}
+/* For i386, common symbol is local only for non-PIE binaries. For
+ x86-64, common symbol is local only for non-PIE binaries or linker
+ supports copy reloc in PIE binaries. */
+
+static bool
+ix86_binds_local_p (const_tree exp)
+{
+ return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
+ (!flag_pic
+ || (TARGET_64BIT
+ && HAVE_LD_PIE_COPYRELOC != 0)));
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
@@ -51927,7 +51940,7 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
#define TARGET_BINDS_LOCAL_P darwin_binds_local_p
#else
#undef TARGET_BINDS_LOCAL_P
-#define TARGET_BINDS_LOCAL_P default_binds_local_p_2
+#define TARGET_BINDS_LOCAL_P ix86_binds_local_p
#endif
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
#undef TARGET_BINDS_LOCAL_P
diff --git a/gcc/output.h b/gcc/output.h
index 53e47d03b3a..81d2ad29a83 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -587,6 +587,7 @@ extern bool default_use_anchors_for_symbol_p (const_rtx);
extern bool default_binds_local_p (const_tree);
extern bool default_binds_local_p_1 (const_tree, int);
extern bool default_binds_local_p_2 (const_tree);
+extern bool default_binds_local_p_3 (const_tree, bool, bool, bool, bool);
extern void default_globalize_label (FILE *, const char *);
extern void default_globalize_decl_name (FILE *, tree);
extern void default_emit_unwind_label (FILE *, tree, int, int);
diff --git a/gcc/testsuite/gcc.dg/pr65780-1.c b/gcc/testsuite/gcc.dg/pr65780-1.c
new file mode 100644
index 00000000000..b586211b649
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr65780-1.c
@@ -0,0 +1,12 @@
+/* PR target/65780 */
+/* { dg-do link { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2" } */
+
+int optopt;
+
+int
+main ()
+{
+ optopt = 4;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr65780-2.c b/gcc/testsuite/gcc.dg/pr65780-2.c
new file mode 100644
index 00000000000..bff33237cf5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr65780-2.c
@@ -0,0 +1,13 @@
+/* PR target/65780 */
+/* { dg-do link { target *-*-linux* *-*-gnu* } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fpie" } */
+
+int optopt;
+
+int
+main ()
+{
+ optopt = 4;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
index 5bd80a0cd47..2622f663059 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
@@ -1,7 +1,8 @@
/* { dg-do compile { target *-*-linux* } } */
/* { dg-options "-O2 -fpie" } */
-/* Common symbol with -fpie. */
+/* Initialized common symbol with -fpie. */
+int xxx = 5;
int xxx;
int
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-9.c b/gcc/testsuite/gcc.target/i386/pr32219-9.c
new file mode 100644
index 00000000000..8c218266359
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target pie_copyreloc } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Uninitialized 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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
index 32969fc689a..8cac6ddb25d 100644
--- a/gcc/testsuite/gcc.target/i386/pr64317.c
+++ b/gcc/testsuite/gcc.target/i386/pr64317.c
@@ -3,7 +3,7 @@
/* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
-long c;
+long c = 1;
int bar();
diff --git a/gcc/varasm.c b/gcc/varasm.c
index e644b1daa7e..609b6443ea4 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6809,9 +6809,9 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
|| resolution == LDPR_RESOLVED_EXEC);
}
-static bool
+bool
default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
- bool extern_protected_data)
+ bool extern_protected_data, bool common_maybe_local)
{
/* A non-decl is an entry in the constant pool. */
if (!DECL_P (exp))
@@ -6836,7 +6836,16 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
because dynamic linking might overwrite symbols
in shared libraries. */
bool resolved_locally = false;
- bool defined_locally = !DECL_EXTERNAL (exp);
+
+ bool uninited_common = (DECL_COMMON (exp)
+ && (DECL_INITIAL (exp) == NULL
+ || (!in_lto_p
+ && DECL_INITIAL (exp) == error_mark_node)));
+
+ /* A non-external variable is defined locally only if it isn't
+ uninitialized COMMON variable or common_maybe_local is true. */
+ bool defined_locally = (!DECL_EXTERNAL (exp)
+ && (!uninited_common || common_maybe_local));
if (symtab_node *node = symtab_node::get (exp))
{
if (node->in_other_partition)
@@ -6878,10 +6887,7 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
/* Uninitialized COMMON variable may be unified with symbols
resolved from other modules. */
- if (DECL_COMMON (exp)
- && !resolved_locally
- && (DECL_INITIAL (exp) == NULL
- || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
+ if (uninited_common && !resolved_locally)
return false;
/* Otherwise we're left with initialized (or non-common) global data
@@ -6895,21 +6901,22 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
bool
default_binds_local_p (const_tree exp)
{
- return default_binds_local_p_3 (exp, flag_shlib != 0, true, false);
+ return default_binds_local_p_3 (exp, flag_shlib != 0, true, false, false);
}
-/* Similar to default_binds_local_p, but protected data may be
- external. */
+/* Similar to default_binds_local_p, but common symbol may be local. */
+
bool
default_binds_local_p_2 (const_tree exp)
{
- return default_binds_local_p_3 (exp, flag_shlib != 0, true, true);
+ return default_binds_local_p_3 (exp, flag_shlib != 0, true, false,
+ !flag_pic);
}
bool
default_binds_local_p_1 (const_tree exp, int shlib)
{
- return default_binds_local_p_3 (exp, shlib != 0, false, false);
+ return default_binds_local_p_3 (exp, shlib != 0, false, false, false);
}
/* Return true when references to DECL must bind to current definition in