OSDN Git Service

2005-10-21 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / targhooks.c
index 5d2a75f..c0c4201 100644 (file)
@@ -1,5 +1,5 @@
 /* Default target hook functions.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -15,8 +15,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* The migration of target macros to target hooks works as follows:
 
@@ -61,6 +61,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "tm_p.h"
 #include "target-def.h"
+#include "ggc.h"
+
 
 void
 default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
@@ -128,6 +130,20 @@ default_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
          != default_setup_incoming_varargs);
 }
 
+enum machine_mode
+default_eh_return_filter_mode (void)
+{
+  return word_mode;
+}
+
+/* The default implementation of TARGET_SHIFT_TRUNCATION_MASK.  */
+
+unsigned HOST_WIDE_INT
+default_shift_truncation_mask (enum machine_mode mode)
+{
+  return SHIFT_COUNT_TRUNCATED ? GET_MODE_BITSIZE (mode) - 1 : 0;
+}
+
 /* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true.  */
 
 bool
@@ -143,3 +159,284 @@ default_cxx_guard_type (void)
 {
   return long_long_integer_type_node;
 }
+
+
+/* Returns the size of the cookie to use when allocating an array
+   whose elements have the indicated TYPE.  Assumes that it is already
+   known that a cookie is needed.  */
+
+tree
+default_cxx_get_cookie_size (tree type)
+{
+  tree cookie_size;
+
+  /* We need to allocate an additional max (sizeof (size_t), alignof
+     (true_type)) bytes.  */
+  tree sizetype_size;
+  tree type_align;
+
+  sizetype_size = size_in_bytes (sizetype);
+  type_align = size_int (TYPE_ALIGN_UNIT (type));
+  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+    cookie_size = sizetype_size;
+  else
+    cookie_size = type_align;
+
+  return cookie_size;
+}
+
+/* Return true if a parameter must be passed by reference.  This version
+   of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
+
+bool
+hook_pass_by_reference_must_pass_in_stack (CUMULATIVE_ARGS *c ATTRIBUTE_UNUSED,
+       enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED,
+       bool named_arg ATTRIBUTE_UNUSED)
+{
+  return targetm.calls.must_pass_in_stack (mode, type);
+}
+
+/* Return true if a parameter follows callee copies conventions.  This
+   version of the hook is true for all named arguments.  */
+
+bool
+hook_callee_copies_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         tree type ATTRIBUTE_UNUSED, bool named)
+{
+  return named;
+}
+
+/* Emit any directives required to unwind this instruction.  */
+
+void
+default_unwind_emit (FILE * stream ATTRIBUTE_UNUSED,
+                    rtx insn ATTRIBUTE_UNUSED)
+{
+  /* Should never happen.  */
+  gcc_unreachable ();
+}
+
+/* True if MODE is valid for the target.  By "valid", we mean able to
+   be manipulated in non-trivial ways.  In particular, this means all
+   the arithmetic is supported.
+
+   By default we guess this means that any C type is supported.  If
+   we can't map the mode back to a type that would be available in C,
+   then reject it.  Special case, here, is the double-word arithmetic
+   supported by optabs.c.  */
+
+bool
+default_scalar_mode_supported_p (enum machine_mode mode)
+{
+  int precision = GET_MODE_PRECISION (mode);
+
+  switch (GET_MODE_CLASS (mode))
+    {
+    case MODE_PARTIAL_INT:
+    case MODE_INT:
+      if (precision == CHAR_TYPE_SIZE)
+       return true;
+      if (precision == SHORT_TYPE_SIZE)
+       return true;
+      if (precision == INT_TYPE_SIZE)
+       return true;
+      if (precision == LONG_TYPE_SIZE)
+       return true;
+      if (precision == LONG_LONG_TYPE_SIZE)
+       return true;
+      if (precision == 2 * BITS_PER_WORD)
+       return true;
+      return false;
+
+    case MODE_FLOAT:
+      if (precision == FLOAT_TYPE_SIZE)
+       return true;
+      if (precision == DOUBLE_TYPE_SIZE)
+       return true;
+      if (precision == LONG_DOUBLE_TYPE_SIZE)
+       return true;
+      return false;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns
+   an error message.
+  
+   This function checks whether a given INSN is valid within a low-overhead
+   loop.  If INSN is invalid it returns the reason for that, otherwise it
+   returns NULL. A called function may clobber any special registers required
+   for low-overhead looping. Additionally, some targets (eg, PPC) use the count
+   register for branch on table instructions. We reject the doloop pattern in
+   these cases.  */
+
+const char *
+default_invalid_within_doloop (rtx insn)
+{
+  if (CALL_P (insn))
+    return "Function call in loop.";
+  
+  if (JUMP_P (insn)
+      && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+         || GET_CODE (PATTERN (insn)) == ADDR_VEC))
+    return "Computed branch in the loop.";
+  
+  return NULL;
+}
+
+bool
+hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
+       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       enum machine_mode mode ATTRIBUTE_UNUSED,
+       tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+bool
+hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
+       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       enum machine_mode mode ATTRIBUTE_UNUSED,
+       tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+int
+hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
+       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       enum machine_mode mode ATTRIBUTE_UNUSED,
+       tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+const char *
+hook_invalid_arg_for_unprototyped_fn (
+       tree typelist ATTRIBUTE_UNUSED,
+       tree funcdecl ATTRIBUTE_UNUSED,
+       tree val ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
+/* Initialize the stack protection decls.  */
+
+/* Stack protection related decls living in libgcc.  */
+static GTY(()) tree stack_chk_guard_decl;
+
+tree
+default_stack_protect_guard (void)
+{
+  tree t = stack_chk_guard_decl;
+
+  if (t == NULL)
+    {
+      t = build_decl (VAR_DECL, get_identifier ("__stack_chk_guard"),
+                     ptr_type_node);
+      TREE_STATIC (t) = 1;
+      TREE_PUBLIC (t) = 1;
+      DECL_EXTERNAL (t) = 1;
+      TREE_USED (t) = 1;
+      TREE_THIS_VOLATILE (t) = 1;
+      DECL_ARTIFICIAL (t) = 1;
+      DECL_IGNORED_P (t) = 1;
+
+      stack_chk_guard_decl = t;
+    }
+
+  return t;
+}
+
+static GTY(()) tree stack_chk_fail_decl;
+
+tree 
+default_external_stack_protect_fail (void)
+{
+  tree t = stack_chk_fail_decl;
+
+  if (t == NULL_TREE)
+    {
+      t = build_function_type_list (void_type_node, NULL_TREE);
+      t = build_decl (FUNCTION_DECL, get_identifier ("__stack_chk_fail"), t);
+      TREE_STATIC (t) = 1;
+      TREE_PUBLIC (t) = 1;
+      DECL_EXTERNAL (t) = 1;
+      TREE_USED (t) = 1;
+      TREE_THIS_VOLATILE (t) = 1;
+      TREE_NOTHROW (t) = 1;
+      DECL_ARTIFICIAL (t) = 1;
+      DECL_IGNORED_P (t) = 1;
+
+      stack_chk_fail_decl = t;
+    }
+
+  return build_function_call_expr (t, NULL_TREE);
+}
+
+tree
+default_hidden_stack_protect_fail (void)
+{
+#ifndef HAVE_GAS_HIDDEN
+  return default_external_stack_protect_fail ();
+#else
+  tree t = stack_chk_fail_decl;
+
+  if (!flag_pic)
+    return default_external_stack_protect_fail ();
+
+  if (t == NULL_TREE)
+    {
+      t = build_function_type_list (void_type_node, NULL_TREE);
+      t = build_decl (FUNCTION_DECL,
+                     get_identifier ("__stack_chk_fail_local"), t);
+      TREE_STATIC (t) = 1;
+      TREE_PUBLIC (t) = 1;
+      DECL_EXTERNAL (t) = 1;
+      TREE_USED (t) = 1;
+      TREE_THIS_VOLATILE (t) = 1;
+      TREE_NOTHROW (t) = 1;
+      DECL_ARTIFICIAL (t) = 1;
+      DECL_IGNORED_P (t) = 1;
+      DECL_VISIBILITY_SPECIFIED (t) = 1;
+      DECL_VISIBILITY (t) = VISIBILITY_HIDDEN;
+
+      stack_chk_fail_decl = t;
+    }
+
+  return build_function_call_expr (t, NULL_TREE);
+#endif
+}
+
+bool
+hook_bool_rtx_commutative_p (rtx x, int outer_code ATTRIBUTE_UNUSED)
+{
+  return COMMUTATIVE_P (x);
+}
+
+rtx
+default_function_value (tree ret_type ATTRIBUTE_UNUSED,
+                       tree fn_decl_or_type,
+                       bool outgoing ATTRIBUTE_UNUSED)
+{
+  /* The old interface doesn't handle receiving the function type.  */
+  if (fn_decl_or_type
+      && !DECL_P (fn_decl_or_type))
+    fn_decl_or_type = NULL;
+
+#ifdef FUNCTION_OUTGOING_VALUE
+  if (outgoing)
+    return FUNCTION_OUTGOING_VALUE (ret_type, fn_decl_or_type);
+#endif
+
+#ifdef FUNCTION_VALUE
+  return FUNCTION_VALUE (ret_type, fn_decl_or_type);
+#else
+  return NULL_RTX;
+#endif
+}
+
+#include "gt-targhooks.h"