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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [cp/] [optimize.c] - Blame information for rev 758

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

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

powered by: WebSVN 2.1.0

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