explow.c revision 267654
157429Smarkm/* Subroutines for manipulating rtx's in semantically interesting ways.
257429Smarkm   Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
357429Smarkm   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
457429Smarkm   Free Software Foundation, Inc.
557429Smarkm
657429SmarkmThis file is part of GCC.
757429Smarkm
860573SkrisGCC is free software; you can redistribute it and/or modify it under
965668Skristhe terms of the GNU General Public License as published by the Free
1065668SkrisSoftware Foundation; either version 2, or (at your option) any later
1165668Skrisversion.
1265668Skris
1365668SkrisGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1465668SkrisWARRANTY; without even the implied warranty of MERCHANTABILITY or
1560573SkrisFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1692559Sdesfor more details.
1765668Skris
1865668SkrisYou should have received a copy of the GNU General Public License
1965668Skrisalong with GCC; see the file COPYING.  If not, write to the Free
2065668SkrisSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2165668Skris02110-1301, USA.  */
2265668Skris
2365668Skris
2465668Skris#include "config.h"
2565668Skris#include "system.h"
2665668Skris#include "coretypes.h"
2765668Skris#include "tm.h"
2865668Skris#include "toplev.h"
2965668Skris#include "rtl.h"
3065668Skris#include "tree.h"
3165668Skris#include "tm_p.h"
3265668Skris#include "flags.h"
3365668Skris#include "function.h"
3465668Skris#include "expr.h"
3565668Skris#include "optabs.h"
3665668Skris#include "hard-reg-set.h"
3765668Skris#include "insn-config.h"
3865668Skris#include "ggc.h"
3957429Smarkm#include "recog.h"
4057429Smarkm#include "langhooks.h"
4157429Smarkm#include "target.h"
42137019Sdes#include "output.h"
4357429Smarkm
4457429Smarkmstatic rtx break_out_memory_refs (rtx);
4576262Sgreenstatic void emit_stack_probe (rtx);
4676262Sgreen
4757429Smarkm
4857429Smarkm/* Truncate and perhaps sign-extend C as appropriate for MODE.  */
4976262Sgreen
5076262SgreenHOST_WIDE_INT
5157429Smarkmtrunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
5257429Smarkm{
5376262Sgreen  int width = GET_MODE_BITSIZE (mode);
5465668Skris
5565668Skris  /* You want to truncate to a _what_?  */
5692559Sdes  gcc_assert (SCALAR_INT_MODE_P (mode));
57124207Sdes
5865668Skris  /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
5992559Sdes  if (mode == BImode)
6057429Smarkm    return c & 1 ? STORE_FLAG_VALUE : 0;
6157429Smarkm
6257429Smarkm  /* Sign-extend for the requested mode.  */
6357429Smarkm
6457429Smarkm  if (width < HOST_BITS_PER_WIDE_INT)
6592559Sdes    {
6657429Smarkm      HOST_WIDE_INT sign = 1;
6757429Smarkm      sign <<= width - 1;
6857429Smarkm      c &= (sign << 1) - 1;
6992559Sdes      c ^= sign;
7057429Smarkm      c -= sign;
71137019Sdes    }
7257429Smarkm
7357429Smarkm  return c;
7457429Smarkm}
7592559Sdes
7657429Smarkm/* Return an rtx for the sum of X and the integer C.  */
7776262Sgreen
7857429Smarkmrtx
7957429Smarkmplus_constant (rtx x, HOST_WIDE_INT c)
8092559Sdes{
8157429Smarkm  RTX_CODE code;
8257429Smarkm  rtx y;
8357429Smarkm  enum machine_mode mode;
8457429Smarkm  rtx tem;
8557429Smarkm  int all_constant = 0;
8657429Smarkm
8757429Smarkm  if (c == 0)
8857429Smarkm    return x;
8960573Skris
9060573Skris restart:
9160573Skris
9257429Smarkm  code = GET_CODE (x);
9357429Smarkm  mode = GET_MODE (x);
9457429Smarkm  y = x;
9557429Smarkm
9692559Sdes  switch (code)
9757429Smarkm    {
9857429Smarkm    case CONST_INT:
9957429Smarkm      return GEN_INT (INTVAL (x) + c);
10057429Smarkm
10157429Smarkm    case CONST_DOUBLE:
10257429Smarkm      {
10357429Smarkm	unsigned HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
10457429Smarkm	HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
10557429Smarkm	unsigned HOST_WIDE_INT l2 = c;
10657429Smarkm	HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
10792559Sdes	unsigned HOST_WIDE_INT lv;
10892559Sdes	HOST_WIDE_INT hv;
10992559Sdes
11092559Sdes	add_double (l1, h1, l2, h2, &lv, &hv);
11192559Sdes
11292559Sdes	return immed_double_const (lv, hv, VOIDmode);
11392559Sdes      }
11492559Sdes
11592559Sdes    case MEM:
11692559Sdes      /* If this is a reference to the constant pool, try replacing it with
11792559Sdes	 a reference to a new constant.  If the resulting address isn't
11892559Sdes	 valid, don't return it because we have no way to validize it.  */
11992559Sdes      if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
12092559Sdes	  && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
12192559Sdes	{
12292559Sdes	  tem
12392559Sdes	    = force_const_mem (GET_MODE (x),
12492559Sdes			       plus_constant (get_pool_constant (XEXP (x, 0)),
12592559Sdes					      c));
12692559Sdes	  if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
12792559Sdes	    return tem;
12892559Sdes	}
12992559Sdes      break;
13092559Sdes
13176262Sgreen    case CONST:
13298941Sdes      /* If adding to something entirely constant, set a flag
13376262Sgreen	 so that we can add a CONST around the result.  */
13492559Sdes      x = XEXP (x, 0);
13592559Sdes      all_constant = 1;
13676262Sgreen      goto restart;
13792559Sdes
13857429Smarkm    case SYMBOL_REF:
13960573Skris    case LABEL_REF:
14060573Skris      all_constant = 1;
14160573Skris      break;
14260573Skris
14392559Sdes    case PLUS:
144137019Sdes      /* The interesting case is adding the integer to a sum.
145124207Sdes	 Look for constant term in the sum and combine
14660573Skris	 with C.  For an integer constant term, we make a combined
14760573Skris	 integer.  For a constant term that is not an explicit integer,
14892559Sdes	 we cannot really combine, but group them together anyway.
14992559Sdes
150124207Sdes	 Restart or use a recursive call in case the remaining operand is
15160573Skris	 something that we handle specially, such as a SYMBOL_REF.
15260573Skris
15360573Skris	 We may not immediately return from the recursive call here, lest
15460573Skris	 all_constant gets lost.  */
15560573Skris
15657429Smarkm      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
15760573Skris	{
15860573Skris	  c += INTVAL (XEXP (x, 1));
15960573Skris
16060573Skris	  if (GET_MODE (x) != VOIDmode)
16192559Sdes	    c = trunc_int_for_mode (c, GET_MODE (x));
16269587Sgreen
16369587Sgreen	  x = XEXP (x, 0);
16460573Skris	  goto restart;
16560573Skris	}
16676262Sgreen      else if (CONSTANT_P (XEXP (x, 1)))
16776262Sgreen	{
16876262Sgreen	  x = gen_rtx_PLUS (mode, XEXP (x, 0), plus_constant (XEXP (x, 1), c));
16976262Sgreen	  c = 0;
17060573Skris	}
17160573Skris      else if (find_constant_term_loc (&y))
17260573Skris	{
17360573Skris	  /* We need to be careful since X may be shared and we can't
17460573Skris	     modify it in place.  */
175137019Sdes	  rtx copy = copy_rtx (x);
17660573Skris	  rtx *const_loc = find_constant_term_loc (&copy);
17760573Skris
17869587Sgreen	  *const_loc = plus_constant (*const_loc, c);
17974500Sgreen	  x = copy;
18074500Sgreen	  c = 0;
181124207Sdes	}
18274500Sgreen      break;
18374500Sgreen
18476262Sgreen    default:
18574500Sgreen      break;
18674500Sgreen    }
18774500Sgreen
18874500Sgreen  if (c != 0)
18974500Sgreen    x = gen_rtx_PLUS (mode, x, GEN_INT (c));
190106130Sdes
19174500Sgreen  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
19269587Sgreen    return x;
19369587Sgreen  else if (all_constant)
19469587Sgreen    return gen_rtx_CONST (mode, x);
19569587Sgreen  else
19669587Sgreen    return x;
19769587Sgreen}
19869587Sgreen
19969587Sgreen/* If X is a sum, return a new sum like X but lacking any constant terms.
20069587Sgreen   Add all the removed constant terms into *CONSTPTR.
20160573Skris   X itself is not altered.  The result != X if and only if
20260573Skris   it is not isomorphic to X.  */
20360573Skris
20457429Smarkmrtx
20557429Smarkmeliminate_constant_term (rtx x, rtx *constptr)
20657429Smarkm{
20757429Smarkm  rtx x0, x1;
20892559Sdes  rtx tem;
20960573Skris
21099063Sdes  if (GET_CODE (x) != PLUS)
21157429Smarkm    return x;
212137019Sdes
213137019Sdes  /* First handle constants appearing at this level explicitly.  */
21457429Smarkm  if (GET_CODE (XEXP (x, 1)) == CONST_INT
21557429Smarkm      && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
21657429Smarkm						XEXP (x, 1)))
21757429Smarkm      && GET_CODE (tem) == CONST_INT)
21857429Smarkm    {
21992559Sdes      *constptr = tem;
22057429Smarkm      return eliminate_constant_term (XEXP (x, 0), constptr);
22192559Sdes    }
22257429Smarkm
22357429Smarkm  tem = const0_rtx;
22457429Smarkm  x0 = eliminate_constant_term (XEXP (x, 0), &tem);
22592559Sdes  x1 = eliminate_constant_term (XEXP (x, 1), &tem);
22657429Smarkm  if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
227137019Sdes      && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
22857429Smarkm						*constptr, tem))
22957429Smarkm      && GET_CODE (tem) == CONST_INT)
230137019Sdes    {
23157429Smarkm      *constptr = tem;
23257429Smarkm      return gen_rtx_PLUS (GET_MODE (x), x0, x1);
23399063Sdes    }
23499063Sdes
23599063Sdes  return x;
236120489Sjoe}
237120489Sjoe
238120489Sjoe/* Return an rtx for the size in bytes of the value of EXP.  */
23969587Sgreen
24057429Smarkmrtx
24192559Sdesexpr_size (tree exp)
24257429Smarkm{
24392559Sdes  tree size;
24492559Sdes
24592559Sdes  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
24657429Smarkm    size = TREE_OPERAND (exp, 1);
24757429Smarkm  else
24860573Skris    size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
24992559Sdes
25092559Sdes  return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
25192559Sdes}
25269587Sgreen
25357429Smarkm/* Return a wide integer for the size in bytes of the value of EXP, or -1
25457429Smarkm   if the size can vary or is larger than an integer.  */
25560573Skris
25660573SkrisHOST_WIDE_INT
25760573Skrisint_expr_size (tree exp)
25860573Skris{
25960573Skris  tree size;
26057429Smarkm
261124207Sdes  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
26260573Skris    size = TREE_OPERAND (exp, 1);
26360573Skris  else
26492559Sdes    size = lang_hooks.expr_size (exp);
26592559Sdes
26692559Sdes  if (size == 0 || !host_integerp (size, 0))
26792559Sdes    return -1;
268137019Sdes
26965668Skris  return tree_low_cst (size, 0);
27057429Smarkm}
27192559Sdes
27257429Smarkm/* Return a copy of X in which all memory references
27392559Sdes   and all constants that involve symbol refs
27492559Sdes   have been replaced with new temporary registers.
27592559Sdes   Also emit code to load the memory locations and constants
27692559Sdes   into those registers.
277137019Sdes
278137019Sdes   If X contains no such constants or memory references,
27992559Sdes   X itself (not a copy) is returned.
28092559Sdes
28192559Sdes   If a constant is found in the address that is not a legitimate constant
28292559Sdes   in an insn, it is left alone in the hope that it might be valid in the
28392559Sdes   address.
28492559Sdes
28592559Sdes   X may contain no arithmetic except addition, subtraction and multiplication.
28692559Sdes   Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
28792559Sdes
28892559Sdesstatic rtx
28992559Sdesbreak_out_memory_refs (rtx x)
29092559Sdes{
29192559Sdes  if (MEM_P (x)
29260573Skris      || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
29392559Sdes	  && GET_MODE (x) != VOIDmode))
29460573Skris    x = force_reg (GET_MODE (x), x);
29592559Sdes  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
29692559Sdes	   || GET_CODE (x) == MULT)
29792559Sdes    {
29892559Sdes      rtx op0 = break_out_memory_refs (XEXP (x, 0));
29992559Sdes      rtx op1 = break_out_memory_refs (XEXP (x, 1));
30092559Sdes
30192559Sdes      if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
30292559Sdes	x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
30392559Sdes    }
30460573Skris
30557429Smarkm  return x;
30660573Skris}
30760573Skris
30892559Sdes/* Given X, a memory address in ptr_mode, convert it to an address
30960573Skris   in Pmode, or vice versa (TO_MODE says which way).  We take advantage of
31057429Smarkm   the fact that pointers are not allowed to overflow by commuting arithmetic
311137019Sdes   operations over conversions so that address arithmetic insns can be
312137019Sdes   used.  */
31392559Sdes
31492559Sdesrtx
315137019Sdesconvert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
31692559Sdes			rtx x)
31792559Sdes{
31892559Sdes#ifndef POINTERS_EXTEND_UNSIGNED
31960573Skris  gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
32057429Smarkm  return x;
32160573Skris#else /* defined(POINTERS_EXTEND_UNSIGNED) */
32260573Skris  enum machine_mode from_mode;
32360573Skris  rtx temp;
32492559Sdes  enum rtx_code code;
32560573Skris
32692559Sdes  /* If X already has the right mode, just return it.  */
327137019Sdes  if (GET_MODE (x) == to_mode)
32876262Sgreen    return x;
32992559Sdes
33092559Sdes  from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
33192559Sdes
332137019Sdes  /* Here we handle some special cases.  If none of them apply, fall through
33392559Sdes     to the default case.  */
33492559Sdes  switch (GET_CODE (x))
33592559Sdes    {
336124207Sdes    case CONST_INT:
33776262Sgreen    case CONST_DOUBLE:
33876262Sgreen      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
33960573Skris	code = TRUNCATE;
34060573Skris      else if (POINTERS_EXTEND_UNSIGNED < 0)
341137019Sdes	break;
342137019Sdes      else if (POINTERS_EXTEND_UNSIGNED > 0)
34360573Skris	code = ZERO_EXTEND;
34460573Skris      else
34560573Skris	code = SIGN_EXTEND;
34660573Skris      temp = simplify_unary_operation (code, to_mode, x, from_mode);
34760573Skris      if (temp)
34860573Skris	return temp;
34960573Skris      break;
35060573Skris
35192559Sdes    case SUBREG:
35292559Sdes      if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
35357429Smarkm	  && GET_MODE (SUBREG_REG (x)) == to_mode)
35457429Smarkm	return SUBREG_REG (x);
35592559Sdes      break;
35692559Sdes
35792559Sdes    case LABEL_REF:
358137019Sdes      temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
35992559Sdes      LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
36092559Sdes      return temp;
36192559Sdes      break;
36292559Sdes
36392559Sdes    case SYMBOL_REF:
36492559Sdes      temp = shallow_copy_rtx (x);
36557429Smarkm      PUT_MODE (temp, to_mode);
36692559Sdes      return temp;
36792559Sdes      break;
36892559Sdes
36992559Sdes    case CONST:
37092559Sdes      return gen_rtx_CONST (to_mode,
37192559Sdes			    convert_memory_address (to_mode, XEXP (x, 0)));
37292559Sdes      break;
373137019Sdes
37492559Sdes    case PLUS:
37592559Sdes    case MULT:
37692559Sdes      /* For addition we can safely permute the conversion and addition
37792559Sdes	 operation if one operand is a constant and converting the constant
37892559Sdes	 does not change it.  We can always safely permute them if we are
37992559Sdes	 making the address narrower.  */
38092559Sdes      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
38192559Sdes	  || (GET_CODE (x) == PLUS
38292559Sdes	      && GET_CODE (XEXP (x, 1)) == CONST_INT
38392559Sdes	      && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))))
38492559Sdes	return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
38592559Sdes			       convert_memory_address (to_mode, XEXP (x, 0)),
38692559Sdes			       XEXP (x, 1));
387137019Sdes      break;
38892559Sdes
38992559Sdes    default:
39092559Sdes      break;
39192559Sdes    }
39292559Sdes
39392559Sdes  return convert_modes (to_mode, from_mode,
39492559Sdes			x, POINTERS_EXTEND_UNSIGNED);
39592559Sdes#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
39692559Sdes}
39792559Sdes
39892559Sdes/* Return something equivalent to X but valid as a memory address
39992559Sdes   for something of mode MODE.  When X is not itself valid, this
40092559Sdes   works by copying X or subexpressions of it into registers.  */
40192559Sdes
40292559Sdesrtx
40392559Sdesmemory_address (enum machine_mode mode, rtx x)
40492559Sdes{
40592559Sdes  rtx oldx = x;
40692559Sdes
40792559Sdes  x = convert_memory_address (Pmode, x);
40892559Sdes
40992559Sdes  /* By passing constant addresses through registers
41092559Sdes     we get a chance to cse them.  */
41192559Sdes  if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
41292559Sdes    x = force_reg (Pmode, x);
41392559Sdes
41492559Sdes  /* We get better cse by rejecting indirect addressing at this stage.
41592559Sdes     Let the combiner create indirect addresses where appropriate.
41692559Sdes     For now, generate the code so that the subexpressions useful to share
41792559Sdes     are visible.  But not if cse won't be done!  */
41892559Sdes  else
41992559Sdes    {
42092559Sdes      if (! cse_not_expected && !REG_P (x))
42192559Sdes	x = break_out_memory_refs (x);
42292559Sdes
423113911Sdes      /* At this point, any valid address is accepted.  */
42492559Sdes      if (memory_address_p (mode, x))
42592559Sdes	goto win;
42692559Sdes
42792559Sdes      /* If it was valid before but breaking out memory refs invalidated it,
42892559Sdes	 use it the old way.  */
429124207Sdes      if (memory_address_p (mode, oldx))
43092559Sdes	goto win2;
43192559Sdes
43292559Sdes      /* Perform machine-dependent transformations on X
43392559Sdes	 in certain cases.  This is not necessary since the code
43492559Sdes	 below can handle all possible cases, but machine-dependent
43592559Sdes	 transformations can make better code.  */
43692559Sdes      LEGITIMIZE_ADDRESS (x, oldx, mode, win);
43792559Sdes
43892559Sdes      /* PLUS and MULT can appear in special ways
43992559Sdes	 as the result of attempts to make an address usable for indexing.
44092559Sdes	 Usually they are dealt with by calling force_operand, below.
44192559Sdes	 But a sum containing constant terms is special
44292559Sdes	 if removing them makes the sum a valid address:
44392559Sdes	 then we generate that address in a register
444137019Sdes	 and index off of it.  We do this because it often makes
44592559Sdes	 shorter code, and because the addresses thus generated
44692559Sdes	 in registers often become common subexpressions.  */
44792559Sdes      if (GET_CODE (x) == PLUS)
44892559Sdes	{
44992559Sdes	  rtx constant_term = const0_rtx;
45092559Sdes	  rtx y = eliminate_constant_term (x, &constant_term);
45192559Sdes	  if (constant_term == const0_rtx
45292559Sdes	      || ! memory_address_p (mode, y))
45392559Sdes	    x = force_operand (x, NULL_RTX);
45492559Sdes	  else
45592559Sdes	    {
45692559Sdes	      y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
45792559Sdes	      if (! memory_address_p (mode, y))
45892559Sdes		x = force_operand (x, NULL_RTX);
45992559Sdes	      else
46092559Sdes		x = y;
46192559Sdes	    }
46292559Sdes	}
46392559Sdes
46492559Sdes      else if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
46592559Sdes	x = force_operand (x, NULL_RTX);
46692559Sdes
46792559Sdes      /* If we have a register that's an invalid address,
46892559Sdes	 it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
46992559Sdes      else if (REG_P (x))
47092559Sdes	x = copy_to_reg (x);
47192559Sdes
47292559Sdes      /* Last resort: copy the value to a register, since
47392559Sdes	 the register is a valid address.  */
47492559Sdes      else
47592559Sdes	x = force_reg (Pmode, x);
47692559Sdes
47792559Sdes      goto done;
47892559Sdes
47992559Sdes    win2:
48092559Sdes      x = oldx;
48192559Sdes    win:
48292559Sdes      if (flag_force_addr && ! cse_not_expected && !REG_P (x))
48392559Sdes	{
48492559Sdes	  x = force_operand (x, NULL_RTX);
48592559Sdes	  x = force_reg (Pmode, x);
48692559Sdes	}
487137019Sdes    }
48892559Sdes
48992559Sdes done:
49092559Sdes
49192559Sdes  /* If we didn't change the address, we are done.  Otherwise, mark
492137019Sdes     a reg as a pointer if we have REG or REG + CONST_INT.  */
49392559Sdes  if (oldx == x)
49492559Sdes    return x;
49592559Sdes  else if (REG_P (x))
49692559Sdes    mark_reg_pointer (x, BITS_PER_UNIT);
49792559Sdes  else if (GET_CODE (x) == PLUS
49892559Sdes	   && REG_P (XEXP (x, 0))
49992559Sdes	   && GET_CODE (XEXP (x, 1)) == CONST_INT)
50092559Sdes    mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
50192559Sdes
50292559Sdes  /* OLDX may have been the address on a temporary.  Update the address
50392559Sdes     to indicate that X is now used.  */
50492559Sdes  update_temp_slot_address (oldx, x);
50592559Sdes
50692559Sdes  return x;
50792559Sdes}
50892559Sdes
50992559Sdes/* Like `memory_address' but pretend `flag_force_addr' is 0.  */
51092559Sdes
51192559Sdesrtx
51292559Sdesmemory_address_noforce (enum machine_mode mode, rtx x)
51392559Sdes{
51492559Sdes  int ambient_force_addr = flag_force_addr;
51592559Sdes  rtx val;
51692559Sdes
51792559Sdes  flag_force_addr = 0;
51892559Sdes  val = memory_address (mode, x);
51992559Sdes  flag_force_addr = ambient_force_addr;
52092559Sdes  return val;
52192559Sdes}
52292559Sdes
52392559Sdes/* Convert a mem ref into one with a valid memory address.
52492559Sdes   Pass through anything else unchanged.  */
52592559Sdes
52692559Sdesrtx
52792559Sdesvalidize_mem (rtx ref)
52892559Sdes{
52992559Sdes  if (!MEM_P (ref))
53092559Sdes    return ref;
53192559Sdes  ref = use_anchored_address (ref);
53292559Sdes  if (! (flag_force_addr && CONSTANT_ADDRESS_P (XEXP (ref, 0)))
53392559Sdes      && memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
53492559Sdes    return ref;
535137019Sdes
53692559Sdes  /* Don't alter REF itself, since that is probably a stack slot.  */
53792559Sdes  return replace_equiv_address (ref, XEXP (ref, 0));
53892559Sdes}
53992559Sdes
54092559Sdes/* If X is a memory reference to a member of an object block, try rewriting
54192559Sdes   it to use an anchor instead.  Return the new memory reference on success
54292559Sdes   and the old one on failure.  */
54392559Sdes
54492559Sdesrtx
54592559Sdesuse_anchored_address (rtx x)
54692559Sdes{
54792559Sdes  rtx base;
54892559Sdes  HOST_WIDE_INT offset;
54992559Sdes
55092559Sdes  if (!flag_section_anchors)
55192559Sdes    return x;
55292559Sdes
55392559Sdes  if (!MEM_P (x))
55492559Sdes    return x;
55592559Sdes
55692559Sdes  /* Split the address into a base and offset.  */
55792559Sdes  base = XEXP (x, 0);
55892559Sdes  offset = 0;
55992559Sdes  if (GET_CODE (base) == CONST
560137019Sdes      && GET_CODE (XEXP (base, 0)) == PLUS
561137019Sdes      && GET_CODE (XEXP (XEXP (base, 0), 1)) == CONST_INT)
56292559Sdes    {
56392559Sdes      offset += INTVAL (XEXP (XEXP (base, 0), 1));
56492559Sdes      base = XEXP (XEXP (base, 0), 0);
56592559Sdes    }
566137019Sdes
56792559Sdes  /* Check whether BASE is suitable for anchors.  */
56892559Sdes  if (GET_CODE (base) != SYMBOL_REF
56992559Sdes      || !SYMBOL_REF_HAS_BLOCK_INFO_P (base)
57092559Sdes      || SYMBOL_REF_ANCHOR_P (base)
57192559Sdes      || SYMBOL_REF_BLOCK (base) == NULL
57292559Sdes      || !targetm.use_anchors_for_symbol_p (base))
57392559Sdes    return x;
57492559Sdes
57592559Sdes  /* Decide where BASE is going to be.  */
57692559Sdes  place_block_symbol (base);
57792559Sdes
57892559Sdes  /* Get the anchor we need to use.  */
57992559Sdes  offset += SYMBOL_REF_BLOCK_OFFSET (base);
58092559Sdes  base = get_section_anchor (SYMBOL_REF_BLOCK (base), offset,
58192559Sdes			     SYMBOL_REF_TLS_MODEL (base));
58292559Sdes
58392559Sdes  /* Work out the offset from the anchor.  */
584106130Sdes  offset -= SYMBOL_REF_BLOCK_OFFSET (base);
58592559Sdes
586124207Sdes  /* If we're going to run a CSE pass, force the anchor into a register.
58792559Sdes     We will then be able to reuse registers for several accesses, if the
58892559Sdes     target costs say that that's worthwhile.  */
589113911Sdes  if (!cse_not_expected)
59092559Sdes    base = force_reg (GET_MODE (base), base);
59192559Sdes
59292559Sdes  return replace_equiv_address (x, plus_constant (base, offset));
59392559Sdes}
59492559Sdes
59592559Sdes/* Copy the value or contents of X to a new temp reg and return that reg.  */
59692559Sdes
59792559Sdesrtx
59892559Sdescopy_to_reg (rtx x)
599113911Sdes{
60092559Sdes  rtx temp = gen_reg_rtx (GET_MODE (x));
601113911Sdes
602106130Sdes  /* If not an operand, must be an address with PLUS and MULT so
60392559Sdes     do the computation.  */
604124207Sdes  if (! general_operand (x, VOIDmode))
60592559Sdes    x = force_operand (x, temp);
60692559Sdes
607137019Sdes  if (x != temp)
60892559Sdes    emit_move_insn (temp, x);
60992559Sdes
61092559Sdes  return temp;
61192559Sdes}
61292559Sdes
61392559Sdes/* Like copy_to_reg but always give the new register mode Pmode
614137019Sdes   in case X is a constant.  */
61592559Sdes
61692559Sdesrtx
617106130Sdescopy_addr_to_reg (rtx x)
61892559Sdes{
619124207Sdes  return copy_to_mode_reg (Pmode, x);
62092559Sdes}
62192559Sdes
62292559Sdes/* Like copy_to_reg but always give the new register mode MODE
623137019Sdes   in case X is a constant.  */
62492559Sdes
62592559Sdesrtx
62692559Sdescopy_to_mode_reg (enum machine_mode mode, rtx x)
62792559Sdes{
62892559Sdes  rtx temp = gen_reg_rtx (mode);
629106130Sdes
63092559Sdes  /* If not an operand, must be an address with PLUS and MULT so
631124207Sdes     do the computation.  */
63292559Sdes  if (! general_operand (x, VOIDmode))
63392559Sdes    x = force_operand (x, temp);
63492559Sdes
63592559Sdes  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
63692559Sdes  if (x != temp)
63792559Sdes    emit_move_insn (temp, x);
63892559Sdes  return temp;
63992559Sdes}
640106130Sdes
64192559Sdes/* Load X into a register if it is not already one.
642124207Sdes   Use mode MODE for the register.
64392559Sdes   X should be valid for mode MODE, but it may be a constant which
64492559Sdes   is valid for all integer modes; that's why caller must specify MODE.
64592559Sdes
64692559Sdes   The caller must not alter the value in the register we return,
64792559Sdes   since we mark it as a "constant" register.  */
64892559Sdes
64992559Sdesrtx
65092559Sdesforce_reg (enum machine_mode mode, rtx x)
651106130Sdes{
65292559Sdes  rtx temp, insn, set;
653124207Sdes
65492559Sdes  if (REG_P (x))
65592559Sdes    return x;
65692559Sdes
65792559Sdes  if (general_operand (x, mode))
65892559Sdes    {
65992559Sdes      temp = gen_reg_rtx (mode);
66092559Sdes      insn = emit_move_insn (temp, x);
66192559Sdes    }
66292559Sdes  else
66392559Sdes    {
664106130Sdes      temp = force_operand (x, NULL_RTX);
66592559Sdes      if (REG_P (temp))
66692559Sdes	insn = get_last_insn ();
66792559Sdes      else
66892559Sdes	{
66992559Sdes	  rtx temp2 = gen_reg_rtx (mode);
67092559Sdes	  insn = emit_move_insn (temp2, temp);
67192559Sdes	  temp = temp2;
67292559Sdes	}
67392559Sdes    }
67492559Sdes
67592559Sdes  /* Let optimizers know that TEMP's value never changes
67692559Sdes     and that X can be substituted for it.  Don't get confused
67760573Skris     if INSN set something else (such as a SUBREG of TEMP).  */
67860573Skris  if (CONSTANT_P (x)
67957429Smarkm      && (set = single_set (insn)) != 0
68060573Skris      && SET_DEST (set) == temp
68160573Skris      && ! rtx_equal_p (x, SET_SRC (set)))
68260573Skris    set_unique_reg_note (insn, REG_EQUAL, x);
68360573Skris
68460573Skris  /* Let optimizers know that TEMP is a pointer, and if so, the
68560573Skris     known alignment of that pointer.  */
68660573Skris  {
68757429Smarkm    unsigned align = 0;
68892559Sdes    if (GET_CODE (x) == SYMBOL_REF)
68960573Skris      {
69057429Smarkm        align = BITS_PER_UNIT;
69160573Skris	if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
69260573Skris	  align = DECL_ALIGN (SYMBOL_REF_DECL (x));
69360573Skris      }
69492559Sdes    else if (GET_CODE (x) == LABEL_REF)
69576262Sgreen      align = BITS_PER_UNIT;
69676262Sgreen    else if (GET_CODE (x) == CONST
69776262Sgreen	     && GET_CODE (XEXP (x, 0)) == PLUS
69876262Sgreen	     && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
69976262Sgreen	     && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
70076262Sgreen      {
70192559Sdes	rtx s = XEXP (XEXP (x, 0), 0);
70260573Skris	rtx c = XEXP (XEXP (x, 0), 1);
70360573Skris	unsigned sa, ca;
70460573Skris
70560573Skris	sa = BITS_PER_UNIT;
70660573Skris	if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
70760573Skris	  sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
70860573Skris
70960573Skris	ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
71092559Sdes
71192559Sdes	align = MIN (sa, ca);
71260573Skris      }
71392559Sdes    else if (MEM_P (x) && MEM_POINTER (x))
71460573Skris      align = MEM_ALIGN (x);
71560573Skris
71692559Sdes    if (align)
71792559Sdes      mark_reg_pointer (temp, align);
71860573Skris  }
71960573Skris
72060573Skris  return temp;
72160573Skris}
72260573Skris
72360573Skris/* If X is a memory ref, copy its contents to a new temp reg and return
72498684Sdes   that reg.  Otherwise, return X.  */
72598684Sdes
72698684Sdesrtx
72798684Sdesforce_not_mem (rtx x)
72898684Sdes{
72960573Skris  rtx temp;
73060573Skris
73160573Skris  if (!MEM_P (x) || GET_MODE (x) == BLKmode)
73292559Sdes    return x;
73360573Skris
73460573Skris  temp = gen_reg_rtx (GET_MODE (x));
73560573Skris
73698684Sdes  if (MEM_POINTER (x))
73798684Sdes    REG_POINTER (temp) = 1;
73860573Skris
73960573Skris  emit_move_insn (temp, x);
74060573Skris  return temp;
741137019Sdes}
742137019Sdes
743137019Sdes/* Copy X to TARGET (if it's nonzero and a reg)
744137019Sdes   or to a new temp reg and return that reg.
74560573Skris   MODE is the mode to use for X in case it is a constant.  */
74660573Skris
74792559Sdesrtx
74860573Skriscopy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
74960573Skris{
75060573Skris  rtx temp;
75160573Skris
75260573Skris  if (target && REG_P (target))
75360573Skris    temp = target;
75460573Skris  else
755124207Sdes    temp = gen_reg_rtx (mode);
75660573Skris
75760573Skris  emit_move_insn (temp, x);
75860573Skris  return temp;
75992559Sdes}
76060573Skris
76160573Skris/* Return the mode to use to store a scalar of TYPE and MODE.
76260573Skris   PUNSIGNEDP points to the signedness of the type and may be adjusted
76392559Sdes   to show what signedness to use on extension operations.
76460573Skris
76560573Skris   FOR_CALL is nonzero if this call is promoting args for a call.  */
76660573Skris
76760573Skris#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
76860573Skris#define PROMOTE_FUNCTION_MODE PROMOTE_MODE
76960573Skris#endif
77060573Skris
77160573Skrisenum machine_mode
77260573Skrispromote_mode (tree type, enum machine_mode mode, int *punsignedp,
77360573Skris	      int for_call ATTRIBUTE_UNUSED)
77460573Skris{
77592559Sdes  enum tree_code code = TREE_CODE (type);
77660573Skris  int unsignedp = *punsignedp;
77792559Sdes
77892559Sdes#ifndef PROMOTE_MODE
77960573Skris  if (! for_call)
78076262Sgreen    return mode;
78176262Sgreen#endif
78257429Smarkm
78360573Skris  switch (code)
78492559Sdes    {
78560573Skris#ifdef PROMOTE_FUNCTION_MODE
78657429Smarkm    case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
78760573Skris    case REAL_TYPE:      case OFFSET_TYPE:
78892559Sdes#ifdef PROMOTE_MODE
78960573Skris      if (for_call)
79060573Skris	{
79160573Skris#endif
79260573Skris	  PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
79360573Skris#ifdef PROMOTE_MODE
79460573Skris	}
79560573Skris      else
796124207Sdes	{
79792559Sdes	  PROMOTE_MODE (mode, unsignedp, type);
79860573Skris	}
79960573Skris#endif
80057429Smarkm      break;
80160573Skris#endif
80292559Sdes
80360573Skris#ifdef POINTERS_EXTEND_UNSIGNED
80460573Skris    case REFERENCE_TYPE:
80557429Smarkm    case POINTER_TYPE:
80660573Skris      mode = Pmode;
80760573Skris      unsignedp = POINTERS_EXTEND_UNSIGNED;
80860573Skris      break;
809124207Sdes#endif
81060573Skris
81160573Skris    default:
81260573Skris      break;
81360573Skris    }
81460573Skris
81560573Skris  *punsignedp = unsignedp;
816124207Sdes  return mode;
81760573Skris}
81860573Skris
81960573Skris/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
82060573Skris   This pops when ADJUST is positive.  ADJUST need not be constant.  */
82160573Skris
82260573Skrisvoid
82360573Skrisadjust_stack (rtx adjust)
82460573Skris{
82560573Skris  rtx temp;
82660573Skris
82760573Skris  if (adjust == const0_rtx)
82860573Skris    return;
82960573Skris
83060573Skris  /* We expect all variable sized adjustments to be multiple of
83160573Skris     PREFERRED_STACK_BOUNDARY.  */
83260573Skris  if (GET_CODE (adjust) == CONST_INT)
83360573Skris    stack_pointer_delta -= INTVAL (adjust);
83457429Smarkm
83592559Sdes  temp = expand_binop (Pmode,
83660573Skris#ifdef STACK_GROWS_DOWNWARD
83760573Skris		       add_optab,
83892559Sdes#else
839106130Sdes		       sub_optab,
84060573Skris#endif
84160573Skris		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
84260573Skris		       OPTAB_LIB_WIDEN);
84360573Skris
84460573Skris  if (temp != stack_pointer_rtx)
84560573Skris    emit_move_insn (stack_pointer_rtx, temp);
84660573Skris}
84760573Skris
84860573Skris/* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
849124207Sdes   This pushes when ADJUST is positive.  ADJUST need not be constant.  */
85060573Skris
85160573Skrisvoid
85292559Sdesanti_adjust_stack (rtx adjust)
85360573Skris{
85460573Skris  rtx temp;
85560573Skris
85660573Skris  if (adjust == const0_rtx)
85760573Skris    return;
85860573Skris
85960573Skris  /* We expect all variable sized adjustments to be multiple of
86057429Smarkm     PREFERRED_STACK_BOUNDARY.  */
86192559Sdes  if (GET_CODE (adjust) == CONST_INT)
86260573Skris    stack_pointer_delta += INTVAL (adjust);
86360573Skris
86492559Sdes  temp = expand_binop (Pmode,
86592559Sdes#ifdef STACK_GROWS_DOWNWARD
86692559Sdes		       sub_optab,
86792559Sdes#else
86860573Skris		       add_optab,
86960573Skris#endif
87092559Sdes		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
87192559Sdes		       OPTAB_LIB_WIDEN);
872124207Sdes
873124207Sdes  if (temp != stack_pointer_rtx)
87492559Sdes    emit_move_insn (stack_pointer_rtx, temp);
87592559Sdes}
87692559Sdes
87792559Sdes/* Round the size of a block to be pushed up to the boundary required
87892559Sdes   by this machine.  SIZE is the desired size, which need not be constant.  */
87960573Skris
88092559Sdesstatic rtx
88160573Skrisround_push (rtx size)
88292559Sdes{
883124207Sdes  int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
88460573Skris
88560573Skris  if (align == 1)
88657429Smarkm    return size;
88776262Sgreen
88892559Sdes  if (GET_CODE (size) == CONST_INT)
88976262Sgreen    {
89076262Sgreen      HOST_WIDE_INT new = (INTVAL (size) + align - 1) / align * align;
891106130Sdes
89276262Sgreen      if (INTVAL (size) != new)
89392559Sdes	size = GEN_INT (new);
89476262Sgreen    }
89576262Sgreen  else
89676262Sgreen    {
89776262Sgreen      /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
89876262Sgreen	 but we know it can't.  So add ourselves and then do
89976262Sgreen	 TRUNC_DIV_EXPR.  */
90076262Sgreen      size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
90176262Sgreen			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
90276262Sgreen      size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
90376262Sgreen			    NULL_RTX, 1);
90476262Sgreen      size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
90576262Sgreen    }
90676262Sgreen
90776262Sgreen  return size;
90876262Sgreen}
90976262Sgreen
91076262Sgreen/* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer
91176262Sgreen   to a previously-created save area.  If no save area has been allocated,
91276262Sgreen   this function will allocate one.  If a save area is specified, it
91376262Sgreen   must be of the proper mode.
91476262Sgreen
91576262Sgreen   The insns are emitted after insn AFTER, if nonzero, otherwise the insns
91676262Sgreen   are emitted at the current position.  */
91776262Sgreen
91876262Sgreenvoid
91976262Sgreenemit_stack_save (enum save_level save_level, rtx *psave, rtx after)
92076262Sgreen{
92176262Sgreen  rtx sa = *psave;
92276262Sgreen  /* The default is that we use a move insn and save in a Pmode object.  */
92376262Sgreen  rtx (*fcn) (rtx, rtx) = gen_move_insn;
92476262Sgreen  enum machine_mode mode = STACK_SAVEAREA_MODE (save_level);
92576262Sgreen
92676262Sgreen  /* See if this machine has anything special to do for this kind of save.  */
92776262Sgreen  switch (save_level)
92876262Sgreen    {
92976262Sgreen#ifdef HAVE_save_stack_block
93076262Sgreen    case SAVE_BLOCK:
93176262Sgreen      if (HAVE_save_stack_block)
93276262Sgreen	fcn = gen_save_stack_block;
93376262Sgreen      break;
93476262Sgreen#endif
93576262Sgreen#ifdef HAVE_save_stack_function
93676262Sgreen    case SAVE_FUNCTION:
93776262Sgreen      if (HAVE_save_stack_function)
93876262Sgreen	fcn = gen_save_stack_function;
93976262Sgreen      break;
94092559Sdes#endif
941124207Sdes#ifdef HAVE_save_stack_nonlocal
94276262Sgreen    case SAVE_NONLOCAL:
94376262Sgreen      if (HAVE_save_stack_nonlocal)
94476262Sgreen	fcn = gen_save_stack_nonlocal;
94576262Sgreen      break;
94676262Sgreen#endif
94776262Sgreen    default:
94876262Sgreen      break;
94976262Sgreen    }
95076262Sgreen
95176262Sgreen  /* If there is no save area and we have to allocate one, do so.  Otherwise
95276262Sgreen     verify the save area is the proper mode.  */
95376262Sgreen
95476262Sgreen  if (sa == 0)
95576262Sgreen    {
95676262Sgreen      if (mode != VOIDmode)
957124207Sdes	{
958124207Sdes	  if (save_level == SAVE_NONLOCAL)
959124207Sdes	    *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
960124207Sdes	  else
961124207Sdes	    *psave = sa = gen_reg_rtx (mode);
962124207Sdes	}
963124207Sdes    }
964124207Sdes
965124207Sdes  if (after)
966124207Sdes    {
967124207Sdes      rtx seq;
968124207Sdes
969124207Sdes      start_sequence ();
970124207Sdes      do_pending_stack_adjust ();
971124207Sdes      /* We must validize inside the sequence, to ensure that any instructions
972124207Sdes	 created by the validize call also get moved to the right place.  */
973124207Sdes      if (sa != 0)
974124207Sdes	sa = validize_mem (sa);
975124207Sdes      emit_insn (fcn (sa, stack_pointer_rtx));
976124207Sdes      seq = get_insns ();
977124207Sdes      end_sequence ();
978124207Sdes      emit_insn_after (seq, after);
979124207Sdes    }
980124207Sdes  else
981124207Sdes    {
982124207Sdes      do_pending_stack_adjust ();
983124207Sdes      if (sa != 0)
984124207Sdes	sa = validize_mem (sa);
985124207Sdes      emit_insn (fcn (sa, stack_pointer_rtx));
986126273Sdes    }
987124207Sdes}
988124207Sdes
989124207Sdes/* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save
990124207Sdes   area made by emit_stack_save.  If it is zero, we have nothing to do.
991124207Sdes
992124207Sdes   Put any emitted insns after insn AFTER, if nonzero, otherwise at
993124207Sdes   current position.  */
994124207Sdes
995124207Sdesvoid
996124207Sdesemit_stack_restore (enum save_level save_level, rtx sa, rtx after)
997124207Sdes{
998124207Sdes  /* The default is that we use a move insn.  */
999124207Sdes  rtx (*fcn) (rtx, rtx) = gen_move_insn;
1000124207Sdes
1001124207Sdes  /* See if this machine has anything special to do for this kind of save.  */
1002124207Sdes  switch (save_level)
1003124207Sdes    {
1004124207Sdes#ifdef HAVE_restore_stack_block
1005124207Sdes    case SAVE_BLOCK:
1006124207Sdes      if (HAVE_restore_stack_block)
1007124207Sdes	fcn = gen_restore_stack_block;
1008124207Sdes      break;
1009124207Sdes#endif
1010124207Sdes#ifdef HAVE_restore_stack_function
1011124207Sdes    case SAVE_FUNCTION:
1012124207Sdes      if (HAVE_restore_stack_function)
1013124207Sdes	fcn = gen_restore_stack_function;
1014124207Sdes      break;
1015124207Sdes#endif
1016124207Sdes#ifdef HAVE_restore_stack_nonlocal
1017124207Sdes    case SAVE_NONLOCAL:
1018124207Sdes      if (HAVE_restore_stack_nonlocal)
1019124207Sdes	fcn = gen_restore_stack_nonlocal;
1020124207Sdes      break;
1021124207Sdes#endif
1022124207Sdes    default:
1023124207Sdes      break;
1024124207Sdes    }
1025124207Sdes
1026124207Sdes  if (sa != 0)
1027124207Sdes    {
1028124207Sdes      sa = validize_mem (sa);
1029124207Sdes      /* These clobbers prevent the scheduler from moving
1030124207Sdes	 references to variable arrays below the code
1031124207Sdes	 that deletes (pops) the arrays.  */
1032124207Sdes      emit_insn (gen_rtx_CLOBBER (VOIDmode,
1033124207Sdes		    gen_rtx_MEM (BLKmode,
1034124207Sdes			gen_rtx_SCRATCH (VOIDmode))));
1035124207Sdes      emit_insn (gen_rtx_CLOBBER (VOIDmode,
1036124207Sdes		    gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
1037124207Sdes    }
1038124207Sdes
1039124207Sdes  discard_pending_stack_adjust ();
1040124207Sdes
1041124207Sdes  if (after)
1042124207Sdes    {
1043124207Sdes      rtx seq;
1044124207Sdes
1045124207Sdes      start_sequence ();
1046124207Sdes      emit_insn (fcn (stack_pointer_rtx, sa));
1047137019Sdes      seq = get_insns ();
1048124207Sdes      end_sequence ();
1049124207Sdes      emit_insn_after (seq, after);
1050124207Sdes    }
1051126273Sdes  else
1052124207Sdes    emit_insn (fcn (stack_pointer_rtx, sa));
1053124207Sdes}
1054124207Sdes
1055124207Sdes/* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
1056124207Sdes   function.  This function should be called whenever we allocate or
1057124207Sdes   deallocate dynamic stack space.  */
1058124207Sdes
1059124207Sdesvoid
1060124207Sdesupdate_nonlocal_goto_save_area (void)
1061124207Sdes{
1062124207Sdes  tree t_save;
1063124207Sdes  rtx r_save;
1064124207Sdes
1065124207Sdes  /* The nonlocal_goto_save_area object is an array of N pointers.  The
1066124207Sdes     first one is used for the frame pointer save; the rest are sized by
1067124207Sdes     STACK_SAVEAREA_MODE.  Create a reference to array index 1, the first
106876262Sgreen     of the stack save area slots.  */
106992559Sdes  t_save = build4 (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
107076262Sgreen		   integer_one_node, NULL_TREE, NULL_TREE);
107176262Sgreen  r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
107276262Sgreen
107376262Sgreen  emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
107476262Sgreen}
107576262Sgreen
107692559Sdes/* Return an rtx representing the address of an area of memory dynamically
107776262Sgreen   pushed on the stack.  This region of memory is always aligned to
107876262Sgreen   a multiple of BIGGEST_ALIGNMENT.
107976262Sgreen
1080124207Sdes   Any required stack pointer alignment is preserved.
108176262Sgreen
108276262Sgreen   SIZE is an rtx representing the size of the area.
108376262Sgreen   TARGET is a place in which the address can be placed.
108476262Sgreen
108576262Sgreen   KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
108676262Sgreen
108776262Sgreenrtx
108876262Sgreenallocate_dynamic_stack_space (rtx size, rtx target, int known_align)
108976262Sgreen{
109076262Sgreen  /* If we're asking for zero bytes, it doesn't matter what we point
1091124207Sdes     to since we can't dereference it.  But return a reasonable
1092124207Sdes     address anyway.  */
1093124207Sdes  if (size == const0_rtx)
109476262Sgreen    return virtual_stack_dynamic_rtx;
109576262Sgreen
109676262Sgreen  /* Otherwise, show we're calling alloca or equivalent.  */
109776262Sgreen  current_function_calls_alloca = 1;
109876262Sgreen
109992559Sdes  /* Ensure the size is in the proper mode.  */
110076262Sgreen  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
110176262Sgreen    size = convert_to_mode (Pmode, size, 1);
110276262Sgreen
110376262Sgreen  /* We can't attempt to minimize alignment necessary, because we don't
110476262Sgreen     know the final value of preferred_stack_boundary yet while executing
110576262Sgreen     this code.  */
110676262Sgreen  cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
110776262Sgreen
110876262Sgreen  /* We will need to ensure that the address we return is aligned to
110976262Sgreen     BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
111076262Sgreen     always know its final value at this point in the compilation (it
111160573Skris     might depend on the size of the outgoing parameter lists, for
111292559Sdes     example), so we must align the value to be returned in that case.
111360573Skris     (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if
111460573Skris     STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
111592559Sdes     We must also do an alignment operation on the returned value if
111660573Skris     the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
111792559Sdes
111860573Skris     If we have to align, we must leave space in SIZE for the hole
111976262Sgreen     that might result from the alignment operation.  */
112060573Skris
112157429Smarkm#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
112260573Skris#define MUST_ALIGN 1
112360573Skris#else
112460573Skris#define MUST_ALIGN (PREFERRED_STACK_BOUNDARY < BIGGEST_ALIGNMENT)
112560573Skris#endif
112692559Sdes
1127124207Sdes  if (MUST_ALIGN)
112892559Sdes    size
112992559Sdes      = force_operand (plus_constant (size,
113092559Sdes				      BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
113160573Skris		       NULL_RTX);
113260573Skris
113360573Skris#ifdef SETJMP_VIA_SAVE_AREA
113460573Skris  /* If setjmp restores regs from a save area in the stack frame,
113592559Sdes     avoid clobbering the reg save area.  Note that the offset of
113676262Sgreen     virtual_incoming_args_rtx includes the preallocated stack args space.
113760573Skris     It would be no problem to clobber that, but it's on the wrong side
113860573Skris     of the old save area.
113976262Sgreen
114057429Smarkm     What used to happen is that, since we did not know for sure
114192559Sdes     whether setjmp() was invoked until after RTL generation, we
114260573Skris     would use reg notes to store the "optimized" size and fix things
1143124207Sdes     up later.  These days we know this information before we ever
114460573Skris     start building RTL so the reg notes are unnecessary.  */
114560573Skris  if (!current_function_calls_setjmp)
114660573Skris    {
114792559Sdes      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
114892559Sdes
114992559Sdes      /* ??? Code below assumes that the save area needs maximal
115076262Sgreen	 alignment.  This constraint may be too strong.  */
115176262Sgreen      gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
115260573Skris
1153124207Sdes      if (GET_CODE (size) == CONST_INT)
115457429Smarkm	{
115560573Skris	  HOST_WIDE_INT new = INTVAL (size) / align * align;
115657429Smarkm
115760573Skris	  if (INTVAL (size) != new)
115860573Skris	    size = GEN_INT (new);
115960573Skris	}
116092559Sdes      else
116192559Sdes	{
116292559Sdes	  /* Since we know overflow is not possible, we avoid using
116392559Sdes	     CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead.  */
116460573Skris	  size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
116557429Smarkm				GEN_INT (align), NULL_RTX, 1);
116676262Sgreen	  size = expand_mult (Pmode, size,
116757429Smarkm			      GEN_INT (align), NULL_RTX, 1);
116857429Smarkm	}
116957429Smarkm    }
117092559Sdes  else
117176262Sgreen    {
117276262Sgreen      rtx dynamic_offset
117376262Sgreen	= expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
117476262Sgreen			stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
117576262Sgreen
117676262Sgreen      size = expand_binop (Pmode, add_optab, size, dynamic_offset,
117776262Sgreen			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
117876262Sgreen    }
117976262Sgreen#endif /* SETJMP_VIA_SAVE_AREA */
118076262Sgreen
118176262Sgreen  /* Round the size to a multiple of the required stack alignment.
118276262Sgreen     Since the stack if presumed to be rounded before this allocation,
118376262Sgreen     this will maintain the required alignment.
118476262Sgreen
118576262Sgreen     If the stack grows downward, we could save an insn by subtracting
118676262Sgreen     SIZE from the stack pointer and then aligning the stack pointer.
118776262Sgreen     The problem with this is that the stack pointer may be unaligned
118876262Sgreen     between the execution of the subtraction and alignment insns and
118976262Sgreen     some machines do not allow this.  Even on those that do, some
119076262Sgreen     signal handlers malfunction if a signal should occur between those
119176262Sgreen     insns.  Since this is an extremely rare event, we have no reliable
119276262Sgreen     way of knowing which systems have this problem.  So we avoid even
119376262Sgreen     momentarily mis-aligning the stack.  */
119476262Sgreen
119576262Sgreen  /* If we added a variable amount to SIZE,
119676262Sgreen     we can no longer assume it is aligned.  */
119776262Sgreen#if !defined (SETJMP_VIA_SAVE_AREA)
119876262Sgreen  if (MUST_ALIGN || known_align % PREFERRED_STACK_BOUNDARY != 0)
119976262Sgreen#endif
120076262Sgreen    size = round_push (size);
120176262Sgreen
120276262Sgreen  do_pending_stack_adjust ();
120376262Sgreen
120476262Sgreen /* We ought to be called always on the toplevel and stack ought to be aligned
120576262Sgreen    properly.  */
120676262Sgreen  gcc_assert (!(stack_pointer_delta
120776262Sgreen		% (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
120876262Sgreen
120976262Sgreen  /* If needed, check that we have the required amount of stack.  Take into
121076262Sgreen     account what has already been checked.  */
121176262Sgreen  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
121276262Sgreen    probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
121392559Sdes
121492559Sdes  /* Don't use a TARGET that isn't a pseudo or is the wrong mode.  */
121576262Sgreen  if (target == 0 || !REG_P (target)
121676262Sgreen      || REGNO (target) < FIRST_PSEUDO_REGISTER
121776262Sgreen      || GET_MODE (target) != Pmode)
121876262Sgreen    target = gen_reg_rtx (Pmode);
121976262Sgreen
122076262Sgreen  mark_reg_pointer (target, known_align);
122157429Smarkm
122260573Skris  /* Perform the required allocation from the stack.  Some systems do
122357429Smarkm     this differently than simply incrementing/decrementing from the
122492559Sdes     stack pointer, such as acquiring the space by calling malloc().  */
122560573Skris#ifdef HAVE_allocate_stack
122657429Smarkm  if (HAVE_allocate_stack)
122776262Sgreen    {
122857429Smarkm      enum machine_mode mode = STACK_SIZE_MODE;
122992559Sdes      insn_operand_predicate_fn pred;
123057429Smarkm
123176262Sgreen      /* We don't have to check against the predicate for operand 0 since
123257429Smarkm	 TARGET is known to be a pseudo of the proper mode, which must
123360573Skris	 be valid for the operand.  For operand 1, convert to the
123460573Skris	 proper mode and validate.  */
123560573Skris      if (mode == VOIDmode)
123660573Skris	mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode;
123776262Sgreen
123892559Sdes      pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
123992559Sdes      if (pred && ! ((*pred) (size, mode)))
124092559Sdes	size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
124192559Sdes
124292559Sdes      emit_insn (gen_allocate_stack (target, size));
124392559Sdes    }
124492559Sdes  else
124592559Sdes#endif
124692559Sdes    {
124792559Sdes#ifndef STACK_GROWS_DOWNWARD
124892559Sdes      emit_move_insn (target, virtual_stack_dynamic_rtx);
124992559Sdes#endif
125076262Sgreen
125160573Skris      /* Check stack bounds if necessary.  */
125260573Skris      if (current_function_limit_stack)
125360573Skris	{
125460573Skris	  rtx available;
125560573Skris	  rtx space_available = gen_label_rtx ();
125660573Skris#ifdef STACK_GROWS_DOWNWARD
125792559Sdes	  available = expand_binop (Pmode, sub_optab,
1258124207Sdes				    stack_pointer_rtx, stack_limit_rtx,
1259124207Sdes				    NULL_RTX, 1, OPTAB_WIDEN);
126076262Sgreen#else
126176262Sgreen	  available = expand_binop (Pmode, sub_optab,
126276262Sgreen				    stack_limit_rtx, stack_pointer_rtx,
126376262Sgreen				    NULL_RTX, 1, OPTAB_WIDEN);
126492559Sdes#endif
126592559Sdes	  emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
126692559Sdes				   space_available);
126792559Sdes#ifdef HAVE_trap
126892559Sdes	  if (HAVE_trap)
126992559Sdes	    emit_insn (gen_trap ());
127092559Sdes	  else
127192559Sdes#endif
127276262Sgreen	    error ("stack limits not supported on this target");
127392559Sdes	  emit_barrier ();
127460573Skris	  emit_label (space_available);
127560573Skris	}
127657429Smarkm
127760573Skris      anti_adjust_stack (size);
127860573Skris
127960573Skris#ifdef STACK_GROWS_DOWNWARD
128060573Skris      emit_move_insn (target, virtual_stack_dynamic_rtx);
128192559Sdes#endif
128260573Skris    }
128360573Skris
128492559Sdes  if (MUST_ALIGN)
128592559Sdes    {
128660573Skris      /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
128760573Skris	 but we know it can't.  So add ourselves and then do
128857429Smarkm	 TRUNC_DIV_EXPR.  */
128960573Skris      target = expand_binop (Pmode, add_optab, target,
129060573Skris			     GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
129160573Skris			     NULL_RTX, 1, OPTAB_LIB_WIDEN);
129260573Skris      target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
129360573Skris			      GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
129460573Skris			      NULL_RTX, 1);
129560573Skris      target = expand_mult (Pmode, target,
129692559Sdes			    GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
129776262Sgreen			    NULL_RTX, 1);
129876262Sgreen    }
1299124207Sdes
130076262Sgreen  /* Record the new stack level for nonlocal gotos.  */
130176262Sgreen  if (cfun->nonlocal_goto_save_area != 0)
130276262Sgreen    update_nonlocal_goto_save_area ();
130392559Sdes
130476262Sgreen  return target;
130576262Sgreen}
130676262Sgreen
130776262Sgreen/* A front end may want to override GCC's stack checking by providing a
130892559Sdes   run-time routine to call to check the stack, so provide a mechanism for
130976262Sgreen   calling that routine.  */
131060573Skris
131160573Skrisstatic GTY(()) rtx stack_check_libfunc;
131260573Skris
131357429Smarkmvoid
131492559Sdesset_stack_check_libfunc (rtx libfunc)
131576262Sgreen{
131676262Sgreen  stack_check_libfunc = libfunc;
131792559Sdes}
131892559Sdes
131992559Sdes/* Emit one stack probe at ADDRESS, an address within the stack.  */
132076262Sgreen
132192559Sdesstatic void
132292559Sdesemit_stack_probe (rtx address)
132392559Sdes{
132492559Sdes  rtx memref = gen_rtx_MEM (word_mode, address);
132592559Sdes
132692559Sdes  MEM_VOLATILE_P (memref) = 1;
132792559Sdes
132892559Sdes  if (STACK_CHECK_PROBE_LOAD)
132992559Sdes    emit_move_insn (gen_reg_rtx (word_mode), memref);
133092559Sdes  else
133192559Sdes    emit_move_insn (memref, const0_rtx);
133292559Sdes}
133392559Sdes
133492559Sdes/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
133592559Sdes   FIRST is a constant and size is a Pmode RTX.  These are offsets from the
133692559Sdes   current stack pointer.  STACK_GROWS_DOWNWARD says whether to add or
133792559Sdes   subtract from the stack.  If SIZE is constant, this is done
133892559Sdes   with a fixed number of probes.  Otherwise, we must make a loop.  */
133976262Sgreen
134092559Sdes#ifdef STACK_GROWS_DOWNWARD
134192559Sdes#define STACK_GROW_OP MINUS
134292559Sdes#else
134392559Sdes#define STACK_GROW_OP PLUS
134492559Sdes#endif
134592559Sdes
134692559Sdesvoid
134792559Sdesprobe_stack_range (HOST_WIDE_INT first, rtx size)
134892559Sdes{
134992559Sdes  /* First ensure SIZE is Pmode.  */
135076262Sgreen  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
135192559Sdes    size = convert_to_mode (Pmode, size, 1);
135292559Sdes
135376262Sgreen  /* Next see if the front end has set up a function for us to call to
135492559Sdes     check the stack.  */
135576262Sgreen  if (stack_check_libfunc != 0)
135692559Sdes    {
135776262Sgreen      rtx addr = memory_address (QImode,
135876262Sgreen				 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
135976262Sgreen					         stack_pointer_rtx,
136092559Sdes					         plus_constant (size, first)));
136160573Skris
136260573Skris      addr = convert_memory_address (ptr_mode, addr);
136360573Skris      emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
136460573Skris			 ptr_mode);
136557429Smarkm    }
136660573Skris
136760573Skris  /* Next see if we have an insn to check the stack.  Use it if so.  */
136860573Skris#ifdef HAVE_check_stack
136960573Skris  else if (HAVE_check_stack)
137060573Skris    {
137178827Sgreen      insn_operand_predicate_fn pred;
1372124207Sdes      rtx last_addr
137360573Skris	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
137476262Sgreen					 stack_pointer_rtx,
1375124207Sdes					 plus_constant (size, first)),
137692559Sdes			 NULL_RTX);
137776262Sgreen
137876262Sgreen      pred = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
137992559Sdes      if (pred && ! ((*pred) (last_addr, Pmode)))
138060573Skris	last_addr = copy_to_mode_reg (Pmode, last_addr);
1381124207Sdes
138260573Skris      emit_insn (gen_check_stack (last_addr));
138360573Skris    }
138457429Smarkm#endif
138560573Skris
138660573Skris  /* If we have to generate explicit probes, see if we have a constant
138792559Sdes     small number of them to generate.  If so, that's the easy case.  */
138865668Skris  else if (GET_CODE (size) == CONST_INT
1389124207Sdes	   && INTVAL (size) < 10 * STACK_CHECK_PROBE_INTERVAL)
139065668Skris    {
139165668Skris      HOST_WIDE_INT offset;
139265668Skris
139365668Skris      /* Start probing at FIRST + N * STACK_CHECK_PROBE_INTERVAL
139465668Skris	 for values of N from 1 until it exceeds LAST.  If only one
139560573Skris	 probe is needed, this will not generate any code.  Then probe
139660573Skris	 at LAST.  */
139760573Skris      for (offset = first + STACK_CHECK_PROBE_INTERVAL;
139892559Sdes	   offset < INTVAL (size);
139960573Skris	   offset = offset + STACK_CHECK_PROBE_INTERVAL)
140060573Skris	emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
140176262Sgreen					  stack_pointer_rtx,
140292559Sdes					  GEN_INT (offset)));
140392559Sdes
140460573Skris      emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
140560573Skris					stack_pointer_rtx,
140660573Skris					plus_constant (size, first)));
140760573Skris    }
140860573Skris
140960573Skris  /* In the variable case, do the same as above, but in a loop.  We emit loop
141092559Sdes     notes so that loop optimization can be done.  */
141192559Sdes  else
1412106130Sdes    {
1413126273Sdes      rtx test_addr
1414126273Sdes	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
1415126273Sdes					 stack_pointer_rtx,
1416106130Sdes					 GEN_INT (first + STACK_CHECK_PROBE_INTERVAL)),
141792559Sdes			 NULL_RTX);
141860573Skris      rtx last_addr
141960573Skris	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
142060573Skris					 stack_pointer_rtx,
142176262Sgreen					 plus_constant (size, first)),
1422124207Sdes			 NULL_RTX);
142392559Sdes      rtx incr = GEN_INT (STACK_CHECK_PROBE_INTERVAL);
142476262Sgreen      rtx loop_lab = gen_label_rtx ();
142576262Sgreen      rtx test_lab = gen_label_rtx ();
142692559Sdes      rtx end_lab = gen_label_rtx ();
1427124207Sdes      rtx temp;
142860573Skris
142960573Skris      if (!REG_P (test_addr)
143060573Skris	  || REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
143157429Smarkm	test_addr = force_reg (Pmode, test_addr);
143260573Skris
143360573Skris      emit_jump (test_lab);
143492559Sdes
143574500Sgreen      emit_label (loop_lab);
143674500Sgreen      emit_stack_probe (test_addr);
143774500Sgreen
143874500Sgreen#ifdef STACK_GROWS_DOWNWARD
143976262Sgreen#define CMP_OPCODE GTU
144076262Sgreen      temp = expand_binop (Pmode, sub_optab, test_addr, incr, test_addr,
144176262Sgreen			   1, OPTAB_WIDEN);
144274500Sgreen#else
144376262Sgreen#define CMP_OPCODE LTU
144474500Sgreen      temp = expand_binop (Pmode, add_optab, test_addr, incr, test_addr,
144574500Sgreen			   1, OPTAB_WIDEN);
144674500Sgreen#endif
144760573Skris
144860573Skris      gcc_assert (temp == test_addr);
144960573Skris
145060573Skris      emit_label (test_lab);
145160573Skris      emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
145260573Skris			       NULL_RTX, Pmode, 1, loop_lab);
145360573Skris      emit_jump (end_lab);
145492559Sdes      emit_label (end_lab);
145560573Skris
145660573Skris      emit_stack_probe (last_addr);
145760573Skris    }
145860573Skris}
145957429Smarkm
146060573Skris/* Return an rtx representing the register or memory location
146160573Skris   in which a scalar value of data type VALTYPE
146260573Skris   was returned by a function call to function FUNC.
146360573Skris   FUNC is a FUNCTION_DECL, FNTYPE a FUNCTION_TYPE node if the precise
146460573Skris   function is known, otherwise 0.
146560573Skris   OUTGOING is 1 if on a machine with register windows this function
146660573Skris   should return the register in which the function will put its result
146769587Sgreen   and 0 otherwise.  */
146860573Skris
146976262Sgreenrtx
147076262Sgreenhard_function_value (tree valtype, tree func, tree fntype,
147176262Sgreen		     int outgoing ATTRIBUTE_UNUSED)
147276262Sgreen{
147376262Sgreen  rtx val;
147492559Sdes
147576262Sgreen  val = targetm.calls.function_value (valtype, func ? func : fntype, outgoing);
147660573Skris
147760573Skris  if (REG_P (val)
147857429Smarkm      && GET_MODE (val) == BLKmode)
147960573Skris    {
148060573Skris      unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype);
148160573Skris      enum machine_mode tmpmode;
148269587Sgreen
148392559Sdes      /* int_size_in_bytes can return -1.  We don't need a check here
148476262Sgreen	 since the value of bytes will then be large enough that no
148576262Sgreen	 mode will match anyway.  */
148676262Sgreen
148776262Sgreen      for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
148860573Skris	   tmpmode != VOIDmode;
148992559Sdes	   tmpmode = GET_MODE_WIDER_MODE (tmpmode))
149076262Sgreen	{
149160573Skris	  /* Have we found a large enough mode?  */
149276262Sgreen	  if (GET_MODE_SIZE (tmpmode) >= bytes)
149360573Skris	    break;
149460573Skris	}
149560573Skris
149660573Skris      /* No suitable mode found.  */
149792559Sdes      gcc_assert (tmpmode != VOIDmode);
1498137019Sdes
1499137019Sdes      PUT_MODE (val, tmpmode);
1500137019Sdes    }
1501137019Sdes  return val;
1502137019Sdes}
1503137019Sdes
1504137019Sdes/* Return an rtx representing the register or memory location
1505137019Sdes   in which a scalar value of mode MODE was returned by a library call.  */
1506137019Sdes
1507137019Sdesrtx
1508137019Sdeshard_libcall_value (enum machine_mode mode)
1509137019Sdes{
1510137019Sdes  return LIBCALL_VALUE (mode);
1511137019Sdes}
1512137019Sdes
1513137019Sdes/* Look up the tree code for a given rtx code
1514137019Sdes   to provide the arithmetic operation for REAL_ARITHMETIC.
1515137019Sdes   The function returns an int because the caller may not know
1516137019Sdes   what `enum tree_code' means.  */
1517137019Sdes
1518137019Sdesint
1519137019Sdesrtx_to_tree_code (enum rtx_code code)
1520137019Sdes{
1521137019Sdes  enum tree_code tcode;
1522137019Sdes
1523137019Sdes  switch (code)
1524137019Sdes    {
152576262Sgreen    case PLUS:
152660573Skris      tcode = PLUS_EXPR;
152776262Sgreen      break;
152876262Sgreen    case MINUS:
152960573Skris      tcode = MINUS_EXPR;
153060573Skris      break;
153160573Skris    case MULT:
153260573Skris      tcode = MULT_EXPR;
153360573Skris      break;
153460573Skris    case DIV:
153569587Sgreen      tcode = RDIV_EXPR;
153660573Skris      break;
153760573Skris    case SMIN:
153860573Skris      tcode = MIN_EXPR;
153960573Skris      break;
154060573Skris    case SMAX:
154160573Skris      tcode = MAX_EXPR;
154260573Skris      break;
154357429Smarkm    default:
154492559Sdes      tcode = LAST_AND_UNUSED_TREE_CODE;
154592559Sdes      break;
154660573Skris    }
154792559Sdes  return ((int) tcode);
154892559Sdes}
154960573Skris
155060573Skris#include "gt-explow.h"
155192559Sdes