From 1ff7789b515733ab51c8c6686d1bcfcbf681b94b Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 11 Jul 1996 22:36:45 +0000 Subject: [PATCH] Deal with -fpic and inlined functions From-SVN: r12428 --- gcc/config/rs6000/rs6000.c | 125 ++++++++++++++++++++++++++++++------- gcc/config/rs6000/rs6000.h | 8 ++- 2 files changed, 109 insertions(+), 24 deletions(-) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 921bc18664e..536e1e404dd 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -372,24 +372,6 @@ rs6000_immed_double_const (i0, i1, mode) return immed_double_const (i0, i1, mode); } - -/* Return the GOT register, creating it if needed. */ - -struct rtx_def * -rs6000_got_register (value) - rtx value; -{ - if (!pic_offset_table_rtx) - { - if (reload_in_progress || reload_completed) - fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value); - - pic_offset_table_rtx = gen_reg_rtx (SImode); - } - - return pic_offset_table_rtx; -} - /* Return non-zero if this function is known to have a null epilogue. */ @@ -2077,6 +2059,81 @@ ccr_bit (op, scc_p) abort (); } } + +/* Return the GOT register, creating it if needed. */ + +struct rtx_def * +rs6000_got_register (value) + rtx value; +{ + if (!pic_offset_table_rtx) + { + if (reload_in_progress || reload_completed) + fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value); + + current_function_uses_pic_offset_table = 1; + pic_offset_table_rtx = gen_rtx (REG, Pmode, GOT_TOC_REGNUM); + } + + return pic_offset_table_rtx; +} + + +/* Replace all occurances of register FROM with an new pseduo register in an insn X. + Store the pseudo register used in REG. + This is only safe during FINALIZE_PIC, since the registers haven't been setup + yet. */ + +static rtx +rs6000_replace_regno (x, from, reg) + rtx x; + int from; + rtx *reg; +{ + register int i, j; + register char *fmt; + + /* Allow this function to make replacements in EXPR_LISTs. */ + if (!x) + return x; + + switch (GET_CODE (x)) + { + case SCRATCH: + case PC: + case CC0: + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case LABEL_REF: + return x; + + case REG: + if (REGNO (x) == from) + { + if (! *reg) + *reg = gen_reg_rtx (Pmode); + + return *reg; + } + + return x; + } + + fmt = GET_RTX_FORMAT (GET_CODE (x)); + for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + XEXP (x, i) = rs6000_replace_regno (XEXP (x, i), from, reg); + else if (fmt[i] == 'E') + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + XVECEXP (x, i, j) = rs6000_replace_regno (XVECEXP (x, i, j), from, reg); + } + + return x; +} + /* By generating position-independent code, when two different programs (A and B) share a common library (libC.a), the text of @@ -2098,17 +2155,39 @@ rs6000_finalize_pic () { if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) { - /* If a PIC register has been created, insert the pic initialization - at the function beginning. */ - if (pic_offset_table_rtx) + /* Loop through all of the insns, replacing the special GOT_TOC_REGNUM + with an appropriate pseduo register. If we find we need GOT/TOC, + add the appropriate init code. */ + if (flag_pic) { rtx insn = get_insns (); - rtx init = gen_init_v4_pic (pic_offset_table_rtx); + rtx reg = NULL_RTX; + rtx first_insn; if (GET_CODE (insn) == NOTE) insn = next_nonnote_insn (insn); - emit_insn_before (init, insn); + first_insn = insn; + for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn)) + { + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') + { + PATTERN (insn) = rs6000_replace_regno (PATTERN (insn), + GOT_TOC_REGNUM, + ®); + + if (REG_NOTES (insn)) + REG_NOTES (insn) = rs6000_replace_regno (REG_NOTES (insn), + GOT_TOC_REGNUM, + ®); + } + } + + if (reg) + { + rtx init = gen_init_v4_pic (reg); + emit_insn_before (init, first_insn); + } } } } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f291bae62a3..58632eb9b34 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -847,10 +847,16 @@ extern struct rs6000_cpu_select rs6000_select[]; /* Special register that represents memory, used for float/int conversions. */ #define FPMEM_REGNUM 76 +/* Register to use as a placeholder for the GOT/allocated TOC register. + FINALIZE_PIC will change all uses of this register to a an appropriate + pseudo register when it adds the code to setup the GOT. We use r2 + because it is a reserved register in all of the ABI's. */ +#define GOT_TOC_REGNUM 2 + /* Place that structure value return address is placed. On the RS/6000, it is passed as an extra parameter. */ -#define STRUCT_VALUE 0 +#define STRUCT_VALUE 0 /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. -- 2.30.2