1/* Procedure integration for GCC.
2   Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4   Contributed by Michael Tiemann (tiemann@cygnus.com)
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to the Free
20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2102110-1301, USA.  */
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tm.h"
27
28#include "rtl.h"
29#include "tree.h"
30#include "tm_p.h"
31#include "regs.h"
32#include "flags.h"
33#include "debug.h"
34#include "insn-config.h"
35#include "expr.h"
36#include "output.h"
37#include "recog.h"
38#include "integrate.h"
39#include "real.h"
40#include "except.h"
41#include "function.h"
42#include "toplev.h"
43#include "intl.h"
44#include "params.h"
45#include "ggc.h"
46#include "target.h"
47#include "langhooks.h"
48#include "tree-pass.h"
49
50/* Round to the next highest integer that meets the alignment.  */
51#define CEIL_ROUND(VALUE,ALIGN)	(((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
52
53
54/* Private type used by {get/has}_hard_reg_initial_val.  */
55typedef struct initial_value_pair GTY(()) {
56  rtx hard_reg;
57  rtx pseudo;
58} initial_value_pair;
59typedef struct initial_value_struct GTY(()) {
60  int num_entries;
61  int max_entries;
62  initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
63} initial_value_struct;
64
65static void set_block_origin_self (tree);
66static void set_block_abstract_flags (tree, int);
67
68
69/* Return false if the function FNDECL cannot be inlined on account of its
70   attributes, true otherwise.  */
71bool
72function_attribute_inlinable_p (tree fndecl)
73{
74  if (targetm.attribute_table)
75    {
76      tree a;
77
78      for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
79	{
80	  tree name = TREE_PURPOSE (a);
81	  int i;
82
83	  for (i = 0; targetm.attribute_table[i].name != NULL; i++)
84	    if (is_attribute_p (targetm.attribute_table[i].name, name))
85	      return targetm.function_attribute_inlinable_p (fndecl);
86	}
87    }
88
89  return true;
90}
91
92/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
93   given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
94   that it points to the node itself, thus indicating that the node is its
95   own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
96   the given node is NULL, recursively descend the decl/block tree which
97   it is the root of, and for each other ..._DECL or BLOCK node contained
98   therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
99   still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
100   values to point to themselves.  */
101
102static void
103set_block_origin_self (tree stmt)
104{
105  if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
106    {
107      BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
108
109      {
110	tree local_decl;
111
112	for (local_decl = BLOCK_VARS (stmt);
113	     local_decl != NULL_TREE;
114	     local_decl = TREE_CHAIN (local_decl))
115	  set_decl_origin_self (local_decl);	/* Potential recursion.  */
116      }
117
118      {
119	tree subblock;
120
121	for (subblock = BLOCK_SUBBLOCKS (stmt);
122	     subblock != NULL_TREE;
123	     subblock = BLOCK_CHAIN (subblock))
124	  set_block_origin_self (subblock);	/* Recurse.  */
125      }
126    }
127}
128
129/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
130   the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
131   node to so that it points to the node itself, thus indicating that the
132   node represents its own (abstract) origin.  Additionally, if the
133   DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
134   the decl/block tree of which the given node is the root of, and for
135   each other ..._DECL or BLOCK node contained therein whose
136   DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
137   set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
138   point to themselves.  */
139
140void
141set_decl_origin_self (tree decl)
142{
143  if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
144    {
145      DECL_ABSTRACT_ORIGIN (decl) = decl;
146      if (TREE_CODE (decl) == FUNCTION_DECL)
147	{
148	  tree arg;
149
150	  for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
151	    DECL_ABSTRACT_ORIGIN (arg) = arg;
152	  if (DECL_INITIAL (decl) != NULL_TREE
153	      && DECL_INITIAL (decl) != error_mark_node)
154	    set_block_origin_self (DECL_INITIAL (decl));
155	}
156    }
157}
158
159/* Given a pointer to some BLOCK node, and a boolean value to set the
160   "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
161   the given block, and for all local decls and all local sub-blocks
162   (recursively) which are contained therein.  */
163
164static void
165set_block_abstract_flags (tree stmt, int setting)
166{
167  tree local_decl;
168  tree subblock;
169
170  BLOCK_ABSTRACT (stmt) = setting;
171
172  for (local_decl = BLOCK_VARS (stmt);
173       local_decl != NULL_TREE;
174       local_decl = TREE_CHAIN (local_decl))
175    set_decl_abstract_flags (local_decl, setting);
176
177  for (subblock = BLOCK_SUBBLOCKS (stmt);
178       subblock != NULL_TREE;
179       subblock = BLOCK_CHAIN (subblock))
180    set_block_abstract_flags (subblock, setting);
181}
182
183/* Given a pointer to some ..._DECL node, and a boolean value to set the
184   "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
185   given decl, and (in the case where the decl is a FUNCTION_DECL) also
186   set the abstract flags for all of the parameters, local vars, local
187   blocks and sub-blocks (recursively) to the same setting.  */
188
189void
190set_decl_abstract_flags (tree decl, int setting)
191{
192  DECL_ABSTRACT (decl) = setting;
193  if (TREE_CODE (decl) == FUNCTION_DECL)
194    {
195      tree arg;
196
197      for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
198	DECL_ABSTRACT (arg) = setting;
199      if (DECL_INITIAL (decl) != NULL_TREE
200	  && DECL_INITIAL (decl) != error_mark_node)
201	set_block_abstract_flags (DECL_INITIAL (decl), setting);
202    }
203}
204
205/* Functions to keep track of the values hard regs had at the start of
206   the function.  */
207
208rtx
209get_hard_reg_initial_reg (struct function *fun, rtx reg)
210{
211  struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
212  int i;
213
214  if (ivs == 0)
215    return NULL_RTX;
216
217  for (i = 0; i < ivs->num_entries; i++)
218    if (rtx_equal_p (ivs->entries[i].pseudo, reg))
219      return ivs->entries[i].hard_reg;
220
221  return NULL_RTX;
222}
223
224/* Make sure that there's a pseudo register of mode MODE that stores the
225   initial value of hard register REGNO.  Return an rtx for such a pseudo.  */
226
227rtx
228get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
229{
230  struct initial_value_struct *ivs;
231  rtx rv;
232
233  rv = has_hard_reg_initial_val (mode, regno);
234  if (rv)
235    return rv;
236
237  ivs = cfun->hard_reg_initial_vals;
238  if (ivs == 0)
239    {
240      ivs = ggc_alloc (sizeof (initial_value_struct));
241      ivs->num_entries = 0;
242      ivs->max_entries = 5;
243      ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
244      cfun->hard_reg_initial_vals = ivs;
245    }
246
247  if (ivs->num_entries >= ivs->max_entries)
248    {
249      ivs->max_entries += 5;
250      ivs->entries = ggc_realloc (ivs->entries,
251				  ivs->max_entries
252				  * sizeof (initial_value_pair));
253    }
254
255  ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno);
256  ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode);
257
258  return ivs->entries[ivs->num_entries++].pseudo;
259}
260
261/* See if get_hard_reg_initial_val has been used to create a pseudo
262   for the initial value of hard register REGNO in mode MODE.  Return
263   the associated pseudo if so, otherwise return NULL.  */
264
265rtx
266has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
267{
268  struct initial_value_struct *ivs;
269  int i;
270
271  ivs = cfun->hard_reg_initial_vals;
272  if (ivs != 0)
273    for (i = 0; i < ivs->num_entries; i++)
274      if (GET_MODE (ivs->entries[i].hard_reg) == mode
275	  && REGNO (ivs->entries[i].hard_reg) == regno)
276	return ivs->entries[i].pseudo;
277
278  return NULL_RTX;
279}
280
281unsigned int
282emit_initial_value_sets (void)
283{
284  struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
285  int i;
286  rtx seq;
287
288  if (ivs == 0)
289    return 0;
290
291  start_sequence ();
292  for (i = 0; i < ivs->num_entries; i++)
293    emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
294  seq = get_insns ();
295  end_sequence ();
296
297  emit_insn_at_entry (seq);
298  return 0;
299}
300
301struct tree_opt_pass pass_initial_value_sets =
302{
303  "initvals",                           /* name */
304  NULL,                                 /* gate */
305  emit_initial_value_sets,              /* execute */
306  NULL,                                 /* sub */
307  NULL,                                 /* next */
308  0,                                    /* static_pass_number */
309  0,                                    /* tv_id */
310  0,                                    /* properties_required */
311  0,                                    /* properties_provided */
312  0,                                    /* properties_destroyed */
313  0,                                    /* todo_flags_start */
314  TODO_dump_func,                       /* todo_flags_finish */
315  0                                     /* letter */
316};
317
318/* If the backend knows where to allocate pseudos for hard
319   register initial values, register these allocations now.  */
320void
321allocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED)
322{
323  if (targetm.allocate_initial_value)
324    {
325      struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
326      int i;
327
328      if (ivs == 0)
329	return;
330
331      for (i = 0; i < ivs->num_entries; i++)
332	{
333	  int regno = REGNO (ivs->entries[i].pseudo);
334	  rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg);
335
336	  if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1)
337	    {
338	      if (MEM_P (x))
339		reg_equiv_memory_loc[regno] = x;
340	      else
341		{
342		  basic_block bb;
343		  int new_regno;
344
345		  gcc_assert (REG_P (x));
346		  new_regno = REGNO (x);
347		  reg_renumber[regno] = new_regno;
348		  /* Poke the regno right into regno_reg_rtx so that even
349		     fixed regs are accepted.  */
350		  REGNO (ivs->entries[i].pseudo) = new_regno;
351		  /* Update global register liveness information.  */
352		  FOR_EACH_BB (bb)
353		    {
354		      struct rtl_bb_info *info = bb->il.rtl;
355
356		      if (REGNO_REG_SET_P(info->global_live_at_start, regno))
357			SET_REGNO_REG_SET (info->global_live_at_start,
358					   new_regno);
359		      if (REGNO_REG_SET_P(info->global_live_at_end, regno))
360			SET_REGNO_REG_SET (info->global_live_at_end,
361					   new_regno);
362		    }
363		}
364	    }
365	}
366    }
367}
368
369#include "gt-integrate.h"
370