190075Sobrien/* Procedure integration for GCC.
2132718Skan   Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3169689Skan   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
418334Speter   Contributed by Michael Tiemann (tiemann@cygnus.com)
518334Speter
690075SobrienThis file is part of GCC.
718334Speter
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1218334Speter
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2218334Speter
2350397Sobrien#include "config.h"
2450397Sobrien#include "system.h"
25132718Skan#include "coretypes.h"
26132718Skan#include "tm.h"
2718334Speter
2818334Speter#include "rtl.h"
2918334Speter#include "tree.h"
3090075Sobrien#include "tm_p.h"
3150397Sobrien#include "regs.h"
3218334Speter#include "flags.h"
3390075Sobrien#include "debug.h"
3418334Speter#include "insn-config.h"
3518334Speter#include "expr.h"
3618334Speter#include "output.h"
3750397Sobrien#include "recog.h"
3818334Speter#include "integrate.h"
3918334Speter#include "real.h"
4050397Sobrien#include "except.h"
4118334Speter#include "function.h"
4250397Sobrien#include "toplev.h"
4352284Sobrien#include "intl.h"
4490075Sobrien#include "params.h"
4590075Sobrien#include "ggc.h"
4690075Sobrien#include "target.h"
47117395Skan#include "langhooks.h"
48169689Skan#include "tree-pass.h"
4918334Speter
50169689Skan/* Round to the next highest integer that meets the alignment.  */
5118334Speter#define CEIL_ROUND(VALUE,ALIGN)	(((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
5218334Speter
5318334Speter
54169689Skan/* Private type used by {get/has}_hard_reg_initial_val.  */
55117395Skantypedef struct initial_value_pair GTY(()) {
5690075Sobrien  rtx hard_reg;
5790075Sobrien  rtx pseudo;
5890075Sobrien} initial_value_pair;
59117395Skantypedef struct initial_value_struct GTY(()) {
6090075Sobrien  int num_entries;
6190075Sobrien  int max_entries;
62117395Skan  initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
6390075Sobrien} initial_value_struct;
6452284Sobrien
65132718Skanstatic void set_block_origin_self (tree);
66132718Skanstatic void set_block_abstract_flags (tree, int);
6718334Speter
6850397Sobrien
6990075Sobrien/* Return false if the function FNDECL cannot be inlined on account of its
7090075Sobrien   attributes, true otherwise.  */
7190075Sobrienbool
72132718Skanfunction_attribute_inlinable_p (tree fndecl)
7390075Sobrien{
74117395Skan  if (targetm.attribute_table)
7590075Sobrien    {
76117395Skan      tree a;
7790075Sobrien
78117395Skan      for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
7990075Sobrien	{
80117395Skan	  tree name = TREE_PURPOSE (a);
81117395Skan	  int i;
82117395Skan
83117395Skan	  for (i = 0; targetm.attribute_table[i].name != NULL; i++)
84117395Skan	    if (is_attribute_p (targetm.attribute_table[i].name, name))
85169689Skan	      return targetm.function_attribute_inlinable_p (fndecl);
8690075Sobrien	}
8790075Sobrien    }
8890075Sobrien
89117395Skan  return true;
9090075Sobrien}
9118334Speter
9218334Speter/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
9318334Speter   given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
9418334Speter   that it points to the node itself, thus indicating that the node is its
9518334Speter   own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
9618334Speter   the given node is NULL, recursively descend the decl/block tree which
9718334Speter   it is the root of, and for each other ..._DECL or BLOCK node contained
9818334Speter   therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
9918334Speter   still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
10018334Speter   values to point to themselves.  */
10118334Speter
10218334Speterstatic void
103132718Skanset_block_origin_self (tree stmt)
10418334Speter{
10518334Speter  if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
10618334Speter    {
10718334Speter      BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
10818334Speter
10918334Speter      {
11090075Sobrien	tree local_decl;
11118334Speter
11290075Sobrien	for (local_decl = BLOCK_VARS (stmt);
11318334Speter	     local_decl != NULL_TREE;
11418334Speter	     local_decl = TREE_CHAIN (local_decl))
11590075Sobrien	  set_decl_origin_self (local_decl);	/* Potential recursion.  */
11618334Speter      }
11718334Speter
11818334Speter      {
11990075Sobrien	tree subblock;
12018334Speter
12190075Sobrien	for (subblock = BLOCK_SUBBLOCKS (stmt);
12218334Speter	     subblock != NULL_TREE;
12318334Speter	     subblock = BLOCK_CHAIN (subblock))
12490075Sobrien	  set_block_origin_self (subblock);	/* Recurse.  */
12518334Speter      }
12618334Speter    }
12718334Speter}
12818334Speter
12918334Speter/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
13018334Speter   the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
13118334Speter   node to so that it points to the node itself, thus indicating that the
13218334Speter   node represents its own (abstract) origin.  Additionally, if the
13318334Speter   DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
13418334Speter   the decl/block tree of which the given node is the root of, and for
13518334Speter   each other ..._DECL or BLOCK node contained therein whose
13618334Speter   DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
13718334Speter   set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
13818334Speter   point to themselves.  */
13918334Speter
14090075Sobrienvoid
141132718Skanset_decl_origin_self (tree decl)
14218334Speter{
14318334Speter  if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
14418334Speter    {
14518334Speter      DECL_ABSTRACT_ORIGIN (decl) = decl;
14618334Speter      if (TREE_CODE (decl) == FUNCTION_DECL)
14718334Speter	{
14890075Sobrien	  tree arg;
14918334Speter
15018334Speter	  for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
15118334Speter	    DECL_ABSTRACT_ORIGIN (arg) = arg;
15218334Speter	  if (DECL_INITIAL (decl) != NULL_TREE
15318334Speter	      && DECL_INITIAL (decl) != error_mark_node)
15418334Speter	    set_block_origin_self (DECL_INITIAL (decl));
15518334Speter	}
15618334Speter    }
15718334Speter}
15818334Speter
15918334Speter/* Given a pointer to some BLOCK node, and a boolean value to set the
16018334Speter   "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
16118334Speter   the given block, and for all local decls and all local sub-blocks
16218334Speter   (recursively) which are contained therein.  */
16318334Speter
16418334Speterstatic void
165132718Skanset_block_abstract_flags (tree stmt, int setting)
16618334Speter{
16790075Sobrien  tree local_decl;
16890075Sobrien  tree subblock;
16950397Sobrien
17018334Speter  BLOCK_ABSTRACT (stmt) = setting;
17118334Speter
17250397Sobrien  for (local_decl = BLOCK_VARS (stmt);
17350397Sobrien       local_decl != NULL_TREE;
17450397Sobrien       local_decl = TREE_CHAIN (local_decl))
17550397Sobrien    set_decl_abstract_flags (local_decl, setting);
17618334Speter
17750397Sobrien  for (subblock = BLOCK_SUBBLOCKS (stmt);
17850397Sobrien       subblock != NULL_TREE;
17950397Sobrien       subblock = BLOCK_CHAIN (subblock))
18050397Sobrien    set_block_abstract_flags (subblock, setting);
18118334Speter}
18218334Speter
18318334Speter/* Given a pointer to some ..._DECL node, and a boolean value to set the
18418334Speter   "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
18518334Speter   given decl, and (in the case where the decl is a FUNCTION_DECL) also
18618334Speter   set the abstract flags for all of the parameters, local vars, local
18718334Speter   blocks and sub-blocks (recursively) to the same setting.  */
18818334Speter
18918334Spetervoid
190132718Skanset_decl_abstract_flags (tree decl, int setting)
19118334Speter{
19218334Speter  DECL_ABSTRACT (decl) = setting;
19318334Speter  if (TREE_CODE (decl) == FUNCTION_DECL)
19418334Speter    {
19590075Sobrien      tree arg;
19618334Speter
19718334Speter      for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
19818334Speter	DECL_ABSTRACT (arg) = setting;
19918334Speter      if (DECL_INITIAL (decl) != NULL_TREE
20018334Speter	  && DECL_INITIAL (decl) != error_mark_node)
20118334Speter	set_block_abstract_flags (DECL_INITIAL (decl), setting);
20218334Speter    }
20318334Speter}
20418334Speter
20590075Sobrien/* Functions to keep track of the values hard regs had at the start of
20690075Sobrien   the function.  */
20718334Speter
20890075Sobrienrtx
209132718Skanget_hard_reg_initial_reg (struct function *fun, rtx reg)
21090075Sobrien{
21190075Sobrien  struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
21290075Sobrien  int i;
21318334Speter
21490075Sobrien  if (ivs == 0)
21590075Sobrien    return NULL_RTX;
21618334Speter
21790075Sobrien  for (i = 0; i < ivs->num_entries; i++)
21890075Sobrien    if (rtx_equal_p (ivs->entries[i].pseudo, reg))
21990075Sobrien      return ivs->entries[i].hard_reg;
22018334Speter
22190075Sobrien  return NULL_RTX;
22290075Sobrien}
22318334Speter
224169689Skan/* Make sure that there's a pseudo register of mode MODE that stores the
225169689Skan   initial value of hard register REGNO.  Return an rtx for such a pseudo.  */
22618334Speter
22790075Sobrienrtx
228169689Skanget_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
22990075Sobrien{
230169689Skan  struct initial_value_struct *ivs;
231169689Skan  rtx rv;
23218334Speter
233169689Skan  rv = has_hard_reg_initial_val (mode, regno);
23490075Sobrien  if (rv)
23590075Sobrien    return rv;
23618334Speter
237169689Skan  ivs = cfun->hard_reg_initial_vals;
23890075Sobrien  if (ivs == 0)
23990075Sobrien    {
240169689Skan      ivs = ggc_alloc (sizeof (initial_value_struct));
24190075Sobrien      ivs->num_entries = 0;
24290075Sobrien      ivs->max_entries = 5;
243132718Skan      ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
244169689Skan      cfun->hard_reg_initial_vals = ivs;
24590075Sobrien    }
24618334Speter
24790075Sobrien  if (ivs->num_entries >= ivs->max_entries)
24818334Speter    {
24990075Sobrien      ivs->max_entries += 5;
250132718Skan      ivs->entries = ggc_realloc (ivs->entries,
251132718Skan				  ivs->max_entries
252132718Skan				  * sizeof (initial_value_pair));
25318334Speter    }
25418334Speter
255169689Skan  ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno);
256169689Skan  ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode);
25718334Speter
25890075Sobrien  return ivs->entries[ivs->num_entries++].pseudo;
25990075Sobrien}
26018334Speter
261169689Skan/* See if get_hard_reg_initial_val has been used to create a pseudo
262169689Skan   for the initial value of hard register REGNO in mode MODE.  Return
263169689Skan   the associated pseudo if so, otherwise return NULL.  */
26418334Speter
26590075Sobrienrtx
266169689Skanhas_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
26790075Sobrien{
268169689Skan  struct initial_value_struct *ivs;
26990075Sobrien  int i;
27090075Sobrien
271169689Skan  ivs = cfun->hard_reg_initial_vals;
272169689Skan  if (ivs != 0)
273169689Skan    for (i = 0; i < ivs->num_entries; i++)
274169689Skan      if (GET_MODE (ivs->entries[i].hard_reg) == mode
275169689Skan	  && REGNO (ivs->entries[i].hard_reg) == regno)
276169689Skan	return ivs->entries[i].pseudo;
27790075Sobrien
278169689Skan  return NULL_RTX;
27990075Sobrien}
28090075Sobrien
281169689Skanunsigned int
282132718Skanemit_initial_value_sets (void)
28390075Sobrien{
28490075Sobrien  struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
28590075Sobrien  int i;
28690075Sobrien  rtx seq;
28790075Sobrien
28890075Sobrien  if (ivs == 0)
289169689Skan    return 0;
29090075Sobrien
29190075Sobrien  start_sequence ();
29290075Sobrien  for (i = 0; i < ivs->num_entries; i++)
29390075Sobrien    emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
29490075Sobrien  seq = get_insns ();
29590075Sobrien  end_sequence ();
29690075Sobrien
297169689Skan  emit_insn_at_entry (seq);
298169689Skan  return 0;
29990075Sobrien}
30090075Sobrien
301169689Skanstruct tree_opt_pass pass_initial_value_sets =
302169689Skan{
303169689Skan  "initvals",                           /* name */
304169689Skan  NULL,                                 /* gate */
305169689Skan  emit_initial_value_sets,              /* execute */
306169689Skan  NULL,                                 /* sub */
307169689Skan  NULL,                                 /* next */
308169689Skan  0,                                    /* static_pass_number */
309169689Skan  0,                                    /* tv_id */
310169689Skan  0,                                    /* properties_required */
311169689Skan  0,                                    /* properties_provided */
312169689Skan  0,                                    /* properties_destroyed */
313169689Skan  0,                                    /* todo_flags_start */
314169689Skan  TODO_dump_func,                       /* todo_flags_finish */
315169689Skan  0                                     /* letter */
316169689Skan};
317169689Skan
31890075Sobrien/* If the backend knows where to allocate pseudos for hard
31990075Sobrien   register initial values, register these allocations now.  */
32090075Sobrienvoid
321132718Skanallocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED)
32290075Sobrien{
323169689Skan  if (targetm.allocate_initial_value)
324169689Skan    {
325169689Skan      struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
326169689Skan      int i;
32790075Sobrien
328169689Skan      if (ivs == 0)
329169689Skan	return;
33090075Sobrien
331169689Skan      for (i = 0; i < ivs->num_entries; i++)
332169689Skan	{
333169689Skan	  int regno = REGNO (ivs->entries[i].pseudo);
334169689Skan	  rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg);
335169689Skan
336169689Skan	  if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1)
337169689Skan	    {
338169689Skan	      if (MEM_P (x))
339169689Skan		reg_equiv_memory_loc[regno] = x;
340169689Skan	      else
341169689Skan		{
342169689Skan		  basic_block bb;
343169689Skan		  int new_regno;
34490075Sobrien
345169689Skan		  gcc_assert (REG_P (x));
346169689Skan		  new_regno = REGNO (x);
347169689Skan		  reg_renumber[regno] = new_regno;
348169689Skan		  /* Poke the regno right into regno_reg_rtx so that even
349169689Skan		     fixed regs are accepted.  */
350169689Skan		  REGNO (ivs->entries[i].pseudo) = new_regno;
351169689Skan		  /* Update global register liveness information.  */
352169689Skan		  FOR_EACH_BB (bb)
353169689Skan		    {
354169689Skan		      struct rtl_bb_info *info = bb->il.rtl;
355169689Skan
356169689Skan		      if (REGNO_REG_SET_P(info->global_live_at_start, regno))
357169689Skan			SET_REGNO_REG_SET (info->global_live_at_start,
358169689Skan					   new_regno);
359169689Skan		      if (REGNO_REG_SET_P(info->global_live_at_end, regno))
360169689Skan			SET_REGNO_REG_SET (info->global_live_at_end,
361169689Skan					   new_regno);
362169689Skan		    }
363169689Skan		}
364169689Skan	    }
36590075Sobrien	}
36690075Sobrien    }
36790075Sobrien}
368117395Skan
369117395Skan#include "gt-integrate.h"
370