From b12a00f173122aef3c77d763e75aeeb872ec4852 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Fri, 14 Jan 2005 13:58:40 +0000 Subject: [PATCH] re PR target/7525 ([ARM/Thumb] long calls stubs only in one code section, cannot branch to them from other section) PR target/7525 * arm.h (struct machine_function): Add call_via field. (thumb_call_via_label): Declare. * arm.c (thumb_call_via_label): New variable. (thumb_call_reg_needed): New variable. (arm_output_function_epilogue): For Thumb code, output any per-function call-indirect trampolines. (thumb_call_via_reg): New function. (arm_file_end): New function. (TARGET_ASM_FILE_END): Call arm_file_end. (aof_file_end): Likewise. * arm-protos.h (thumb_call_via_reg): Declare. * arm.md (call_reg_thumb, call_value_reg_thumb): Call thumb_call_via_reg in normal case. From-SVN: r93641 --- gcc/ChangeLog | 17 ++++++++ gcc/config/arm/arm-protos.h | 3 +- gcc/config/arm/arm.c | 86 ++++++++++++++++++++++++++++++++++++- gcc/config/arm/arm.h | 9 +++- gcc/config/arm/arm.md | 6 +-- 5 files changed, 115 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 91796254cdc..7233c29222b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2005-01-14 Richard Earnshaw + + PR target/7525 + * arm.h (struct machine_function): Add call_via field. + (thumb_call_via_label): Declare. + * arm.c (thumb_call_via_label): New variable. + (thumb_call_reg_needed): New variable. + (arm_output_function_epilogue): For Thumb code, output any per-function + call-indirect trampolines. + (thumb_call_via_reg): New function. + (arm_file_end): New function. + (TARGET_ASM_FILE_END): Call arm_file_end. + (aof_file_end): Likewise. + * arm-protos.h (thumb_call_via_reg): Declare. + * arm.md (call_reg_thumb, call_value_reg_thumb): Call + thumb_call_via_reg in normal case. + 2005-01-14 Jakub Jelinek PR middle-end/19084 diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index c46ce8273db..99c79231d78 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -1,5 +1,5 @@ /* Prototypes for exported functions defined in arm.c and pe.c - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rearnsha@arm.com) Minor hacks by Nick Clifton (nickc@cygnus.com) @@ -150,6 +150,7 @@ extern int thumb_shiftable_const (unsigned HOST_WIDE_INT); extern void thumb_final_prescan_insn (rtx); extern const char *thumb_load_double_from_address (rtx *); extern const char *thumb_output_move_mem_multiple (int, rtx *); +extern const char *thumb_call_via_reg (rtx); extern void thumb_expand_movmemqi (rtx *); extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx); extern int thumb_go_if_legitimate_address (enum machine_mode, rtx); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 65820219394..649fde30299 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1,6 +1,6 @@ /* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com). @@ -153,6 +153,9 @@ static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, #ifndef ARM_PE static void arm_encode_section_info (tree, rtx, int); #endif + +static void arm_file_end (void); + #ifdef AOF_ASSEMBLER static void aof_globalize_label (FILE *, const char *); static void aof_dump_imports (FILE *); @@ -188,6 +191,9 @@ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode); #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE arm_attribute_table +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END arm_file_end + #ifdef AOF_ASSEMBLER #undef TARGET_ASM_BYTE_OP #define TARGET_ASM_BYTE_OP "\tDCB\t" @@ -366,6 +372,10 @@ const char * target_abi_name = NULL; const char * structure_size_string = NULL; int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY; +/* Used for Thumb call_via trampolines. */ +rtx thumb_call_via_label[13]; +static int thumb_call_reg_needed; + /* Bit values used to identify processor capabilities. */ #define FL_CO_PROC (1 << 0) /* Has external co-processor bus */ #define FL_ARCH3M (1 << 1) /* Extended multiply */ @@ -9600,6 +9610,23 @@ arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, if (TARGET_THUMB) { + int regno; + + /* Emit any call-via-reg trampolines that are needed for v4t support + of call_reg and call_value_reg type insns. */ + for (regno = 0; regno < SP_REGNUM; regno++) + { + rtx label = cfun->machine->call_via[regno]; + + if (label != NULL) + { + function_section (current_function_decl); + targetm.asm_out.internal_label (asm_out_file, "L", + CODE_LABEL_NUMBER (label)); + asm_fprintf (asm_out_file, "\tbx\t%r\n", regno); + } + } + /* ??? Probably not safe to set this here, since it assumes that a function will be emitted as assembly immediately after we generate RTL for it. This does not happen for inline functions. */ @@ -13652,6 +13679,37 @@ thumb_output_move_mem_multiple (int n, rtx *operands) return ""; } +/* Output a call-via instruction for thumb state. */ +const char * +thumb_call_via_reg (rtx reg) +{ + int regno = REGNO (reg); + rtx *labelp; + + gcc_assert (regno < SP_REGNUM); + + /* If we are in the normal text section we can use a single instance + per compilation unit. If we are doing function sections, then we need + an entry per section, since we can't rely on reachability. */ + if (in_text_section ()) + { + thumb_call_reg_needed = 1; + + if (thumb_call_via_label[regno] == NULL) + thumb_call_via_label[regno] = gen_label_rtx (); + labelp = thumb_call_via_label + regno; + } + else + { + if (cfun->machine->call_via[regno] == NULL) + cfun->machine->call_via[regno] = gen_label_rtx (); + labelp = cfun->machine->call_via + regno; + } + + output_asm_insn ("bl\t%a0", labelp); + return ""; +} + /* Routines for generating rtl. */ void thumb_expand_movmemqi (rtx *operands) @@ -13762,6 +13820,31 @@ arm_asm_output_labelref (FILE *stream, const char *name) asm_fprintf (stream, "%U%s", name); } +static void +arm_file_end (void) +{ + int regno; + + if (! thumb_call_reg_needed) + return; + + text_section (); + asm_fprintf (asm_out_file, "\t.code 16\n"); + ASM_OUTPUT_ALIGN (asm_out_file, 1); + + for (regno = 0; regno < SP_REGNUM; regno++) + { + rtx label = thumb_call_via_label[regno]; + + if (label != 0) + { + targetm.asm_out.internal_label (asm_out_file, "L", + CODE_LABEL_NUMBER (label)); + asm_fprintf (asm_out_file, "\tbx\t%r\n", regno); + } + } +} + rtx aof_pic_label; #ifdef AOF_ASSEMBLER @@ -13958,6 +14041,7 @@ aof_file_end (void) { if (flag_pic) aof_dump_pic_table (asm_out_file); + arm_file_end (); aof_dump_imports (asm_out_file); fputs ("\tEND\n", asm_out_file); } diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 2278731a5f9..9e84626acbd 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com) @@ -1703,9 +1703,16 @@ typedef struct machine_function GTY(()) /* Records if sibcalls are blocked because an argument register is needed to preserve stack alignment. */ int sibcall_blocked; + /* Labels for per-function Thumb call-via stubs. One per potential calling + register. We can never call via SP, LR or PC. */ + rtx call_via[13]; } machine_function; +/* As in the machine_function, a global set of call-via labels, for code + that is in text_section(). */ +extern GTY(()) rtx thumb_call_via_label[13]; + /* A C type for declaring a variable that is used as the first argument of `FUNCTION_ARG' and other related values. For some target machines, the type `int' suffices and can hold the number of bytes of argument so far. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 3255f059dda..7d8075ff795 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1,6 +1,6 @@ ;;- Machine description for ARM for GNU compiler ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003 2004 Free Software Foundation, Inc. +;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) ;; and Martin Simmons (@harleqn.co.uk). ;; More major hacks by Richard Earnshaw (rearnsha@arm.com). @@ -7436,7 +7436,7 @@ "* { if (!TARGET_CALLER_INTERWORKING) - return \"bl\\t%__call_via_%0\"; + return thumb_call_via_reg (operands[0]); else if (operands[1] == const0_rtx) return \"bl\\t%__interwork_call_via_%0\"; else if (frame_pointer_needed) @@ -7530,7 +7530,7 @@ "* { if (!TARGET_CALLER_INTERWORKING) - return \"bl\\t%__call_via_%1\"; + return thumb_call_via_reg (operands[1]); else if (operands[2] == const0_rtx) return \"bl\\t%__interwork_call_via_%1\"; else if (frame_pointer_needed) -- 2.30.2