return bitmap_bit_p (DF_LR_OUT (bb), 12);
}
+/* Return whether we need to emit an ELFv2 global entry point prologue. */
+
+static bool
+rs6000_global_entry_point_needed_p (void)
+{
+ /* Only needed for the ELFv2 ABI. */
+ if (DEFAULT_ABI != ABI_ELFv2)
+ return false;
+
+ /* With -msingle-pic-base, we assume the whole program shares the same
+ TOC, so no global entry point prologues are needed anywhere. */
+ if (TARGET_SINGLE_PIC_BASE)
+ return false;
+
+ /* Ensure we have a global entry point for thunks. ??? We could
+ avoid that if the target routine doesn't need a global entry point,
+ but we do not know whether this is the case at this point. */
+ if (cfun->is_thunk)
+ return true;
+
+ /* For regular functions, rs6000_emit_prologue sets this flag if the
+ routine ever uses the TOC pointer. */
+ return cfun->machine->r2_setup_needed;
+}
+
/* Emit function prologue as insns. */
void
/* ELFv2 ABI r2 setup code and local entry point. This must follow
immediately after the global entry point label. */
- if (DEFAULT_ABI == ABI_ELFv2 && cfun->machine->r2_setup_needed)
+ if (rs6000_global_entry_point_needed_p ())
{
const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
- fprintf (file, "0:\taddis 2,12,.TOC.-0b@ha\n");
- fprintf (file, "\taddi 2,2,.TOC.-0b@l\n");
+ (*targetm.asm_out.internal_label) (file, "LCF", rs6000_pic_labelno);
+
+ if (TARGET_CMODEL != CMODEL_LARGE)
+ {
+ /* In the small and medium code models, we assume the TOC is less
+ 2 GB away from the text section, so it can be computed via the
+ following two-instruction sequence. */
+ char buf[256];
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ fprintf (file, "0:\taddis 2,12,.TOC.-");
+ assemble_name (file, buf);
+ fprintf (file, "@ha\n");
+ fprintf (file, "\taddi 2,2,.TOC.-");
+ assemble_name (file, buf);
+ fprintf (file, "@l\n");
+ }
+ else
+ {
+ /* In the large code model, we allow arbitrary offsets between the
+ TOC and the text section, so we have to load the offset from
+ memory. The data field is emitted directly before the global
+ entry point in rs6000_elf_declare_function_name. */
+ char buf[256];
+
+#ifdef HAVE_AS_ENTRY_MARKERS
+ /* If supported by the linker, emit a marker relocation. If the
+ total code size of the final executable or shared library
+ happens to fit into 2 GB after all, the linker will replace
+ this code sequence with the sequence for the small or medium
+ code model. */
+ fprintf (file, "\t.reloc .,R_PPC64_ENTRY\n");
+#endif
+ fprintf (file, "\tld 2,");
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
+ assemble_name (file, buf);
+ fprintf (file, "-");
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ assemble_name (file, buf);
+ fprintf (file, "(12)\n");
+ fprintf (file, "\tadd 2,2,12\n");
+ }
fputs ("\t.localentry\t", file);
assemble_name (file, name);
SIBLING_CALL_P (insn) = 1;
emit_barrier ();
- /* Ensure we have a global entry point for the thunk. ??? We could
- avoid that if the target routine doesn't need a global entry point,
- but we do not know whether this is the case at this point. */
- if (DEFAULT_ABI == ABI_ELFv2
- && !TARGET_SINGLE_PIC_BASE)
- cfun->machine->r2_setup_needed = true;
-
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
instruction scheduling worth while. Note that use_thunk calls
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
+ if (TARGET_CMODEL == CMODEL_LARGE && rs6000_global_entry_point_needed_p ())
+ {
+ char buf[256];
+
+ (*targetm.asm_out.internal_label) (file, "LCL", rs6000_pic_labelno);
+
+ fprintf (file, "\t.quad .TOC.-");
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ assemble_name (file, buf);
+ putc ('\n', file);
+ }
+
if (DEFAULT_ABI == ABI_AIX)
{
const char *desc_name, *orig_name;
$as_echo "#define HAVE_AS_TLS_MARKERS 1" >>confdefs.h
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for prologue entry point marker support" >&5
+$as_echo_n "checking assembler for prologue entry point marker support... " >&6; }
+if test "${gcc_cv_as_powerpc_entry_markers+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_entry_markers=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 26 \) \* 1000 + 0`
+ then gcc_cv_as_powerpc_entry_markers=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo ' .reloc .,R_PPC64_ENTRY; nop' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a64 --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_powerpc_entry_markers=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_powerpc_entry_markers" >&5
+$as_echo "$gcc_cv_as_powerpc_entry_markers" >&6; }
+if test $gcc_cv_as_powerpc_entry_markers = yes; then
+
+$as_echo "#define HAVE_AS_ENTRY_MARKERS 1" >>confdefs.h
+
fi
case $target in