OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [integrate.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* 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
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 2, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING.  If not, write to the Free
20
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21
02110-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.  */
55
typedef struct initial_value_pair GTY(()) {
56
  rtx hard_reg;
57
  rtx pseudo;
58
} initial_value_pair;
59
typedef 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
 
65
static void set_block_origin_self (tree);
66
static 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.  */
71
bool
72
function_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
 
102
static void
103
set_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
 
140
void
141
set_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
 
164
static void
165
set_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
 
189
void
190
set_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
 
208
rtx
209
get_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
 
227
rtx
228
get_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
 
265
rtx
266
has_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
 
281
void
282
emit_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;
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_after (seq, entry_of_function ());
298
}
299
 
300
struct tree_opt_pass pass_initial_value_sets =
301
{
302
  "initvals",                           /* name */
303
  NULL,                                 /* gate */
304
  emit_initial_value_sets,              /* execute */
305
  NULL,                                 /* sub */
306
  NULL,                                 /* next */
307
  0,                                    /* static_pass_number */
308
  0,                                    /* tv_id */
309
  0,                                    /* properties_required */
310
  0,                                    /* properties_provided */
311
  0,                                    /* properties_destroyed */
312
  0,                                    /* todo_flags_start */
313
  TODO_dump_func,                       /* todo_flags_finish */
314
 
315
};
316
 
317
/* If the backend knows where to allocate pseudos for hard
318
   register initial values, register these allocations now.  */
319
void
320
allocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED)
321
{
322
  if (targetm.allocate_initial_value)
323
    {
324
      struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
325
      int i;
326
 
327
      if (ivs == 0)
328
        return;
329
 
330
      for (i = 0; i < ivs->num_entries; i++)
331
        {
332
          int regno = REGNO (ivs->entries[i].pseudo);
333
          rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg);
334
 
335
          if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1)
336
            {
337
              if (MEM_P (x))
338
                reg_equiv_memory_loc[regno] = x;
339
              else
340
                {
341
                  basic_block bb;
342
                  int new_regno;
343
 
344
                  gcc_assert (REG_P (x));
345
                  new_regno = REGNO (x);
346
                  reg_renumber[regno] = new_regno;
347
                  /* Poke the regno right into regno_reg_rtx so that even
348
                     fixed regs are accepted.  */
349
                  REGNO (ivs->entries[i].pseudo) = new_regno;
350
                  /* Update global register liveness information.  */
351
                  FOR_EACH_BB (bb)
352
                    {
353
                      struct rtl_bb_info *info = bb->il.rtl;
354
 
355
                      if (REGNO_REG_SET_P(info->global_live_at_start, regno))
356
                        SET_REGNO_REG_SET (info->global_live_at_start,
357
                                           new_regno);
358
                      if (REGNO_REG_SET_P(info->global_live_at_end, regno))
359
                        SET_REGNO_REG_SET (info->global_live_at_end,
360
                                           new_regno);
361
                    }
362
                }
363
            }
364
        }
365
    }
366
}
367
 
368
#include "gt-integrate.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.