This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch ARM] PR target/19599 Enable sibcalls through function pointers.
- From: Ramana Radhakrishnan <ramana dot r at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Earnshaw <richard dot earnshaw at arm dot com>
- Date: Thu, 4 Jun 2009 12:44:04 +0100
- Subject: [Patch ARM] PR target/19599 Enable sibcalls through function pointers.
Hi,
This patch allows sibling calls through function pointers on the ARM
port. Testing currently on a qemu cross to cortex-a8 on arm-none-eabi
cross.
The one case (as Richard pointed out this morning ) not considered
with this patch is that it doesn't consider the corner case of users
trying to use -fcaller-save and -fcallee-save from the command line
but the caller-save callee-save bits of the ABI for this are quite
hard-coded in the ARM backend that one will have to rewrite quite a
few bits in the backend to get those options supported properly.
Ok to commit if no regressions ?
cheers
Ramana
2009-06-02 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
PR target/19599
* config/arm/predicates.md (call_insn_operand): New predicate.
* config/arm/constraints.md ("Cs"): New register constraint.
("Ss"): New constraint for symbol references.
* config/arm/arm.md (sibcall): Allow only memory indirects through
symbol refs or register operands for operands[0].
(sibcall_value): Likewise for operands[1].
(*sibcall_insn): Allow register indirect sibcalls.
(*sibcall_value): Allow register indirect sibcalls.
* config/arm/arm.h (enum reg_class): New reg class ARM_CALLER_SAVE_REGS.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
* config/arm/arm.c (arm_function_ok_for_sibcall): Remove check for
functions without decls. Handle fallout of NULL decls.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c (revision 148103)
+++ gcc/config/arm/arm.c (working copy)
@@ -3545,7 +3545,7 @@ arm_function_ok_for_sibcall (tree decl,
/* Never tailcall something for which we have no decl, or if we
are in Thumb mode. */
- if (decl == NULL || TARGET_THUMB)
+ if (TARGET_THUMB)
return false;
/* The PIC register is live on entry to VxWorks PLT entries, so we
@@ -3555,13 +3555,15 @@ arm_function_ok_for_sibcall (tree decl,
/* Cannot tail-call to long calls, since these are out of range of
a branch instruction. */
- if (arm_is_long_call_p (decl))
+ if ((decl != NULL)
+ && arm_is_long_call_p (decl))
return false;
/* If we are interworking and the function is not declared static
then we can't tail-call it unless we know that it exists in this
compilation unit (since it might be a Thumb routine). */
- if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
+ if (TARGET_INTERWORK && (decl != NULL) && TREE_PUBLIC (decl) &&
+ !TREE_ASM_WRITTEN (decl))
return false;
func_type = arm_current_func_type ();
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h (revision 148103)
+++ gcc/config/arm/arm.h (working copy)
@@ -1133,6 +1133,7 @@ enum reg_class
STACK_REG,
BASE_REGS,
HI_REGS,
+ ARM_CALLER_SAVE_REGS,
CC_REG,
VFPCC_REG,
GENERAL_REGS,
@@ -1159,6 +1160,7 @@ enum reg_class
"STACK_REG", \
"BASE_REGS", \
"HI_REGS", \
+ "ARM_CALLER_SAVE_REGS", \
"CC_REG", \
"VFPCC_REG", \
"GENERAL_REGS", \
@@ -1184,6 +1186,7 @@ enum reg_class
{ 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
{ 0x0000DF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
+ { 0x0000100F, 0x00000000, 0x00000000, 0x00000000 }, /* ARM_CALLER_SAVE_REGS */ \
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
{ 0x0200DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md (revision 148103)
+++ gcc/config/arm/arm.md (working copy)
@@ -8424,13 +8424,17 @@ (define_insn "*call_value_insn"
;; We may also be able to do sibcalls for Thumb, but it's much harder...
(define_expand "sibcall"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
(return)
(use (match_operand 2 "" ""))])]
"TARGET_ARM"
"
{
+ if (!REG_P (XEXP (operands[0], 0))
+ && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
+ XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
+
if (operands[2] == NULL_RTX)
operands[2] = const0_rtx;
}"
@@ -8438,39 +8442,55 @@ (define_expand "sibcall"
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
(return)
(use (match_operand 3 "" ""))])]
"TARGET_ARM"
"
{
+ if (!REG_P (XEXP (operands[1], 0)) &&
+ (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF))
+ XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
+
if (operands[3] == NULL_RTX)
operands[3] = const0_rtx;
}"
)
(define_insn "*sibcall_insn"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs,Ss"))
(match_operand 1 "" ""))
(return)
(use (match_operand 2 "" ""))]
- "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
+ "TARGET_ARM"
"*
- return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
+ if (which_alternative == 1)
+ return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
+ else
+ if (arm_arch5 || arm_arch4t)
+ return \" bx\\t%0\\t%@ indirect register sibling call\";
+ else
+ return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
"
[(set_attr "type" "call")]
)
(define_insn "*sibcall_value_insn"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "" "X"))
+ [(set (match_operand 0 "s_register_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,Ss"))
(match_operand 2 "" "")))
(return)
(use (match_operand 3 "" ""))]
- "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
+ "TARGET_ARM"
"*
- return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
+ if (which_alternative == 1)
+ return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
+ else
+ if (arm_arch5 || arm_arch4t)
+ return \"bx\\t%1\";
+ else
+ return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
"
[(set_attr "type" "call")]
)
Index: gcc/config/arm/constraints.md
===================================================================
--- gcc/config/arm/constraints.md (revision 148103)
+++ gcc/config/arm/constraints.md (working copy)
@@ -75,6 +75,9 @@ (define_register_constraint "b" "TARGET_
(define_register_constraint "c" "CC_REG"
"@internal The condition code register.")
+(define_register_constraint "Cs" "ARM_CALLER_SAVE_REGS"
+ "@internal The caller save registers. Useful for sibcalls.")
+
(define_constraint "I"
"In ARM/Thumb-2 state a constant that can be used as an immediate value in a
Data Processing instruction. In Thumb-1 state a constant in the range
@@ -247,9 +250,16 @@ (define_memory_constraint "Q"
(and (match_code "mem")
(match_test "REG_P (XEXP (op, 0))")))
-;; We used to have constraint letters for S and R in ARM state, but
+;; We used to have constraint letters for R in ARM state, but
;; all uses of these now appear to have been removed.
;; Additionally, we used to have a Q constraint in Thumb state, but
;; this wasn't really a valid memory constraint. Again, all uses of
;; this now seem to have been removed.
+
+(define_constraint "Ss"
+ "@internal
+ In ARM state S is a symbol reference."
+ (match_code "symbol_ref")
+)
+
\ No newline at end of file
Index: gcc/config/arm/predicates.md
===================================================================
--- gcc/config/arm/predicates.md (revision 148103)
+++ gcc/config/arm/predicates.md (working copy)
@@ -517,3 +517,6 @@ (define_predicate "neon_lane_number"
(and (match_code "const_int")
(match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+(define_predicate "call_insn_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "s_register_operand")))