OSDN Git Service

2010-08-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / targhooks.c
index 1dd6c7c..f8cb522 100644 (file)
@@ -1,5 +1,5 @@
 /* Default target hook functions.
-   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "expr.h"
 #include "output.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "function.h"
 #include "target.h"
@@ -68,6 +69,22 @@ along with GCC; see the file COPYING3.  If not see
 #include "recog.h"
 
 
+bool
+default_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+                             rtx addr ATTRIBUTE_UNUSED,
+                             bool strict ATTRIBUTE_UNUSED)
+{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+  /* Defer to the old implementation using a goto.  */
+  if (strict)
+    return strict_memory_address_p (mode, addr);
+  else
+    return memory_address_p (mode, addr);
+#else
+  gcc_unreachable ();
+#endif
+}
+
 void
 default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
 {
@@ -97,6 +114,29 @@ default_unspec_may_trap_p (const_rtx x, unsigned flags)
 }
 
 enum machine_mode
+default_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                              enum machine_mode mode,
+                              int *punsignedp ATTRIBUTE_UNUSED,
+                              const_tree funtype ATTRIBUTE_UNUSED,
+                              int for_return ATTRIBUTE_UNUSED)
+{
+  if (for_return == 2)
+    return promote_mode (type, mode, punsignedp);
+  return mode;
+}
+
+enum machine_mode
+default_promote_function_mode_always_promote (const_tree type,
+                                             enum machine_mode mode,
+                                             int *punsignedp,
+                                             const_tree funtype ATTRIBUTE_UNUSED,
+                                             int for_return ATTRIBUTE_UNUSED)
+{
+  return promote_mode (type, mode, punsignedp);
+}
+
+
+enum machine_mode
 default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
 {
   if (m1 == m2)
@@ -276,14 +316,59 @@ hook_callee_copies_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
   return named;
 }
 
-/* Emit any directives required to unwind this instruction.  */
+/* Emit to STREAM the assembler syntax for insn operand X.  */
+
+void
+default_print_operand (FILE *stream ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
+                      int code ATTRIBUTE_UNUSED)
+{
+#ifdef PRINT_OPERAND
+  PRINT_OPERAND (stream, x, code);
+#else
+  gcc_unreachable ();
+#endif
+}
+
+/* Emit to STREAM the assembler syntax for an insn operand whose memory
+   address is X.  */
 
 void
-default_unwind_emit (FILE * stream ATTRIBUTE_UNUSED,
-                    rtx insn ATTRIBUTE_UNUSED)
+default_print_operand_address (FILE *stream ATTRIBUTE_UNUSED,
+                              rtx x ATTRIBUTE_UNUSED)
 {
-  /* Should never happen.  */
+#ifdef PRINT_OPERAND_ADDRESS
+  PRINT_OPERAND_ADDRESS (stream, x);
+#else
   gcc_unreachable ();
+#endif
+}
+
+/* Return true if CODE is a valid punctuation character for the
+   `print_operand' hook.  */
+
+bool
+default_print_operand_punct_valid_p (unsigned char code ATTRIBUTE_UNUSED)
+{
+#ifdef PRINT_OPERAND_PUNCT_VALID_P
+  return PRINT_OPERAND_PUNCT_VALID_P (code);
+#else
+  return false;
+#endif
+}
+
+/* The default implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA.  */
+
+bool
+default_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED,
+                                    rtx x ATTRIBUTE_UNUSED)
+{
+#ifdef OUTPUT_ADDR_CONST_EXTRA
+  OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
+  return true;
+
+fail:
+#endif
+  return false;
 }
 
 /* True if MODE is valid for the target.  By "valid", we mean able to
@@ -357,7 +442,7 @@ default_fixed_point_supported_p (void)
 
 /* 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
@@ -370,19 +455,17 @@ default_invalid_within_doloop (const_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))
+
+  if (JUMP_TABLE_DATA_P (insn))
     return "Computed branch in the loop.";
-  
+
   return NULL;
 }
 
 /* Mapping of builtin functions to vectorized variants.  */
 
 tree
-default_builtin_vectorized_function (enum built_in_function fn ATTRIBUTE_UNUSED,
+default_builtin_vectorized_function (tree fndecl ATTRIBUTE_UNUSED,
                                     tree type_out ATTRIBUTE_UNUSED,
                                     tree type_in ATTRIBUTE_UNUSED)
 {
@@ -392,16 +475,50 @@ default_builtin_vectorized_function (enum built_in_function fn ATTRIBUTE_UNUSED,
 /* Vectorized conversion.  */
 
 tree
-default_builtin_vectorized_conversion (enum tree_code code ATTRIBUTE_UNUSED,
-                                      tree type ATTRIBUTE_UNUSED)
+default_builtin_vectorized_conversion (unsigned int code ATTRIBUTE_UNUSED,
+                                      tree dest_type ATTRIBUTE_UNUSED,
+                                      tree src_type ATTRIBUTE_UNUSED)
 {
   return NULL_TREE;
 }
 
+/* Default vectorizer cost model values.  */
+
+int
+default_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
+                                    tree vectype ATTRIBUTE_UNUSED,
+                                    int misalign ATTRIBUTE_UNUSED)
+{
+  switch (type_of_cost)
+    {
+      case scalar_stmt:
+      case scalar_load:
+      case scalar_store:
+      case vector_stmt:
+      case vector_load:
+      case vector_store:
+      case vec_to_scalar:
+      case scalar_to_vec:
+      case cond_branch_not_taken:
+      case vec_perm:
+        return 1;
+
+      case unaligned_load:
+      case unaligned_store:
+        return 2;
+
+      case cond_branch_taken:
+        return 3;
+
+      default:
+        gcc_unreachable ();
+    }
+}
+
 /* Reciprocal.  */
 
 tree
-default_builtin_reciprocal (enum built_in_function fn ATTRIBUTE_UNUSED,
+default_builtin_reciprocal (unsigned int fn ATTRIBUTE_UNUSED,
                            bool md_fn ATTRIBUTE_UNUSED,
                            bool sqrt ATTRIBUTE_UNUSED)
 {
@@ -435,7 +552,48 @@ hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
   return 0;
 }
 
-void 
+void
+default_function_arg_advance (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                             enum machine_mode mode ATTRIBUTE_UNUSED,
+                             const_tree type ATTRIBUTE_UNUSED,
+                             bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_ARG_ADVANCE
+  CUMULATIVE_ARGS args = *ca;
+  FUNCTION_ARG_ADVANCE (args, mode, CONST_CAST_TREE (type), named);
+  *ca = args;
+#else
+  gcc_unreachable ();
+#endif
+}
+
+rtx
+default_function_arg (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                     enum machine_mode mode ATTRIBUTE_UNUSED,
+                     const_tree type ATTRIBUTE_UNUSED,
+                     bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_ARG
+  return FUNCTION_ARG (*ca, mode, CONST_CAST_TREE (type), named);
+#else
+  gcc_unreachable ();
+#endif
+}
+
+rtx
+default_function_incoming_arg (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                              enum machine_mode mode ATTRIBUTE_UNUSED,
+                              const_tree type ATTRIBUTE_UNUSED,
+                              bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_INCOMING_ARG
+  return FUNCTION_INCOMING_ARG (*ca, mode, CONST_CAST_TREE (type), named);
+#else
+  gcc_unreachable ();
+#endif
+}
+
+void
 hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
 {
 }
@@ -461,7 +619,10 @@ default_stack_protect_guard (void)
 
   if (t == NULL)
     {
-      t = build_decl (VAR_DECL, get_identifier ("__stack_chk_guard"),
+      rtx x;
+
+      t = build_decl (UNKNOWN_LOCATION,
+                     VAR_DECL, get_identifier ("__stack_chk_guard"),
                      ptr_type_node);
       TREE_STATIC (t) = 1;
       TREE_PUBLIC (t) = 1;
@@ -471,6 +632,11 @@ default_stack_protect_guard (void)
       DECL_ARTIFICIAL (t) = 1;
       DECL_IGNORED_P (t) = 1;
 
+      /* Do not share RTL as the declaration is visible outside of
+        current function.  */
+      x = DECL_RTL (t);
+      RTX_FLAG (x, used) = 1;
+
       stack_chk_guard_decl = t;
     }
 
@@ -479,7 +645,7 @@ default_stack_protect_guard (void)
 
 static GTY(()) tree stack_chk_fail_decl;
 
-tree 
+tree
 default_external_stack_protect_fail (void)
 {
   tree t = stack_chk_fail_decl;
@@ -487,7 +653,8 @@ default_external_stack_protect_fail (void)
   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);
+      t = build_decl (UNKNOWN_LOCATION,
+                     FUNCTION_DECL, get_identifier ("__stack_chk_fail"), t);
       TREE_STATIC (t) = 1;
       TREE_PUBLIC (t) = 1;
       DECL_EXTERNAL (t) = 1;
@@ -519,7 +686,7 @@ default_hidden_stack_protect_fail (void)
   if (t == NULL_TREE)
     {
       t = build_function_type_list (void_type_node, NULL_TREE);
-      t = build_decl (FUNCTION_DECL,
+      t = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
                      get_identifier ("__stack_chk_fail_local"), t);
       TREE_STATIC (t) = 1;
       TREE_PUBLIC (t) = 1;
@@ -556,15 +723,33 @@ default_function_value (const_tree ret_type ATTRIBUTE_UNUSED,
       && !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;
+  gcc_unreachable ();
+#endif
+}
+
+rtx
+default_libcall_value (enum machine_mode mode ATTRIBUTE_UNUSED,
+                      const_rtx fun ATTRIBUTE_UNUSED)
+{
+#ifdef LIBCALL_VALUE
+  return LIBCALL_VALUE (mode);
+#else
+  gcc_unreachable ();
+#endif
+}
+
+/* The default hook for TARGET_FUNCTION_VALUE_REGNO_P.  */
+
+bool
+default_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_VALUE_REGNO_P
+  return FUNCTION_VALUE_REGNO_P (regno);
+#else
+  gcc_unreachable ();
 #endif
 }
 
@@ -583,28 +768,75 @@ default_internal_arg_pointer (void)
     return virtual_incoming_args_rtx;
 }
 
-enum reg_class
+rtx
+default_static_chain (const_tree fndecl, bool incoming_p)
+{
+  if (!DECL_STATIC_CHAIN (fndecl))
+    return NULL;
+
+  if (incoming_p)
+    {
+#ifdef STATIC_CHAIN_INCOMING_REGNUM
+      return gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
+#endif
+    }
+
+#ifdef STATIC_CHAIN_REGNUM
+  return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+#endif
+
+  {
+    static bool issued_error;
+    if (!issued_error)
+      {
+       issued_error = true;
+       sorry ("nested functions not supported on this target");
+      }
+
+    /* It really doesn't matter what we return here, so long at it
+       doesn't cause the rest of the compiler to crash.  */
+    return gen_rtx_MEM (Pmode, stack_pointer_rtx);
+  }
+}
+
+void
+default_trampoline_init (rtx ARG_UNUSED (m_tramp), tree ARG_UNUSED (t_func),
+                        rtx ARG_UNUSED (r_chain))
+{
+  sorry ("nested function trampolines not supported on this target");
+}
+
+int
+default_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                         tree funtype ATTRIBUTE_UNUSED,
+                         int size ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+reg_class_t
 default_branch_target_register_class (void)
 {
   return NO_REGS;
 }
 
 #ifdef IRA_COVER_CLASSES
-const enum reg_class *
+const reg_class_t *
 default_ira_cover_classes (void)
 {
-  static enum reg_class classes[] = IRA_COVER_CLASSES;
+  static reg_class_t classes[] = IRA_COVER_CLASSES;
   return classes;
 }
 #endif
 
-enum reg_class
+reg_class_t
 default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
-                         enum reg_class reload_class ATTRIBUTE_UNUSED,
+                         reg_class_t reload_class_i ATTRIBUTE_UNUSED,
                          enum machine_mode reload_mode ATTRIBUTE_UNUSED,
                          secondary_reload_info *sri)
 {
   enum reg_class rclass = NO_REGS;
+  enum reg_class reload_class = (enum reg_class) reload_class_i;
 
   if (sri->prev_sri && sri->prev_sri->t_icode != CODE_FOR_nothing)
     {
@@ -621,8 +853,9 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
 #endif
   if (rclass != NO_REGS)
     {
-      enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
-                             : reload_out_optab[(int) reload_mode]);
+      enum insn_code icode
+       = direct_optab_handler (in_p ? reload_in_optab : reload_out_optab,
+                               reload_mode);
 
       if (icode != CODE_FOR_nothing
          && insn_data[(int) icode].operand[in_p].predicate
@@ -686,6 +919,14 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
   return rclass;
 }
 
+void
+default_target_option_override (void)
+{
+#ifdef OVERRIDE_OPTIONS
+  OVERRIDE_OPTIONS;
+#endif
+}
+
 bool
 default_handle_c_option (size_t code ATTRIBUTE_UNUSED,
                         const char *arg ATTRIBUTE_UNUSED,
@@ -726,12 +967,150 @@ default_builtin_vector_alignment_reachable (const_tree type, bool is_packed)
   return true;
 }
 
+/* By default, assume that a target supports any factor of misalignment
+   memory access if it supports movmisalign patten.
+   is_packed is true if the memory access is defined in a packed struct.  */
+bool
+default_builtin_support_vector_misalignment (enum machine_mode mode,
+                                            const_tree type
+                                            ATTRIBUTE_UNUSED,
+                                            int misalignment
+                                            ATTRIBUTE_UNUSED,
+                                            bool is_packed
+                                            ATTRIBUTE_UNUSED)
+{
+  if (optab_handler (movmisalign_optab, mode) != CODE_FOR_nothing)
+    return true;
+  return false;
+}
+
+/* Determine whether or not a pointer mode is valid. Assume defaults
+   of ptr_mode or Pmode - can be overridden.  */
+bool
+default_valid_pointer_mode (enum machine_mode mode)
+{
+  return (mode == ptr_mode || mode == Pmode);
+}
+
+/* Return the mode for a pointer to a given ADDRSPACE, defaulting to ptr_mode
+   for the generic address space only.  */
+
+enum machine_mode
+default_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_assert (ADDR_SPACE_GENERIC_P (addrspace));
+  return ptr_mode;
+}
+
+/* Return the mode for an address in a given ADDRSPACE, defaulting to Pmode
+   for the generic address space only.  */
+
+enum machine_mode
+default_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_assert (ADDR_SPACE_GENERIC_P (addrspace));
+  return Pmode;
+}
+
+/* Named address space version of valid_pointer_mode.  */
+
+bool
+default_addr_space_valid_pointer_mode (enum machine_mode mode, addr_space_t as)
+{
+  if (!ADDR_SPACE_GENERIC_P (as))
+    return (mode == targetm.addr_space.pointer_mode (as)
+           || mode == targetm.addr_space.address_mode (as));
+
+  return targetm.valid_pointer_mode (mode);
+}
+
+/* Some places still assume that all pointer or address modes are the
+   standard Pmode and ptr_mode.  These optimizations become invalid if
+   the target actually supports multiple different modes.  For now,
+   we disable such optimizations on such targets, using this function.  */
+
+bool
+target_default_pointer_address_modes_p (void)
+{
+  if (targetm.addr_space.address_mode != default_addr_space_address_mode)
+    return false;
+  if (targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+    return false;
+
+  return true;
+}
+
+/* Named address space version of legitimate_address_p.  */
+
+bool
+default_addr_space_legitimate_address_p (enum machine_mode mode, rtx mem,
+                                        bool strict, addr_space_t as)
+{
+  if (!ADDR_SPACE_GENERIC_P (as))
+    gcc_unreachable ();
+
+  return targetm.legitimate_address_p (mode, mem, strict);
+}
+
+/* Named address space version of LEGITIMIZE_ADDRESS.  */
+
+rtx
+default_addr_space_legitimize_address (rtx x, rtx oldx,
+                                      enum machine_mode mode, addr_space_t as)
+{
+  if (!ADDR_SPACE_GENERIC_P (as))
+    return x;
+
+  return targetm.legitimize_address (x, oldx, mode);
+}
+
+/* The default hook for determining if one named address space is a subset of
+   another and to return which address space to use as the common address
+   space.  */
+
+bool
+default_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
+{
+  return (subset == superset);
+}
+
+/* The default hook for TARGET_ADDR_SPACE_CONVERT. This hook should never be
+   called for targets with only a generic address space.  */
+
+rtx
+default_addr_space_convert (rtx op ATTRIBUTE_UNUSED,
+                           tree from_type ATTRIBUTE_UNUSED,
+                           tree to_type ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 bool
 default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
 {
   return true;
 }
 
+/* The default implementation of TARGET_MODE_DEPENDENT_ADDRESS_P.  */
+
+bool
+default_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED)
+{
+#ifdef GO_IF_MODE_DEPENDENT_ADDRESS
+
+  GO_IF_MODE_DEPENDENT_ADDRESS (CONST_CAST_RTX (addr), win);
+  return false;
+  /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS.  */
+ win: ATTRIBUTE_UNUSED_LABEL
+  return true;
+
+#else
+
+  return false;
+
+#endif
+}
+
 bool
 default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl),
                                         tree ARG_UNUSED (name),
@@ -755,7 +1134,7 @@ default_target_option_pragma_parse (tree ARG_UNUSED (args),
 }
 
 bool
-default_target_option_can_inline_p (tree caller, tree callee)
+default_target_can_inline_p (tree caller, tree callee)
 {
   bool ret = false;
   tree callee_opts = DECL_FUNCTION_SPECIFIC_TARGET (callee);
@@ -792,4 +1171,53 @@ unsigned int default_case_values_threshold (void)
   return (HAVE_casesi ? 4 : 5);
 }
 
+bool
+default_have_conditional_execution (void)
+{
+#ifdef HAVE_conditional_execution
+  return HAVE_conditional_execution;
+#else
+  return false;
+#endif
+}
+
+/* Compute cost of moving registers to/from memory.  */
+
+int
+default_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                         reg_class_t rclass ATTRIBUTE_UNUSED,
+                         bool in ATTRIBUTE_UNUSED)
+{
+#ifndef MEMORY_MOVE_COST
+    return (4 + memory_move_secondary_cost (mode, (enum reg_class) rclass, in));
+#else
+    return MEMORY_MOVE_COST (mode, (enum reg_class) rclass, in);
+#endif
+}
+
+/* Compute cost of moving data from a register of class FROM to one of
+   TO, using MODE.  */
+
+int
+default_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                            reg_class_t from ATTRIBUTE_UNUSED,
+                            reg_class_t to ATTRIBUTE_UNUSED)
+{
+#ifndef REGISTER_MOVE_COST
+  return 2;
+#else
+  return REGISTER_MOVE_COST (mode, (enum reg_class) from, (enum reg_class) to);
+#endif
+}
+
+bool
+default_profile_before_prologue (void)
+{
+#ifdef PROFILE_BEFORE_PROLOGUE
+  return true;
+#else
+  return false;
+#endif
+}
+
 #include "gt-targhooks.h"