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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [cp/] [optimize.c] - Blame information for rev 862

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 283 jeremybenn
/* Perform optimizations on tree structure.
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009
3
   Free Software Foundation, Inc.
4
   Written by Mark Michell (mark@codesourcery.com).
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
11
any later version.
12
 
13
GCC is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "tree.h"
27
#include "cp-tree.h"
28
#include "rtl.h"
29
#include "insn-config.h"
30
#include "input.h"
31
#include "integrate.h"
32
#include "toplev.h"
33
#include "varray.h"
34
#include "params.h"
35
#include "hashtab.h"
36
#include "target.h"
37
#include "debug.h"
38
#include "tree-inline.h"
39
#include "flags.h"
40
#include "langhooks.h"
41
#include "diagnostic.h"
42
#include "tree-dump.h"
43
#include "gimple.h"
44
#include "tree-iterator.h"
45
#include "cgraph.h"
46
 
47
/* Prototypes.  */
48
 
49
static void update_cloned_parm (tree, tree, bool);
50
 
51
/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
52
   or destructor.  Update it to ensure that the source-position for
53
   the cloned parameter matches that for the original, and that the
54
   debugging generation code will be able to find the original PARM.  */
55
 
56
static void
57
update_cloned_parm (tree parm, tree cloned_parm, bool first)
58
{
59
  DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
60
 
61
  /* We may have taken its address.  */
62
  TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
63
 
64
  /* The definition might have different constness.  */
65
  TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
66
 
67
  TREE_USED (cloned_parm) = !first || TREE_USED (parm);
68
 
69
  /* The name may have changed from the declaration.  */
70
  DECL_NAME (cloned_parm) = DECL_NAME (parm);
71
  DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
72
  TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
73
 
74
  DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
75
}
76
 
77
 
78
/* FN is a function in High GIMPLE form that has a complete body and no
79
   CFG.  CLONE is a function whose body is to be set to a copy of FN,
80
   mapping argument declarations according to the ARG_MAP splay_tree.  */
81
 
82
static void
83
clone_body (tree clone, tree fn, void *arg_map)
84
{
85
  copy_body_data id;
86
  tree stmts;
87
 
88
  /* Clone the body, as if we were making an inline call.  But, remap
89
     the parameters in the callee to the parameters of caller.  */
90
  memset (&id, 0, sizeof (id));
91
  id.src_fn = fn;
92
  id.dst_fn = clone;
93
  id.src_cfun = DECL_STRUCT_FUNCTION (fn);
94
  id.decl_map = (struct pointer_map_t *) arg_map;
95
 
96
  id.copy_decl = copy_decl_no_change;
97
  id.transform_call_graph_edges = CB_CGE_DUPLICATE;
98
  id.transform_new_cfg = true;
99
  id.transform_return_to_modify = false;
100
  id.transform_lang_insert_block = NULL;
101
 
102
  /* We're not inside any EH region.  */
103
  id.eh_lp_nr = 0;
104
 
105
  stmts = DECL_SAVED_TREE (fn);
106
  walk_tree (&stmts, copy_tree_body_r, &id, NULL);
107
 
108
  /* Also remap the initializer of any static variables so that they (in
109
     particular, any label addresses) correspond to the base variant rather
110
     than the abstract one.  */
111
  if (DECL_NAME (clone) == base_dtor_identifier
112
      || DECL_NAME (clone) == base_ctor_identifier)
113
    {
114
      tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls;
115
      for (; decls; decls = TREE_CHAIN (decls))
116
        {
117
          tree decl = TREE_VALUE (decls);
118
          walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
119
        }
120
    }
121
 
122
  append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
123
}
124
 
125
/* DELETE_DTOR is a delete destructor whose body will be built.
126
   COMPLETE_DTOR is the corresponding complete destructor.  */
127
 
128
static void
129
build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
130
{
131
  tree call_dtor, call_delete;
132
  tree parm = DECL_ARGUMENTS (delete_dtor);
133
  tree virtual_size = cxx_sizeof (current_class_type);
134
 
135
  /* Call the corresponding complete destructor.  */
136
  gcc_assert (complete_dtor);
137
  call_dtor = build_cxx_call (complete_dtor, 1, &parm);
138
  add_stmt (call_dtor);
139
 
140
  add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
141
 
142
  /* Call the delete function.  */
143
  call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
144
                                      virtual_size,
145
                                      /*global_p=*/false,
146
                                      /*placement=*/NULL_TREE,
147
                                      /*alloc_fn=*/NULL_TREE);
148
  add_stmt (call_delete);
149
 
150
  /* Return the address of the object.  */
151
  if (targetm.cxx.cdtor_returns_this ())
152
    {
153
      tree val = DECL_ARGUMENTS (delete_dtor);
154
      val = build2 (MODIFY_EXPR, TREE_TYPE (val),
155
                    DECL_RESULT (delete_dtor), val);
156
      add_stmt (build_stmt (0, RETURN_EXPR, val));
157
    }
158
}
159
 
160
/* Return name of comdat group for complete and base ctor (or dtor)
161
   that have the same body.  If dtor is virtual, deleting dtor goes
162
   into this comdat group as well.  */
163
 
164
static tree
165
cdtor_comdat_group (tree complete, tree base)
166
{
167
  tree complete_name = DECL_COMDAT_GROUP (complete);
168
  tree base_name = DECL_COMDAT_GROUP (base);
169
  char *grp_name;
170
  const char *p, *q;
171
  bool diff_seen = false;
172
  size_t idx;
173
  if (complete_name == NULL)
174
    complete_name = cxx_comdat_group (complete);
175
  if (base_name == NULL)
176
    base_name = cxx_comdat_group (base);
177
  gcc_assert (IDENTIFIER_LENGTH (complete_name)
178
              == IDENTIFIER_LENGTH (base_name));
179
  grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
180
  p = IDENTIFIER_POINTER (complete_name);
181
  q = IDENTIFIER_POINTER (base_name);
182
  for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
183
    if (p[idx] == q[idx])
184
      grp_name[idx] = p[idx];
185
    else
186
      {
187
        gcc_assert (!diff_seen
188
                    && idx > 0
189
                    && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
190
                    && p[idx] == '1'
191
                    && q[idx] == '2');
192
        grp_name[idx] = '5';
193
        diff_seen = true;
194
      }
195
  grp_name[idx] = '\0';
196
  gcc_assert (diff_seen);
197
  return get_identifier (grp_name);
198
}
199
 
200
/* FN is a function that has a complete body.  Clone the body as
201
   necessary.  Returns nonzero if there's no longer any need to
202
   process the main body.  */
203
 
204
bool
205
maybe_clone_body (tree fn)
206
{
207
  tree comdat_group = NULL_TREE;
208
  tree clone;
209
  tree fns[3];
210
  bool first = true;
211
  bool in_charge_parm_used;
212
  int idx;
213
  bool need_alias = false;
214
 
215
  /* We only clone constructors and destructors.  */
216
  if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
217
      && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
218
    return 0;
219
 
220
  /* Emit the DWARF1 abstract instance.  */
221
  (*debug_hooks->deferred_inline_function) (fn);
222
 
223
  in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
224
  fns[0] = NULL_TREE;
225
  fns[1] = NULL_TREE;
226
  fns[2] = NULL_TREE;
227
 
228
  /* Look for the complete destructor which may be used to build the
229
     delete destructor.  */
230
  FOR_EACH_CLONE (clone, fn)
231
    if (DECL_NAME (clone) == complete_dtor_identifier
232
        || DECL_NAME (clone) == complete_ctor_identifier)
233
      fns[1] = clone;
234
    else if (DECL_NAME (clone) == base_dtor_identifier
235
             || DECL_NAME (clone) == base_ctor_identifier)
236
      fns[0] = clone;
237
    else if (DECL_NAME (clone) == deleting_dtor_identifier)
238
      fns[2] = clone;
239
    else
240
      gcc_unreachable ();
241
 
242
  /* Remember if we can't have multiple clones for some reason.  We need to
243
     check this before we remap local static initializers in clone_body.  */
244
  if (!tree_versionable_function_p (fn))
245
    need_alias = true;
246
 
247
  /* We know that any clones immediately follow FN in the TYPE_METHODS
248
     list.  */
249
  push_to_top_level ();
250
  for (idx = 0; idx < 3; idx++)
251
    {
252
      tree parm;
253
      tree clone_parm;
254
      int parmno;
255
      bool alias = false;
256
      struct pointer_map_t *decl_map;
257
 
258
      clone = fns[idx];
259
      if (!clone)
260
        continue;
261
 
262
      /* Update CLONE's source position information to match FN's.  */
263
      DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
264
      DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
265
      DECL_COMDAT (clone) = DECL_COMDAT (fn);
266
      DECL_WEAK (clone) = DECL_WEAK (fn);
267
 
268
      /* We don't copy the comdat group from fn to clone because the assembler
269
         name of fn was corrupted by write_mangled_name by adding *INTERNAL*
270
         to it. By doing so, it also corrupted the comdat group. */
271
      if (DECL_ONE_ONLY (fn))
272
        DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
273
      DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
274
      DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
275
      DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
276
      DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
277
      DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
278
      TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
279
      DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
280
      DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
281
      DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
282
      DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
283
      DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
284
 
285
      /* Adjust the parameter names and locations.  */
286
      parm = DECL_ARGUMENTS (fn);
287
      clone_parm = DECL_ARGUMENTS (clone);
288
      /* Update the `this' parameter, which is always first.  */
289
      update_cloned_parm (parm, clone_parm, first);
290
      parm = TREE_CHAIN (parm);
291
      clone_parm = TREE_CHAIN (clone_parm);
292
      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
293
        parm = TREE_CHAIN (parm);
294
      if (DECL_HAS_VTT_PARM_P (fn))
295
        parm = TREE_CHAIN (parm);
296
      if (DECL_HAS_VTT_PARM_P (clone))
297
        clone_parm = TREE_CHAIN (clone_parm);
298
      for (; parm;
299
           parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
300
        /* Update this parameter.  */
301
        update_cloned_parm (parm, clone_parm, first);
302
 
303
      /* Start processing the function.  */
304
      start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
305
 
306
      /* Tell cgraph if both ctors or both dtors are known to have
307
         the same body.  */
308
      if (!in_charge_parm_used
309
          && fns[0]
310
          && idx == 1
311
          && !flag_use_repository
312
          && DECL_INTERFACE_KNOWN (fns[0])
313
          && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
314
          && (!DECL_ONE_ONLY (fns[0])
315
              || (HAVE_COMDAT_GROUP
316
                  && DECL_WEAK (fns[0])))
317
          && cgraph_same_body_alias (clone, fns[0]))
318
        {
319
          alias = true;
320
          if (DECL_ONE_ONLY (fns[0]))
321
            {
322
              /* For comdat base and complete cdtors put them
323
                 into the same, *[CD]5* comdat group instead of
324
                 *[CD][12]*.  */
325
              comdat_group = cdtor_comdat_group (fns[1], fns[0]);
326
              DECL_COMDAT_GROUP (fns[0]) = comdat_group;
327
            }
328
        }
329
 
330
      /* Build the delete destructor by calling complete destructor
331
         and delete function.  */
332
      if (idx == 2)
333
        build_delete_destructor_body (clone, fns[1]);
334
      else if (alias)
335
        /* No need to populate body.  */ ;
336
      else
337
        {
338
          /* If we can't have multiple copies of FN (say, because there's a
339
             static local initialized with the address of a label), we need
340
             to use an alias for the complete variant.  */
341
          if (idx == 1 && need_alias)
342
            {
343
              if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
344
                sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
345
              else
346
                sorry ("making multiple clones of %qD", fn);
347
            }
348
 
349
          /* Remap the parameters.  */
350
          decl_map = pointer_map_create ();
351
          for (parmno = 0,
352
                parm = DECL_ARGUMENTS (fn),
353
                clone_parm = DECL_ARGUMENTS (clone);
354
              parm;
355
              ++parmno,
356
                parm = TREE_CHAIN (parm))
357
            {
358
              /* Map the in-charge parameter to an appropriate constant.  */
359
              if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
360
                {
361
                  tree in_charge;
362
                  in_charge = in_charge_arg_for_name (DECL_NAME (clone));
363
                  *pointer_map_insert (decl_map, parm) = in_charge;
364
                }
365
              else if (DECL_ARTIFICIAL (parm)
366
                       && DECL_NAME (parm) == vtt_parm_identifier)
367
                {
368
                  /* For a subobject constructor or destructor, the next
369
                     argument is the VTT parameter.  Remap the VTT_PARM
370
                     from the CLONE to this parameter.  */
371
                  if (DECL_HAS_VTT_PARM_P (clone))
372
                    {
373
                      DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
374
                      *pointer_map_insert (decl_map, parm) = clone_parm;
375
                      clone_parm = TREE_CHAIN (clone_parm);
376
                    }
377
                  /* Otherwise, map the VTT parameter to `NULL'.  */
378
                  else
379
                    *pointer_map_insert (decl_map, parm)
380
                       = fold_convert (TREE_TYPE (parm), null_pointer_node);
381
                }
382
              /* Map other parameters to their equivalents in the cloned
383
                 function.  */
384
              else
385
                {
386
                  *pointer_map_insert (decl_map, parm) = clone_parm;
387
                  clone_parm = TREE_CHAIN (clone_parm);
388
                }
389
            }
390
 
391
          if (targetm.cxx.cdtor_returns_this ())
392
            {
393
              parm = DECL_RESULT (fn);
394
              clone_parm = DECL_RESULT (clone);
395
              *pointer_map_insert (decl_map, parm) = clone_parm;
396
            }
397
 
398
          /* Clone the body.  */
399
          clone_body (clone, fn, decl_map);
400
 
401
          /* Clean up.  */
402
          pointer_map_destroy (decl_map);
403
        }
404
 
405
      /* The clone can throw iff the original function can throw.  */
406
      cp_function_chain->can_throw = !TREE_NOTHROW (fn);
407
 
408
      /* Now, expand this function into RTL, if appropriate.  */
409
      finish_function (0);
410
      BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
411
      if (alias)
412
        {
413
          if (expand_or_defer_fn_1 (clone))
414
            emit_associated_thunks (clone);
415
        }
416
      else
417
        expand_or_defer_fn (clone);
418
      first = false;
419
    }
420
  pop_from_top_level ();
421
 
422
  if (comdat_group)
423
    {
424
      DECL_COMDAT_GROUP (fns[1]) = comdat_group;
425
      if (fns[2])
426
        {
427
          struct cgraph_node *base_dtor_node, *deleting_dtor_node;
428
          /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
429
             virtual, it goes into the same comdat group as well.  */
430
          DECL_COMDAT_GROUP (fns[2]) = comdat_group;
431
          base_dtor_node = cgraph_node (fns[0]);
432
          deleting_dtor_node = cgraph_node (fns[2]);
433
          gcc_assert (base_dtor_node->same_comdat_group == NULL);
434
          gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
435
          base_dtor_node->same_comdat_group = deleting_dtor_node;
436
          deleting_dtor_node->same_comdat_group = base_dtor_node;
437
        }
438
    }
439
 
440
  /* We don't need to process the original function any further.  */
441
  return 1;
442
}

powered by: WebSVN 2.1.0

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