From 21c767169b833b6c22f8b1e8550e95ef792b6fd1 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 12 Nov 2014 21:16:14 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 +++++ gcc/config/i386/i386.c | 50 ++++++++++++++++++---------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/other/pr63815.C | 50 ++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/pr63815.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b98649f226..1fc374b69d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-11-12 H.J. Lu + + 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 * sdbout.c (sdbout_symbol): Eliminate register only diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 28669009014..3d7e057e64a 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 d943df62a0f..93889d4d065 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-11-12 H.J. Lu + + PR target/63815 + * g++.dg/other/pr63815.C: New test. + 2014-11-12 Paolo Carlini 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 00000000000..fce6226bb71 --- /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; +} -- 2.30.2