Hello! Symbol references are not legitimate sibcall operands for -mcmodel=large, so have to be moved to registers (using movabs). Unfortunately, moving symbol references for CM_LARGE_PIC requires PIC fixup which by default generates Pmode pseudos. When generating thunk in x86_output_mi_thunk, we are already past reload time, so pseudos are not allowed.
The solution is to call legitimize_pic_address with hard temporary Pmode register in advance, to avoid situations that would lead to generation of pseudo registers in emit_move_insn. Patched gcc generates: .set .LTHUNK0,_ZN1D4foo2Ev .p2align 4,,15 .globl _ZThn16_N1D4foo2Ev .type _ZThn16_N1D4foo2Ev, @function _ZThn16_N1D4foo2Ev: .LFB15: .cfi_startproc subq $16, %rdi movabsq $.LTHUNK0@GOTOFF, %r10 addq %rbx, %r10 jmp *%r10 .cfi_endproc .LFE15: .size _ZThn16_N1D4foo2Ev, .-_ZThn16_N1D4foo2Ev which is the same as when calling static local functions with -mcmodel=large -fPIC. 2012-07-06 Uros Bizjak <ubiz...@gmail.com> PR target/53811 * config/i386/i386.c (x86_output_mi_thunk): For CM_LARGE_PIC model, emit PIC sequence for fnaddr symbol reference in advance. Tested on x86_64-pc-linux-gnu {,-m32} and by testing various runtime tests in testsuite/g++.dg/inherit with "-mcmodel=large -fPIC". Committed to mainline SVN, will backport to 4.7. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 189310) +++ config/i386/i386.c (working copy) @@ -33057,6 +33057,10 @@ x86_output_mi_thunk (FILE *file, emit_jump_insn (gen_indirect_jump (fnaddr)); else { + if (ix86_cmodel == CM_LARGE_PIC && SYMBOLIC_CONST (fnaddr)) + fnaddr = legitimize_pic_address (fnaddr, + gen_rtx_REG (Pmode, tmp_regno)); + if (!sibcall_insn_operand (fnaddr, word_mode)) { tmp = gen_rtx_REG (word_mode, tmp_regno);