Hi, r216154 exposed an x86 backend bug. For large PIC mode thunk, there are
if (ix86_cmodel == CM_LARGE_PIC && SYMBOLIC_CONST (fnaddr)) fnaddr = legitimize_pic_address (fnaddr, gen_rtx_REG (Pmode, tmp_regno)); and legitimize_pic_address does: if (reg != 0) { new_rtx = expand_simple_binop (Pmode, PLUS, reg, pic_offset_table_rtx, tmpreg, 1, OPTAB_DIRECT); new_rtx = reg; } However, pic_offset_table_rtx was never initialized. Befor r216154, we generated thunk with random value in hardcoded PIC register. After r216154, compiler crashes. This patch sets PIC register to %r11 and initialize it. Tested on Linux/x86-64. OK for trunk and backport to 4.8/4.9 branches? Thanks. H.J. --- gcc/ 2014-11-12 H.J. Lu <hongjiu...@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. gcc/testsuite/ 2014-11-12 H.J. Lu <hongjiu...@intel.com> PR target/63815 * g++.dg/other/pr63815.C: New test. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 2866900..0bd3ff3 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,12 @@ 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)); + { + 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/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; +}