diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2014-11-12 21:16:14 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2014-11-12 13:16:14 -0800 |
commit | 21c767169b833b6c22f8b1e8550e95ef792b6fd1 (patch) | |
tree | 98bab630dbbcc84f4da9fe5e76576f8dc2a819ab /gcc | |
parent | 186ad798b9f039e5c824636687d0ee67f29bfc80 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/pr63815.C | 50 |
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; +} |