OSDN Git Service

* arm.c (arm_function_ok_for_sibcall): New function.
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Aug 2000 15:14:06 +0000 (15:14 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Aug 2000 15:14:06 +0000 (15:14 +0000)
* arm.h (FUNCTION_OK_FOR_SIBCALL): Define.
* arm.md (call expanders): Don't check here for calls that can't
be sibling calls.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35708 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md

index 8192bbe..71c99bc 100644 (file)
@@ -1,5 +1,12 @@
 2000-08-15  Richard Earnshaw <rearnsha@arm.com>
 
+       * arm.c (arm_function_ok_for_sibcall): New function.
+       * arm.h (FUNCTION_OK_FOR_SIBCALL): Define.
+       * arm.md (call expanders): Don't check here for calls that can't
+       be sibling calls.
+
+2000-08-15  Richard Earnshaw <rearnsha@arm.com>
+
        * arm.md (splits generating cond_exec): Disable.
 
 2000-08-15  Richard Earnshaw <rearnsha@arm.com>
index e905dae..d559d00 100644 (file)
@@ -1830,6 +1830,41 @@ arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
     || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
     || TARGET_LONG_CALLS;
 }
+
+/* Return non-zero if it is ok to make a tail-call to DECL.  */
+int
+arm_function_ok_for_sibcall (decl)
+     tree decl;
+{
+  int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL;
+
+  /* Never tailcall something for which we have no decl, or if we
+     are in Thumb mode.  */
+  if (decl == NULL || TARGET_THUMB)
+    return 0;
+
+  /* Get the calling method.  */
+  if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+    call_type = CALL_SHORT;
+  else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+    call_type = CALL_LONG;
+
+  /* Cannot tail-call to long calls, since these are out of range of
+     a branch instruction.  However, if not compiling PIC, we know
+     we can reach the symbol if it is in this compilation unit.  */
+  if (call_type == CALL_LONG && (flag_pic || ! TREE_ASM_WRITTEN (decl)))
+    return 0;
+
+  /* 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))
+    return 0;
+
+  /* Everything else is ok.  */
+  return 1;
+}
+
 \f
 int
 legitimate_pic_operand_p (x)
index 04702f1..b94e8b4 100644 (file)
@@ -1450,6 +1450,13 @@ typedef struct
 #define FUNCTION_ARG_REGNO_P(REGNO)  \
   ((REGNO) >= 0 && (REGNO) <= 3)
 
+\f
+/* Tail calling.  */
+
+/* A C expression that evaluates to true if it is ok to perform a sibling
+   call to DECL.  */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) arm_function_ok_for_sibcall ((DECL))
+
 /* Perform any actions needed for a function that is receiving a variable
    number of arguments.  CUM is as above.  MODE and TYPE are the mode and type
    of the current parameter.  PRETEND_SIZE is a variable that should be set to
index 46bf515..379b308 100644 (file)
   {
     if (operands[2] == NULL_RTX)
       operands[2] = const0_rtx;
-
-    /* If we need to emit a long-call, we can't do it as a sibling call,
-       so fail over to a normal call.  */
-    if (arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
-      {
-       emit_call_insn (gen_call (operands[0], operands[1], operands[2]));
-       DONE;
-      }
   }"
 )
 
   {
     if (operands[3] == NULL_RTX)
       operands[3] = const0_rtx;
-
-    /* If we need to emit a long-call, we can't do it as a sibling call,
-       so fail over to a normal call.  */
-    if (arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
-      {
-       emit_call_insn (gen_call_value (operands[0], operands[1], operands[2],
-                                       operands[3]));
-       DONE;
-      }
   }"
 )