aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2014-11-12 21:16:14 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2014-11-12 13:16:14 -0800
commit21c767169b833b6c22f8b1e8550e95ef792b6fd1 (patch)
tree98bab630dbbcc84f4da9fe5e76576f8dc2a819ab /gcc
parent186ad798b9f039e5c824636687d0ee67f29bfc80 (diff)
downloadgcc-21c767169b833b6c22f8b1e8550e95ef792b6fd1.zip
gcc-21c767169b833b6c22f8b1e8550e95ef792b6fd1.tar.gz
gcc-21c767169b833b6c22f8b1e8550e95ef792b6fd1.tar.bz2
Initialize PIC register for large PIC model C++ thunk
gcc/ PR target/63815 * config/i386/i386.c (ix86_init_large_pic_reg): New. Extracted from ... (ix86_init_pic_reg): Here. Use ix86_init_large_pic_reg. (x86_output_mi_thunk): Set PIC register to %r11. Call ix86_init_large_pic_reg to initialize PIC register. gcc/testsuite/ PR target/63815 * g++.dg/other/pr63815.C: New test. From-SVN: r217445
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386.c50
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/other/pr63815.C50
4 files changed, 96 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8b98649..1fc374b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2014-11-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/63815
+ * config/i386/i386.c (ix86_init_large_pic_reg): New. Extracted
+ from ...
+ (ix86_init_pic_reg): Here. Use ix86_init_large_pic_reg.
+ (x86_output_mi_thunk): Set PIC register to %r11. Call
+ ix86_init_large_pic_reg to initialize PIC register.
+
2014-11-12 Kai Tietz <ktietz@redhat.com>
* sdbout.c (sdbout_symbol): Eliminate register only
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2866900..3d7e057 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6195,6 +6195,27 @@ ix86_use_pseudo_pic_reg (void)
return true;
}
+/* Initialize large model PIC register. */
+
+static void
+ix86_init_large_pic_reg (unsigned int tmp_regno)
+{
+ rtx_code_label *label;
+ rtx tmp_reg;
+
+ gcc_assert (Pmode == DImode);
+ label = gen_label_rtx ();
+ emit_label (label);
+ LABEL_PRESERVE_P (label) = 1;
+ tmp_reg = gen_rtx_REG (Pmode, tmp_regno);
+ gcc_assert (REGNO (pic_offset_table_rtx) != tmp_regno);
+ emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx,
+ label));
+ emit_insn (gen_set_got_offset_rex64 (tmp_reg, label));
+ emit_insn (ix86_gen_add3 (pic_offset_table_rtx,
+ pic_offset_table_rtx, tmp_reg));
+}
+
/* Create and initialize PIC register if required. */
static void
ix86_init_pic_reg (void)
@@ -6210,22 +6231,7 @@ ix86_init_pic_reg (void)
if (TARGET_64BIT)
{
if (ix86_cmodel == CM_LARGE_PIC)
- {
- rtx_code_label *label;
- rtx tmp_reg;
-
- gcc_assert (Pmode == DImode);
- label = gen_label_rtx ();
- emit_label (label);
- LABEL_PRESERVE_P (label) = 1;
- tmp_reg = gen_rtx_REG (Pmode, R11_REG);
- gcc_assert (REGNO (pic_offset_table_rtx) != REGNO (tmp_reg));
- emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx,
- label));
- emit_insn (gen_set_got_offset_rex64 (tmp_reg, label));
- emit_insn (ix86_gen_add3 (pic_offset_table_rtx,
- pic_offset_table_rtx, tmp_reg));
- }
+ ix86_init_large_pic_reg (R11_REG);
else
emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
}
@@ -42686,8 +42692,16 @@ x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
else
{
if (ix86_cmodel == CM_LARGE_PIC && SYMBOLIC_CONST (fnaddr))
- fnaddr = legitimize_pic_address (fnaddr,
- gen_rtx_REG (Pmode, tmp_regno));
+ {
+ // CM_LARGE_PIC always uses pseudo PIC register which is
+ // uninitialized. Since FUNCTION is local and calling it
+ // doesn't go through PLT, we use scratch register %r11 as
+ // PIC register and initialize it here.
+ SET_REGNO (pic_offset_table_rtx, R11_REG);
+ ix86_init_large_pic_reg (tmp_regno);
+ fnaddr = legitimize_pic_address (fnaddr,
+ gen_rtx_REG (Pmode, tmp_regno));
+ }
if (!sibcall_insn_operand (fnaddr, word_mode))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d943df6..93889d4d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/63815
+ * g++.dg/other/pr63815.C: New test.
+
2014-11-12 Paolo Carlini <paolo.carlini@oracle.com>
DR 1510
diff --git a/gcc/testsuite/g++.dg/other/pr63815.C b/gcc/testsuite/g++.dg/other/pr63815.C
new file mode 100644
index 0000000..fce6226
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr63815.C
@@ -0,0 +1,50 @@
+// PR target/63815
+// { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } }
+// { dg-options "-mcmodel=large" }
+// { dg-additional-options "-fpic" { target fpic } }
+
+struct ICCStringClass
+{
+ virtual int CreateString (int) = 0;
+};
+
+struct AGSCCDynamicObject
+{
+ virtual void Unserialize () = 0;
+};
+
+struct ScriptString:AGSCCDynamicObject, ICCStringClass
+{
+ virtual int CreateString (int);
+ virtual void Unserialize ();
+};
+
+int
+__attribute__ ((noinline))
+CreateNewScriptString (int fromText, bool reAllocate = true)
+{
+ return fromText;
+}
+
+int
+__attribute__ ((noinline))
+ScriptString::CreateString (int fromText)
+{
+ return CreateNewScriptString (fromText);
+}
+
+void
+__attribute__ ((noinline))
+ScriptString::Unserialize ()
+{
+}
+
+int
+main ()
+{
+ ICCStringClass *x = new ScriptString;
+
+ if (x->CreateString (1) != 1)
+ __builtin_abort ();
+ return 0;
+}