targhooks.c revision 169690
159243Sobrien/* Default target hook functions.
259243Sobrien   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
359243Sobrien
459243SobrienThis file is part of GCC.
559243Sobrien
659243SobrienGCC is free software; you can redistribute it and/or modify it under
759243Sobrienthe terms of the GNU General Public License as published by the Free
859243SobrienSoftware Foundation; either version 2, or (at your option) any later
959243Sobrienversion.
1059243Sobrien
1159243SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
12100616SmpWARRANTY; without even the implied warranty of MERCHANTABILITY or
1359243SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1459243Sobrienfor more details.
1559243Sobrien
1659243SobrienYou should have received a copy of the GNU General Public License
1759243Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1859243SobrienSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
1959243Sobrien02110-1301, USA.  */
2059243Sobrien
2159243Sobrien/* The migration of target macros to target hooks works as follows:
2259243Sobrien
2359243Sobrien   1. Create a target hook that uses the existing target macros to
2459243Sobrien      implement the same functionality.
2559243Sobrien
2659243Sobrien   2. Convert all the MI files to use the hook instead of the macro.
2759243Sobrien
2859415Sobrien   3. Repeat for a majority of the remaining target macros.  This will
2959243Sobrien      take some time.
3059243Sobrien
3159243Sobrien   4. Tell target maintainers to start migrating.
3259243Sobrien
3359243Sobrien   5. Eventually convert the backends to override the hook instead of
3459243Sobrien      defining the macros.  This will take some time too.
3559243Sobrien
3659243Sobrien   6. TBD when, poison the macros.  Unmigrated targets will break at
3759415Sobrien      this point.
3859243Sobrien
3959415Sobrien   Note that we expect steps 1-3 to be done by the people that
4059243Sobrien   understand what the MI does with each macro, and step 5 to be done
4159243Sobrien   by the target maintainers for their respective targets.
4259243Sobrien
4359243Sobrien   Note that steps 1 and 2 don't have to be done together, but no
4459243Sobrien   target can override the new hook until step 2 is complete for it.
4559243Sobrien
4659243Sobrien   Once the macros are poisoned, we will revert to the old migration
4759243Sobrien   rules - migrate the macro, callers, and targets all at once.  This
4859415Sobrien   comment can thus be removed at that point.  */
4959243Sobrien
5059415Sobrien#include "config.h"
5159415Sobrien#include "system.h"
5259243Sobrien#include "coretypes.h"
5359243Sobrien#include "tm.h"
5459243Sobrien#include "machmode.h"
5559243Sobrien#include "rtl.h"
5659243Sobrien#include "tree.h"
5759243Sobrien#include "expr.h"
5859243Sobrien#include "output.h"
5959243Sobrien#include "toplev.h"
6059243Sobrien#include "function.h"
6159243Sobrien#include "target.h"
6259243Sobrien#include "tm_p.h"
6359243Sobrien#include "target-def.h"
6459243Sobrien#include "ggc.h"
6559243Sobrien#include "hard-reg-set.h"
6659243Sobrien#include "reload.h"
6759243Sobrien#include "optabs.h"
6859243Sobrien#include "recog.h"
6959243Sobrien
7059243Sobrien
7159415Sobrienvoid
7259243Sobriendefault_external_libcall (rtx fun ATTRIBUTE_UNUSED)
7359243Sobrien{
7459243Sobrien#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
75231990Smp  ASM_OUTPUT_EXTERNAL_LIBCALL(asm_out_file, fun);
7659243Sobrien#endif
7759243Sobrien}
7859243Sobrien
7959243Sobrienenum machine_mode
8059243Sobriendefault_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
8159243Sobrien{
8259243Sobrien  if (m1 == m2)
8359243Sobrien    return m1;
8459243Sobrien  return VOIDmode;
8559243Sobrien}
8659243Sobrien
8759243Sobrienbool
8859243Sobriendefault_return_in_memory (tree type,
8959243Sobrien			  tree fntype ATTRIBUTE_UNUSED)
9059243Sobrien{
9159243Sobrien#ifndef RETURN_IN_MEMORY
9259243Sobrien  return (TYPE_MODE (type) == BLKmode);
9359243Sobrien#else
9459415Sobrien  return RETURN_IN_MEMORY (type);
9559243Sobrien#endif
9659243Sobrien}
9759243Sobrien
9859243Sobrienrtx
9959243Sobriendefault_expand_builtin_saveregs (void)
10059243Sobrien{
10159243Sobrien  error ("__builtin_saveregs not supported by this target");
10259243Sobrien  return const0_rtx;
10359243Sobrien}
10459243Sobrien
10559243Sobrienvoid
10659243Sobriendefault_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
10759243Sobrien				enum machine_mode mode ATTRIBUTE_UNUSED,
10859243Sobrien				tree type ATTRIBUTE_UNUSED,
10959243Sobrien				int *pretend_arg_size ATTRIBUTE_UNUSED,
11059243Sobrien				int second_time ATTRIBUTE_UNUSED)
11159243Sobrien{
11259243Sobrien}
11359243Sobrien
11459243Sobrien/* The default implementation of TARGET_BUILTIN_SETJMP_FRAME_VALUE.  */
11559243Sobrien
11659243Sobrienrtx
11759243Sobriendefault_builtin_setjmp_frame_value (void)
11859243Sobrien{
11959243Sobrien  return virtual_stack_vars_rtx;
12059243Sobrien}
12159243Sobrien
12259243Sobrien/* Generic hook that takes a CUMULATIVE_ARGS pointer and returns false.  */
12359243Sobrien
12459243Sobrienbool
12559243Sobrienhook_bool_CUMULATIVE_ARGS_false (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
12659243Sobrien{
12759243Sobrien  return false;
12859243Sobrien}
12959243Sobrien
13059243Sobrienbool
13159243Sobriendefault_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
132167465Smp{
133167465Smp  return (targetm.calls.setup_incoming_varargs
13459243Sobrien	  != default_setup_incoming_varargs);
13559243Sobrien}
136167465Smp
13759243Sobrienenum machine_mode
13859243Sobriendefault_eh_return_filter_mode (void)
13959243Sobrien{
14059243Sobrien  return word_mode;
14159243Sobrien}
14259243Sobrien
14359243Sobrien/* The default implementation of TARGET_SHIFT_TRUNCATION_MASK.  */
14459415Sobrien
14559243Sobrienunsigned HOST_WIDE_INT
14659243Sobriendefault_shift_truncation_mask (enum machine_mode mode)
14759243Sobrien{
14859243Sobrien  return SHIFT_COUNT_TRUNCATED ? GET_MODE_BITSIZE (mode) - 1 : 0;
14959415Sobrien}
15059243Sobrien
15159243Sobrien/* The default implementation of TARGET_MIN_DIVISIONS_FOR_RECIP_MUL.  */
15259243Sobrien
15359243Sobrienunsigned int
15459243Sobriendefault_min_divisions_for_recip_mul (enum machine_mode mode ATTRIBUTE_UNUSED)
15559415Sobrien{
15659243Sobrien  return have_insn_for (DIV, mode) ? 3 : 2;
15759415Sobrien}
15859243Sobrien
15959243Sobrien/* The default implementation of TARGET_MODE_REP_EXTENDED.  */
16059243Sobrien
16159243Sobrienint
16259243Sobriendefault_mode_rep_extended (enum machine_mode mode ATTRIBUTE_UNUSED,
16359243Sobrien			   enum machine_mode mode_rep ATTRIBUTE_UNUSED)
16459243Sobrien{
16559243Sobrien  return UNKNOWN;
16659243Sobrien}
16759243Sobrien
16859243Sobrien/* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true.  */
16959243Sobrien
17059243Sobrienbool
17159243Sobrienhook_bool_CUMULATIVE_ARGS_true (CUMULATIVE_ARGS * a ATTRIBUTE_UNUSED)
17259243Sobrien{
17359243Sobrien  return true;
17459243Sobrien}
17559243Sobrien
17659243Sobrien
17759243Sobrien/* The generic C++ ABI specifies this is a 64-bit value.  */
17859243Sobrientree
179145479Smpdefault_cxx_guard_type (void)
180145479Smp{
181145479Smp  return long_long_integer_type_node;
182145479Smp}
183145479Smp
184145479Smp
185145479Smp/* Returns the size of the cookie to use when allocating an array
18659243Sobrien   whose elements have the indicated TYPE.  Assumes that it is already
18759243Sobrien   known that a cookie is needed.  */
18859243Sobrien
18959243Sobrientree
19059243Sobriendefault_cxx_get_cookie_size (tree type)
19159415Sobrien{
19259243Sobrien  tree cookie_size;
19359243Sobrien
19459415Sobrien  /* We need to allocate an additional max (sizeof (size_t), alignof
19559243Sobrien     (true_type)) bytes.  */
19659243Sobrien  tree sizetype_size;
19759243Sobrien  tree type_align;
19859243Sobrien
19959243Sobrien  sizetype_size = size_in_bytes (sizetype);
20059243Sobrien  type_align = size_int (TYPE_ALIGN_UNIT (type));
20159243Sobrien  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
20259243Sobrien    cookie_size = sizetype_size;
20359243Sobrien  else
20459243Sobrien    cookie_size = type_align;
20559243Sobrien
20659243Sobrien  return cookie_size;
20759243Sobrien}
20859243Sobrien
20959243Sobrien/* Return true if a parameter must be passed by reference.  This version
21059243Sobrien   of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
21159243Sobrien
21259243Sobrienbool
21359243Sobrienhook_pass_by_reference_must_pass_in_stack (CUMULATIVE_ARGS *c ATTRIBUTE_UNUSED,
21459243Sobrien	enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED,
21583098Smp	bool named_arg ATTRIBUTE_UNUSED)
21683098Smp{
21783098Smp  return targetm.calls.must_pass_in_stack (mode, type);
21859243Sobrien}
21959243Sobrien
22059243Sobrien/* Return true if a parameter follows callee copies conventions.  This
22159243Sobrien   version of the hook is true for all named arguments.  */
22259243Sobrien
22359243Sobrienbool
22459243Sobrienhook_callee_copies_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
22559243Sobrien			  enum machine_mode mode ATTRIBUTE_UNUSED,
22659243Sobrien			  tree type ATTRIBUTE_UNUSED, bool named)
22759243Sobrien{
22859243Sobrien  return named;
22959243Sobrien}
23059243Sobrien
23159243Sobrien/* Emit any directives required to unwind this instruction.  */
23259243Sobrien
23359243Sobrienvoid
23459243Sobriendefault_unwind_emit (FILE * stream ATTRIBUTE_UNUSED,
23559243Sobrien		     rtx insn ATTRIBUTE_UNUSED)
23659243Sobrien{
23759243Sobrien  /* Should never happen.  */
23859243Sobrien  gcc_unreachable ();
23959243Sobrien}
24059415Sobrien
24159243Sobrien/* True if MODE is valid for the target.  By "valid", we mean able to
24259243Sobrien   be manipulated in non-trivial ways.  In particular, this means all
24359243Sobrien   the arithmetic is supported.
24459243Sobrien
24559243Sobrien   By default we guess this means that any C type is supported.  If
24659243Sobrien   we can't map the mode back to a type that would be available in C,
24759243Sobrien   then reject it.  Special case, here, is the double-word arithmetic
24859415Sobrien   supported by optabs.c.  */
24959243Sobrien
25059243Sobrienbool
25159243Sobriendefault_scalar_mode_supported_p (enum machine_mode mode)
25259243Sobrien{
25359243Sobrien  int precision = GET_MODE_PRECISION (mode);
25459243Sobrien
25559243Sobrien  switch (GET_MODE_CLASS (mode))
25659243Sobrien    {
25759243Sobrien    case MODE_PARTIAL_INT:
25859243Sobrien    case MODE_INT:
25959243Sobrien      if (precision == CHAR_TYPE_SIZE)
26059243Sobrien	return true;
26159243Sobrien      if (precision == SHORT_TYPE_SIZE)
26259243Sobrien	return true;
26359243Sobrien      if (precision == INT_TYPE_SIZE)
26459243Sobrien	return true;
26559243Sobrien      if (precision == LONG_TYPE_SIZE)
26659243Sobrien	return true;
26759243Sobrien      if (precision == LONG_LONG_TYPE_SIZE)
26859243Sobrien	return true;
26959243Sobrien      if (precision == 2 * BITS_PER_WORD)
27059243Sobrien	return true;
27159243Sobrien      return false;
27259243Sobrien
27359243Sobrien    case MODE_FLOAT:
27459243Sobrien      if (precision == FLOAT_TYPE_SIZE)
27559243Sobrien	return true;
27659243Sobrien      if (precision == DOUBLE_TYPE_SIZE)
27759243Sobrien	return true;
27859243Sobrien      if (precision == LONG_DOUBLE_TYPE_SIZE)
27959243Sobrien	return true;
28059243Sobrien      return false;
28159243Sobrien
28259243Sobrien    case MODE_DECIMAL_FLOAT:
28359243Sobrien      return false;
28459243Sobrien
28559243Sobrien    default:
28659243Sobrien      gcc_unreachable ();
28759243Sobrien    }
28859243Sobrien}
28959415Sobrien
29059243Sobrien/* True if the target supports decimal floating point.  */
29159243Sobrien
29259243Sobrienbool
29359415Sobriendefault_decimal_float_supported_p (void)
29459243Sobrien{
29559243Sobrien  return ENABLE_DECIMAL_FLOAT;
29659243Sobrien}
29759243Sobrien
29859243Sobrien/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns
29959243Sobrien   an error message.
30059243Sobrien
30159243Sobrien   This function checks whether a given INSN is valid within a low-overhead
30259243Sobrien   loop.  If INSN is invalid it returns the reason for that, otherwise it
30359243Sobrien   returns NULL. A called function may clobber any special registers required
30459243Sobrien   for low-overhead looping. Additionally, some targets (eg, PPC) use the count
30559243Sobrien   register for branch on table instructions. We reject the doloop pattern in
30659243Sobrien   these cases.  */
30759243Sobrien
30859243Sobrienconst char *
30959243Sobriendefault_invalid_within_doloop (rtx insn)
31059243Sobrien{
31159243Sobrien  if (CALL_P (insn))
31259243Sobrien    return "Function call in loop.";
31359415Sobrien
31459415Sobrien  if (JUMP_P (insn)
31559415Sobrien      && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
31659243Sobrien	  || GET_CODE (PATTERN (insn)) == ADDR_VEC))
31759243Sobrien    return "Computed branch in the loop.";
31859243Sobrien
31959243Sobrien  return NULL;
32059243Sobrien}
32159243Sobrien
32259243Sobrienbool
32359243Sobrienhook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
32459243Sobrien	CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
32559243Sobrien	enum machine_mode mode ATTRIBUTE_UNUSED,
32659243Sobrien	tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
32759243Sobrien{
32859243Sobrien  return false;
32959243Sobrien}
33059243Sobrien
33159415Sobrienbool
33259243Sobrienhook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
33359243Sobrien	CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
33459243Sobrien	enum machine_mode mode ATTRIBUTE_UNUSED,
33559243Sobrien	tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
33659243Sobrien{
33759243Sobrien  return true;
33859243Sobrien}
33959243Sobrien
34059243Sobrienint
34159243Sobrienhook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
34259243Sobrien	CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
34359243Sobrien	enum machine_mode mode ATTRIBUTE_UNUSED,
34459243Sobrien	tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
34559243Sobrien{
34659243Sobrien  return 0;
34759243Sobrien}
34859243Sobrien
34959243Sobrienvoid
35059243Sobrienhook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
35159243Sobrien{
35259243Sobrien}
35359243Sobrien
35459243Sobrienconst char *
35559243Sobrienhook_invalid_arg_for_unprototyped_fn (
35659243Sobrien	tree typelist ATTRIBUTE_UNUSED,
35759243Sobrien	tree funcdecl ATTRIBUTE_UNUSED,
35859243Sobrien	tree val ATTRIBUTE_UNUSED)
35959243Sobrien{
36059243Sobrien  return NULL;
36159415Sobrien}
36259243Sobrien
36359243Sobrien/* Initialize the stack protection decls.  */
36459243Sobrien
36559243Sobrien/* Stack protection related decls living in libgcc.  */
36659243Sobrienstatic GTY(()) tree stack_chk_guard_decl;
36759243Sobrien
36859243Sobrientree
36959243Sobriendefault_stack_protect_guard (void)
37059243Sobrien{
37159243Sobrien  tree t = stack_chk_guard_decl;
37259243Sobrien
37359243Sobrien  if (t == NULL)
37459243Sobrien    {
37559243Sobrien      t = build_decl (VAR_DECL, get_identifier ("__stack_chk_guard"),
37659243Sobrien		      ptr_type_node);
37759243Sobrien      TREE_STATIC (t) = 1;
37859243Sobrien      TREE_PUBLIC (t) = 1;
37959415Sobrien      DECL_EXTERNAL (t) = 1;
38059243Sobrien      TREE_USED (t) = 1;
38159243Sobrien      TREE_THIS_VOLATILE (t) = 1;
38259243Sobrien      DECL_ARTIFICIAL (t) = 1;
38359243Sobrien      DECL_IGNORED_P (t) = 1;
38459243Sobrien
38559243Sobrien      stack_chk_guard_decl = t;
38659415Sobrien    }
38759243Sobrien
38859243Sobrien  return t;
38959243Sobrien}
39059243Sobrien
39159415Sobrienstatic GTY(()) tree stack_chk_fail_decl;
39259243Sobrien
39359243Sobrientree
39459243Sobriendefault_external_stack_protect_fail (void)
39559243Sobrien{
39659243Sobrien  tree t = stack_chk_fail_decl;
39759243Sobrien
39859243Sobrien  if (t == NULL_TREE)
39959243Sobrien    {
40059243Sobrien      t = build_function_type_list (void_type_node, NULL_TREE);
40159415Sobrien      t = build_decl (FUNCTION_DECL, get_identifier ("__stack_chk_fail"), t);
40259243Sobrien      TREE_STATIC (t) = 1;
40359243Sobrien      TREE_PUBLIC (t) = 1;
40459243Sobrien      DECL_EXTERNAL (t) = 1;
40559243Sobrien      TREE_USED (t) = 1;
40659243Sobrien      TREE_THIS_VOLATILE (t) = 1;
40759243Sobrien      TREE_NOTHROW (t) = 1;
40859243Sobrien      DECL_ARTIFICIAL (t) = 1;
40959243Sobrien      DECL_IGNORED_P (t) = 1;
41059243Sobrien      DECL_VISIBILITY (t) = VISIBILITY_DEFAULT;
41159243Sobrien      DECL_VISIBILITY_SPECIFIED (t) = 1;
41259243Sobrien
41359243Sobrien      stack_chk_fail_decl = t;
41459243Sobrien    }
41559243Sobrien
41659243Sobrien  return build_function_call_expr (t, NULL_TREE);
41759243Sobrien}
41859243Sobrien
41959243Sobrientree
42059243Sobriendefault_hidden_stack_protect_fail (void)
42159243Sobrien{
42259243Sobrien#ifndef HAVE_GAS_HIDDEN
42359243Sobrien  return default_external_stack_protect_fail ();
42459243Sobrien#else
42559243Sobrien  tree t = stack_chk_fail_decl;
42659243Sobrien
42759243Sobrien  if (!flag_pic)
42859243Sobrien    return default_external_stack_protect_fail ();
42959243Sobrien
43059415Sobrien  if (t == NULL_TREE)
43159243Sobrien    {
43259243Sobrien      t = build_function_type_list (void_type_node, NULL_TREE);
43359243Sobrien      t = build_decl (FUNCTION_DECL,
43459243Sobrien		      get_identifier ("__stack_chk_fail_local"), t);
43559243Sobrien      TREE_STATIC (t) = 1;
43659243Sobrien      TREE_PUBLIC (t) = 1;
43759243Sobrien      DECL_EXTERNAL (t) = 1;
43859415Sobrien      TREE_USED (t) = 1;
43959243Sobrien      TREE_THIS_VOLATILE (t) = 1;
44059243Sobrien      TREE_NOTHROW (t) = 1;
44159243Sobrien      DECL_ARTIFICIAL (t) = 1;
44259243Sobrien      DECL_IGNORED_P (t) = 1;
44359243Sobrien      DECL_VISIBILITY_SPECIFIED (t) = 1;
44459415Sobrien      DECL_VISIBILITY (t) = VISIBILITY_HIDDEN;
44559243Sobrien
44659243Sobrien      stack_chk_fail_decl = t;
447231990Smp    }
448231990Smp
449231990Smp  return build_function_call_expr (t, NULL_TREE);
450231990Smp#endif
451231990Smp}
452231990Smp
453231990Smpbool
454231990Smphook_bool_rtx_commutative_p (rtx x, int outer_code ATTRIBUTE_UNUSED)
455231990Smp{
456231990Smp  return COMMUTATIVE_P (x);
457231990Smp}
45859243Sobrien
45959243Sobrienrtx
46059243Sobriendefault_function_value (tree ret_type ATTRIBUTE_UNUSED,
46159243Sobrien			tree fn_decl_or_type,
46259243Sobrien			bool outgoing ATTRIBUTE_UNUSED)
46359243Sobrien{
46459243Sobrien  /* The old interface doesn't handle receiving the function type.  */
46559243Sobrien  if (fn_decl_or_type
46659243Sobrien      && !DECL_P (fn_decl_or_type))
46759243Sobrien    fn_decl_or_type = NULL;
46859243Sobrien
46959243Sobrien#ifdef FUNCTION_OUTGOING_VALUE
47059243Sobrien  if (outgoing)
47159243Sobrien    return FUNCTION_OUTGOING_VALUE (ret_type, fn_decl_or_type);
47259243Sobrien#endif
47359243Sobrien
47459243Sobrien#ifdef FUNCTION_VALUE
47559243Sobrien  return FUNCTION_VALUE (ret_type, fn_decl_or_type);
47659243Sobrien#else
47759243Sobrien  return NULL_RTX;
47859243Sobrien#endif
47959243Sobrien}
48059243Sobrien
48159243Sobrienrtx
48259243Sobriendefault_internal_arg_pointer (void)
48359243Sobrien{
48459243Sobrien  /* If the reg that the virtual arg pointer will be translated into is
48559243Sobrien     not a fixed reg or is the stack pointer, make a copy of the virtual
48659415Sobrien     arg pointer, and address parms via the copy.  The frame pointer is
48759243Sobrien     considered fixed even though it is not marked as such.  */
48859243Sobrien  if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
48959243Sobrien       || ! (fixed_regs[ARG_POINTER_REGNUM]
49059243Sobrien	     || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
49159243Sobrien    return copy_to_reg (virtual_incoming_args_rtx);
49259243Sobrien  else
49359243Sobrien    return virtual_incoming_args_rtx;
49459243Sobrien}
49559243Sobrien
49659243Sobrienenum reg_class
49759243Sobriendefault_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
49859243Sobrien			  enum reg_class reload_class ATTRIBUTE_UNUSED,
49959243Sobrien			  enum machine_mode reload_mode ATTRIBUTE_UNUSED,
50059243Sobrien			  secondary_reload_info *sri)
50159243Sobrien{
50259243Sobrien  enum reg_class class = NO_REGS;
50359243Sobrien
50459243Sobrien  if (sri->prev_sri && sri->prev_sri->t_icode != CODE_FOR_nothing)
50559243Sobrien    {
50659243Sobrien      sri->icode = sri->prev_sri->t_icode;
50759243Sobrien      return NO_REGS;
50859243Sobrien    }
50959243Sobrien#ifdef SECONDARY_INPUT_RELOAD_CLASS
51059243Sobrien  if (in_p)
51159243Sobrien    class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
51259243Sobrien#endif
51359243Sobrien#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
51459243Sobrien  if (! in_p)
51559243Sobrien    class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
51659243Sobrien#endif
51759243Sobrien  if (class != NO_REGS)
51859243Sobrien    {
51959243Sobrien      enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
52059243Sobrien			      : reload_out_optab[(int) reload_mode]);
52159243Sobrien
52259243Sobrien      if (icode != CODE_FOR_nothing
52359243Sobrien	  && insn_data[(int) icode].operand[in_p].predicate
52459243Sobrien	  && ! insn_data[(int) icode].operand[in_p].predicate (x, reload_mode))
52559243Sobrien	icode = CODE_FOR_nothing;
52659243Sobrien      else if (icode != CODE_FOR_nothing)
52759415Sobrien	{
52859243Sobrien	  const char *insn_constraint, *scratch_constraint;
52959243Sobrien	  char insn_letter, scratch_letter;
53059415Sobrien	  enum reg_class insn_class, scratch_class;
53159243Sobrien
53259243Sobrien	  gcc_assert (insn_data[(int) icode].n_operands == 3);
53359243Sobrien	  insn_constraint = insn_data[(int) icode].operand[!in_p].constraint;
53459243Sobrien	  if (!*insn_constraint)
53559243Sobrien	    insn_class = ALL_REGS;
53659243Sobrien	  else
53759243Sobrien	    {
53859243Sobrien	      if (in_p)
53959415Sobrien		{
54059243Sobrien		  gcc_assert (*insn_constraint == '=');
54159243Sobrien		  insn_constraint++;
54259243Sobrien		}
54359243Sobrien	      insn_letter = *insn_constraint;
54459243Sobrien	      insn_class
54559243Sobrien		= (insn_letter == 'r' ? GENERAL_REGS
54659243Sobrien		   : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
54759243Sobrien						insn_constraint));
54859243Sobrien	      gcc_assert (insn_class != NO_REGS);
54959415Sobrien	    }
55059243Sobrien
55159415Sobrien	  scratch_constraint = insn_data[(int) icode].operand[2].constraint;
55259243Sobrien	  /* The scratch register's constraint must start with "=&",
55359243Sobrien	     except for an input reload, where only "=" is necessary,
55459243Sobrien	     and where it might be beneficial to re-use registers from
55559243Sobrien	     the input.  */
55659243Sobrien	  gcc_assert (scratch_constraint[0] == '='
55759243Sobrien		      && (in_p || scratch_constraint[1] == '&'));
55859243Sobrien	  scratch_constraint++;
55959243Sobrien	  if (*scratch_constraint == '&')
56059243Sobrien	    scratch_constraint++;
56159243Sobrien	  scratch_letter = *scratch_constraint;
56259243Sobrien	  scratch_class
56359415Sobrien	    = (scratch_letter == 'r' ? GENERAL_REGS
56459243Sobrien	       : REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
56559243Sobrien					    scratch_constraint));
56659243Sobrien
56759243Sobrien	  if (reg_class_subset_p (reload_class, insn_class))
56859243Sobrien	    {
56959243Sobrien	      gcc_assert (scratch_class == class);
57059243Sobrien	      class = NO_REGS;
57159243Sobrien	    }
57259243Sobrien	  else
57359243Sobrien	    class = insn_class;
57459243Sobrien
57559243Sobrien        }
57659243Sobrien      if (class == NO_REGS)
57759243Sobrien	sri->icode = icode;
57859243Sobrien      else
57959243Sobrien	sri->t_icode = icode;
58059243Sobrien    }
58159243Sobrien  return class;
58259243Sobrien}
58359243Sobrien
58459243Sobrien
58559243Sobrien/* If STRICT_ALIGNMENT is true we use the container type for accessing
58659243Sobrien   volatile bitfields.  This is generally the preferred behavior for memory
58759243Sobrien   mapped peripherals on RISC architectures.
58859243Sobrien   If STRICT_ALIGNMENT is false we use the narrowest type possible.  This
58959243Sobrien   is typically used to avoid spurious page faults and extra memory accesses
59059243Sobrien   due to unaligned accesses on CISC architectures.  */
59159243Sobrien
59259243Sobrienbool
59359243Sobriendefault_narrow_bitfield (void)
59459243Sobrien{
59559243Sobrien  return !STRICT_ALIGNMENT;
59659243Sobrien}
59759243Sobrien
59859243Sobrien/* By default, if flag_pic is true, then neither local nor global relocs
59959415Sobrien   should be placed in readonly memory.  */
60059243Sobrien
60159243Sobrienint
60259243Sobriendefault_reloc_rw_mask (void)
60359243Sobrien{
60459243Sobrien  return flag_pic ? 3 : 0;
60559243Sobrien}
60659243Sobrien
60759243Sobrien#include "gt-targhooks.h"
60859243Sobrien