+2015-04-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/65780
+ * output.h (default_binds_local_p_3): New.
+ * varasm.c (default_binds_local_p_3): Make it public. Take an
+ argument to indicate if common symbol may be local. If common
+ symbol may be local, treat non-external variable as defined
+ locally.
+ (default_binds_local_p_2): Pass !flag_pic to default_binds_local_p_3.
+ (default_binds_local_p_1): Pass false to default_binds_local_p_3.
+ * config/i386/i386.c (ix86_binds_local_p): New.
+ (TARGET_BINDS_LOCAL_P): Replace default_binds_local_p_2 with
+ ix86_binds_local_p.
+
2015-04-17 Jakub Jelinek <jakub@redhat.com>
PR debug/65771
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
#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
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);
+2015-04-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/65780
+ * gcc.dg/pr65780-1.c: New test.
+ * gcc.dg/pr65780-2.c: Likewise.
+ * gcc.target/i386/pr32219-9.c: Likewise.
+ * gcc.target/i386/pr32219-1.c (xxx): Make it initialized common
+ symbol.
+ * gcc.target/i386/pr64317.c (c): Initialize.
+
2015-04-17 H.J. Lu <hongjiu.lu@intel.com>
PR target/65612
--- /dev/null
+/* PR target/65780 */
+/* { dg-do link { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2" } */
+
+int optopt;
+
+int
+main ()
+{
+ optopt = 4;
+ return 0;
+}
--- /dev/null
+/* 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;
+}
/* { dg-do compile { target *-*-linux* } } */
/* { dg-options "-O2 -fpie" } */
-/* Common symbol with -fpie. */
+/* Initialized common symbol with -fpie. */
+int xxx = 5;
int xxx;
int
--- /dev/null
+/* { 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 } } } } */
/* { 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();
|| resolution == LDPR_RESOLVED_EXEC);
}
-static bool
+/* COMMON_LOCAL_P is true means that the linker can guarantee that an
+ uninitialized common symbol in the executable will still be defined
+ (through COPY relocation) in the executable. */
+
+bool
default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
- bool extern_protected_data)
+ bool extern_protected_data, bool common_local_p)
{
/* A non-decl is an entry in the constant pool. */
if (!DECL_P (exp))
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_local_p is true. */
+ bool defined_locally = (!DECL_EXTERNAL (exp)
+ && (!uninited_common || common_local_p));
if (symtab_node *node = symtab_node::get (exp))
{
if (node->in_other_partition)
/* 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
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