This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH/RFA] PR target/16665: SH thunk with -fPIC
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: gcc-patches at gcc dot gnu dot org
- Cc: joern dot rennecke at superh dot com, aoliva at redhat dot com
- Date: Sun, 01 Aug 2004 09:03:33 +0900 (JST)
- Subject: [PATCH/RFA] PR target/16665: SH thunk with -fPIC
Hi,
The attached patch is to fix PR target/16665 which is a problem for
the thunk routine in PIC case. For PIC, sh_output_mi_thunk outputs
a jmp to .LTHUNK*@GOTOFF which assumes that the PIC register is set
to GOT. The patch does it and restore & save the original value of
the PIC register.
BTW, the testcase given in PR causes an ICE for sh64-elf with -fPIC:
lib.cxx:3: error: insn does not satisfy its constraints:
(insn 5 4 6 (set (reg:SI 128 tr0)
(const:SI (unspec [
(symbol_ref:SI ("*.LTHUNK0") [flags 0x3] <function_decl 0x402154d8 *.LTHUNK0>)
] 8))) 126 {*movsi_media} (nil)
(nil))
lib.cxx:3: internal compiler error: in extract_constrain_insn_cached, at recog.c:1985
and the if (flag_pic && TARGET_SHMEDIA) part of the patch below is
for this ICE. It'd be better to send this hunk as a separated one,
though it's required to fix the PR in SHmedia PIC case anyway.
The patch is tested with bootstrap and regtest on the mainline for
native sh4-unknown-linux-gnu. It's also regtested on the mainline
for x86 cross sh64-elf.
Regards,
kaz
--
2004-07-31 Kaz Kojima <kkojima@gcc.gnu.org>
PR target/16665
* config/sh/sh.c (sh_output_mi_thunk): Load GOT to the PIC
register temporary for PIC case. Use one more intermediate
scrach register to load an UNSPEC_GOTOFF expression for
SHmedia PIC case.
diff -up ORIG/gcc/gcc/config/sh/sh.c LOCAL/gcc/gcc/config/sh/sh.c
--- ORIG/gcc/gcc/config/sh/sh.c 2004-07-27 06:56:55.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.c 2004-07-27 08:40:48.000000000 +0900
@@ -9564,6 +9564,15 @@ sh_output_mi_thunk (FILE *file, tree thu
}
this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
+ /* In PIC case, we need GOT address to get the target address. We
+ can use a scratch register to save and restore the original value
+ of PIC register except for SHcompact. For SHcompact, use stack. */
+ if (flag_pic && TARGET_SHCOMPACT)
+ {
+ push (PIC_OFFSET_TABLE_REGNUM);
+ emit_insn (gen_GOTaddr2picreg ());
+ }
+
/* For SHcompact, we only have r0 for a scratch register: r1 is the
static chain pointer (even if you can't have nested virtual functions
right now, someone might implement them sometime), and the rest of the
@@ -9646,8 +9655,35 @@ sh_output_mi_thunk (FILE *file, tree thu
assemble_external (function);
TREE_USED (function) = 1;
}
+ /* We can use scratch1 to save and restore the original value of PIC
+ register except for SHcompact. */
+ if (flag_pic && ! TARGET_SHCOMPACT)
+ {
+ emit_move_insn (scratch1,
+ gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
+ emit_insn (gen_GOTaddr2picreg ());
+ }
funexp = XEXP (DECL_RTL (function), 0);
- emit_move_insn (scratch2, funexp);
+ if (flag_pic && TARGET_SHMEDIA)
+ {
+ /* When generating PIC, the following first emit_move_insn might
+ call gen_symGOT_load which expects its first operand is a general
+ purpose register so to use it as an index register at no_new_pseudos
+ period. So take one more scratch GPR. */
+ rtx scratch = gen_rtx_REG (ptr_mode, 22);
+ emit_move_insn (scratch, funexp);
+ emit_move_insn (scratch2, scratch);
+ }
+ else
+ emit_move_insn (scratch2, funexp);
+ if (flag_pic)
+ {
+ if (! TARGET_SHCOMPACT)
+ emit_move_insn (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM),
+ scratch1);
+ else
+ pop (PIC_OFFSET_TABLE_REGNUM);
+ }
funexp = gen_rtx_MEM (FUNCTION_MODE, scratch2);
sibcall = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX));
SIBLING_CALL_P (sibcall) = 1;