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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [cp/] [cp-gimplify.c] - Blame information for rev 16

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

Line No. Rev Author Line
1 12 jlechner
/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
 
3
   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4
   Contributed by Jason Merrill <jason@redhat.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
#include "tree.h"
28
#include "cp-tree.h"
29
#include "c-common.h"
30
#include "toplev.h"
31
#include "tree-gimple.h"
32
#include "hashtab.h"
33
#include "pointer-set.h"
34
#include "flags.h"
35
 
36
/* Local declarations.  */
37
 
38
enum bc_t { bc_break = 0, bc_continue = 1 };
39
 
40
static struct cp_gimplify_ctx
41
{
42
  /* Stack of labels which are targets for "break" or "continue",
43
     linked through TREE_CHAIN.  */
44
  tree current_label[2];
45
} *ctxp;
46
 
47
static void
48
push_context (void)
49
{
50
  gcc_assert (!ctxp);
51
  ctxp = ((struct cp_gimplify_ctx *)
52
          xcalloc (1, sizeof (struct cp_gimplify_ctx)));
53
}
54
 
55
static void
56
pop_context (void)
57
{
58
  gcc_assert (ctxp
59
              && !ctxp->current_label[0]
60
              && !ctxp->current_label[1]);
61
  free (ctxp);
62
  ctxp = NULL;
63
}
64
 
65
/* Begin a scope which can be exited by a break or continue statement.  BC
66
   indicates which.
67
 
68
   Just creates a label and pushes it into the current context.  */
69
 
70
static tree
71
begin_bc_block (enum bc_t bc)
72
{
73
  tree label = create_artificial_label ();
74
  TREE_CHAIN (label) = ctxp->current_label[bc];
75
  ctxp->current_label[bc] = label;
76
  return label;
77
}
78
 
79
/* Finish a scope which can be exited by a break or continue statement.
80
   LABEL was returned from the most recent call to begin_bc_block.  BODY is
81
   an expression for the contents of the scope.
82
 
83
   If we saw a break (or continue) in the scope, append a LABEL_EXPR to
84
   body.  Otherwise, just forget the label.  */
85
 
86
static tree
87
finish_bc_block (enum bc_t bc, tree label, tree body)
88
{
89
  gcc_assert (label == ctxp->current_label[bc]);
90
 
91
  if (TREE_USED (label))
92
    {
93
      tree t, sl = NULL;
94
 
95
      t = build1 (LABEL_EXPR, void_type_node, label);
96
 
97
      append_to_statement_list (body, &sl);
98
      append_to_statement_list (t, &sl);
99
      body = sl;
100
    }
101
 
102
  ctxp->current_label[bc] = TREE_CHAIN (label);
103
  TREE_CHAIN (label) = NULL_TREE;
104
  return body;
105
}
106
 
107
/* Build a GOTO_EXPR to represent a break or continue statement.  BC
108
   indicates which.  */
109
 
110
static tree
111
build_bc_goto (enum bc_t bc)
112
{
113
  tree label = ctxp->current_label[bc];
114
 
115
  if (label == NULL_TREE)
116
    {
117
      if (bc == bc_break)
118
        error ("break statement not within loop or switch");
119
      else
120
        error ("continue statement not within loop or switch");
121
 
122
      return NULL_TREE;
123
    }
124
 
125
  /* Mark the label used for finish_bc_block.  */
126
  TREE_USED (label) = 1;
127
  return build1 (GOTO_EXPR, void_type_node, label);
128
}
129
 
130
/* Genericize a TRY_BLOCK.  */
131
 
132
static void
133
genericize_try_block (tree *stmt_p)
134
{
135
  tree body = TRY_STMTS (*stmt_p);
136
  tree cleanup = TRY_HANDLERS (*stmt_p);
137
 
138
  gimplify_stmt (&body);
139
 
140
  if (CLEANUP_P (*stmt_p))
141
    /* A cleanup is an expression, so it doesn't need to be genericized.  */;
142
  else
143
    gimplify_stmt (&cleanup);
144
 
145
  *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
146
}
147
 
148
/* Genericize a HANDLER by converting to a CATCH_EXPR.  */
149
 
150
static void
151
genericize_catch_block (tree *stmt_p)
152
{
153
  tree type = HANDLER_TYPE (*stmt_p);
154
  tree body = HANDLER_BODY (*stmt_p);
155
 
156
  gimplify_stmt (&body);
157
 
158
  /* FIXME should the caught type go in TREE_TYPE?  */
159
  *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
160
}
161
 
162
/* Genericize an EH_SPEC_BLOCK by converting it to a
163
   TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
164
 
165
static void
166
genericize_eh_spec_block (tree *stmt_p)
167
{
168
  tree body = EH_SPEC_STMTS (*stmt_p);
169
  tree allowed = EH_SPEC_RAISES (*stmt_p);
170
  tree failure = build_call (call_unexpected_node,
171
                             tree_cons (NULL_TREE, build_exc_ptr (),
172
                                        NULL_TREE));
173
  gimplify_stmt (&body);
174
 
175
  *stmt_p = gimple_build_eh_filter (body, allowed, failure);
176
}
177
 
178
/* Genericize an IF_STMT by turning it into a COND_EXPR.  */
179
 
180
static void
181
gimplify_if_stmt (tree *stmt_p)
182
{
183
  tree stmt, cond, then_, else_;
184
 
185
  stmt = *stmt_p;
186
  cond = IF_COND (stmt);
187
  then_ = THEN_CLAUSE (stmt);
188
  else_ = ELSE_CLAUSE (stmt);
189
 
190
  if (!then_)
191
    then_ = build_empty_stmt ();
192
  if (!else_)
193
    else_ = build_empty_stmt ();
194
 
195
  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
196
    stmt = then_;
197
  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
198
    stmt = else_;
199
  else
200
    stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
201
  *stmt_p = stmt;
202
}
203
 
204
/* Build a generic representation of one of the C loop forms.  COND is the
205
   loop condition or NULL_TREE.  BODY is the (possibly compound) statement
206
   controlled by the loop.  INCR is the increment expression of a for-loop,
207
   or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
208
   evaluated before the loop body as in while and for loops, or after the
209
   loop body as in do-while loops.  */
210
 
211
static tree
212
gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
213
{
214
  tree top, entry, exit, cont_block, break_block, stmt_list, t;
215
  location_t stmt_locus;
216
 
217
  stmt_locus = input_location;
218
  stmt_list = NULL_TREE;
219
  entry = NULL_TREE;
220
 
221
  break_block = begin_bc_block (bc_break);
222
  cont_block = begin_bc_block (bc_continue);
223
 
224
  /* If condition is zero don't generate a loop construct.  */
225
  if (cond && integer_zerop (cond))
226
    {
227
      top = NULL_TREE;
228
      exit = NULL_TREE;
229
      if (cond_is_first)
230
        {
231
          t = build_bc_goto (bc_break);
232
          append_to_statement_list (t, &stmt_list);
233
        }
234
    }
235
  else
236
    {
237
      /* If we use a LOOP_EXPR here, we have to feed the whole thing
238
         back through the main gimplifier to lower it.  Given that we
239
         have to gimplify the loop body NOW so that we can resolve
240
         break/continue stmts, seems easier to just expand to gotos.  */
241
      top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
242
 
243
      /* If we have an exit condition, then we build an IF with gotos either
244
         out of the loop, or to the top of it.  If there's no exit condition,
245
         then we just build a jump back to the top.  */
246
      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
247
      if (cond && !integer_nonzerop (cond))
248
        {
249
          t = build_bc_goto (bc_break);
250
          exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
251
          exit = fold (exit);
252
          gimplify_stmt (&exit);
253
 
254
          if (cond_is_first)
255
            {
256
              if (incr)
257
                {
258
                  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
259
                  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
260
                }
261
              else
262
                t = build_bc_goto (bc_continue);
263
              append_to_statement_list (t, &stmt_list);
264
            }
265
        }
266
    }
267
 
268
  gimplify_stmt (&body);
269
  gimplify_stmt (&incr);
270
 
271
  body = finish_bc_block (bc_continue, cont_block, body);
272
 
273
  append_to_statement_list (top, &stmt_list);
274
  append_to_statement_list (body, &stmt_list);
275
  append_to_statement_list (incr, &stmt_list);
276
  append_to_statement_list (entry, &stmt_list);
277
  append_to_statement_list (exit, &stmt_list);
278
 
279
  annotate_all_with_locus (&stmt_list, stmt_locus);
280
 
281
  return finish_bc_block (bc_break, break_block, stmt_list);
282
}
283
 
284
/* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
285
   prequeue and hand off to gimplify_cp_loop.  */
286
 
287
static void
288
gimplify_for_stmt (tree *stmt_p, tree *pre_p)
289
{
290
  tree stmt = *stmt_p;
291
 
292
  if (FOR_INIT_STMT (stmt))
293
    gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
294
 
295
  *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
296
                              FOR_EXPR (stmt), 1);
297
}
298
 
299
/* Gimplify a WHILE_STMT node.  */
300
 
301
static void
302
gimplify_while_stmt (tree *stmt_p)
303
{
304
  tree stmt = *stmt_p;
305
  *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
306
                              NULL_TREE, 1);
307
}
308
 
309
/* Gimplify a DO_STMT node.  */
310
 
311
static void
312
gimplify_do_stmt (tree *stmt_p)
313
{
314
  tree stmt = *stmt_p;
315
  *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
316
                              NULL_TREE, 0);
317
}
318
 
319
/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
320
 
321
static void
322
gimplify_switch_stmt (tree *stmt_p)
323
{
324
  tree stmt = *stmt_p;
325
  tree break_block, body;
326
  location_t stmt_locus = input_location;
327
 
328
  break_block = begin_bc_block (bc_break);
329
 
330
  body = SWITCH_STMT_BODY (stmt);
331
  if (!body)
332
    body = build_empty_stmt ();
333
 
334
  *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
335
                    SWITCH_STMT_COND (stmt), body, NULL_TREE);
336
  SET_EXPR_LOCATION (*stmt_p, stmt_locus);
337
  gimplify_stmt (stmt_p);
338
 
339
  *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
340
}
341
 
342
/*  Gimplify an EXPR_STMT node.  */
343
 
344
static void
345
gimplify_expr_stmt (tree *stmt_p)
346
{
347
  tree stmt = EXPR_STMT_EXPR (*stmt_p);
348
 
349
  if (stmt == error_mark_node)
350
    stmt = NULL;
351
 
352
  /* Gimplification of a statement expression will nullify the
353
     statement if all its side effects are moved to *PRE_P and *POST_P.
354
 
355
     In this case we will not want to emit the gimplified statement.
356
     However, we may still want to emit a warning, so we do that before
357
     gimplification.  */
358
  if (stmt && (extra_warnings || warn_unused_value))
359
    {
360
      if (!TREE_SIDE_EFFECTS (stmt))
361
        {
362
          if (!IS_EMPTY_STMT (stmt)
363
              && !VOID_TYPE_P (TREE_TYPE (stmt))
364
              && !TREE_NO_WARNING (stmt))
365
            warning (0, "statement with no effect");
366
        }
367
      else if (warn_unused_value)
368
        warn_if_unused_value (stmt, input_location);
369
    }
370
 
371
  if (stmt == NULL_TREE)
372
    stmt = alloc_stmt_list ();
373
 
374
  *stmt_p = stmt;
375
}
376
 
377
/* Gimplify initialization from an AGGR_INIT_EXPR.  */
378
 
379
static void
380
cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
381
{
382
  tree from = TREE_OPERAND (*expr_p, 1);
383
  tree to = TREE_OPERAND (*expr_p, 0);
384
  tree sub;
385
 
386
  /* If we are initializing something from a TARGET_EXPR, strip the
387
     TARGET_EXPR and initialize it directly.  */
388
  /* What about code that pulls out the temp and uses it elsewhere?  I
389
     think that such code never uses the TARGET_EXPR as an initializer.  If
390
     I'm wrong, we'll abort because the temp won't have any RTL.  In that
391
     case, I guess we'll need to replace references somehow.  */
392
  if (TREE_CODE (from) == TARGET_EXPR)
393
    from = TARGET_EXPR_INITIAL (from);
394
  if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
395
    from = TREE_OPERAND (from, 0);
396
 
397
  /* Look through any COMPOUND_EXPRs.  */
398
  sub = expr_last (from);
399
 
400
  /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
401
     replace the slot operand with our target.
402
 
403
     Should we add a target parm to gimplify_expr instead?  No, as in this
404
     case we want to replace the INIT_EXPR.  */
405
  if (TREE_CODE (sub) == AGGR_INIT_EXPR)
406
    {
407
      gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
408
      TREE_OPERAND (sub, 2) = to;
409
      *expr_p = from;
410
 
411
      /* The initialization is now a side-effect, so the container can
412
         become void.  */
413
      if (from != sub)
414
        TREE_TYPE (from) = void_type_node;
415
    }
416
}
417
 
418
/* Gimplify a MUST_NOT_THROW_EXPR.  */
419
 
420
static void
421
gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
422
{
423
  tree stmt = *expr_p;
424
  tree temp = voidify_wrapper_expr (stmt, NULL);
425
  tree body = TREE_OPERAND (stmt, 0);
426
 
427
  gimplify_stmt (&body);
428
 
429
  stmt = gimple_build_eh_filter (body, NULL_TREE,
430
                                 build_call (terminate_node, NULL_TREE));
431
 
432
  if (temp)
433
    {
434
      append_to_statement_list (stmt, pre_p);
435
      *expr_p = temp;
436
    }
437
  else
438
    *expr_p = stmt;
439
}
440
 
441
/* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
442
 
443
int
444
cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
445
{
446
  int saved_stmts_are_full_exprs_p = 0;
447
  enum tree_code code = TREE_CODE (*expr_p);
448
  enum gimplify_status ret;
449
 
450
  if (STATEMENT_CODE_P (code))
451
    {
452
      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
453
      current_stmt_tree ()->stmts_are_full_exprs_p
454
        = STMT_IS_FULL_EXPR_P (*expr_p);
455
    }
456
 
457
  switch (code)
458
    {
459
    case PTRMEM_CST:
460
      *expr_p = cplus_expand_constant (*expr_p);
461
      ret = GS_OK;
462
      break;
463
 
464
    case AGGR_INIT_EXPR:
465
      simplify_aggr_init_expr (expr_p);
466
      ret = GS_OK;
467
      break;
468
 
469
    case THROW_EXPR:
470
      /* FIXME communicate throw type to backend, probably by moving
471
         THROW_EXPR into ../tree.def.  */
472
      *expr_p = TREE_OPERAND (*expr_p, 0);
473
      ret = GS_OK;
474
      break;
475
 
476
    case MUST_NOT_THROW_EXPR:
477
      gimplify_must_not_throw_expr (expr_p, pre_p);
478
      ret = GS_OK;
479
      break;
480
 
481
      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
482
         LHS of an assignment might also be involved in the RHS, as in bug
483
         25979.  */
484
    case INIT_EXPR:
485
      cp_gimplify_init_expr (expr_p, pre_p, post_p);
486
      ret = GS_OK;
487
      break;
488
 
489
    case EMPTY_CLASS_EXPR:
490
      /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
491
      *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
492
      ret = GS_OK;
493
      break;
494
 
495
    case BASELINK:
496
      *expr_p = BASELINK_FUNCTIONS (*expr_p);
497
      ret = GS_OK;
498
      break;
499
 
500
    case TRY_BLOCK:
501
      genericize_try_block (expr_p);
502
      ret = GS_OK;
503
      break;
504
 
505
    case HANDLER:
506
      genericize_catch_block (expr_p);
507
      ret = GS_OK;
508
      break;
509
 
510
    case EH_SPEC_BLOCK:
511
      genericize_eh_spec_block (expr_p);
512
      ret = GS_OK;
513
      break;
514
 
515
    case USING_STMT:
516
      /* Just ignore for now.  Eventually we will want to pass this on to
517
         the debugger.  */
518
      *expr_p = build_empty_stmt ();
519
      ret = GS_ALL_DONE;
520
      break;
521
 
522
    case IF_STMT:
523
      gimplify_if_stmt (expr_p);
524
      ret = GS_OK;
525
      break;
526
 
527
    case FOR_STMT:
528
      gimplify_for_stmt (expr_p, pre_p);
529
      ret = GS_ALL_DONE;
530
      break;
531
 
532
    case WHILE_STMT:
533
      gimplify_while_stmt (expr_p);
534
      ret = GS_ALL_DONE;
535
      break;
536
 
537
    case DO_STMT:
538
      gimplify_do_stmt (expr_p);
539
      ret = GS_ALL_DONE;
540
      break;
541
 
542
    case SWITCH_STMT:
543
      gimplify_switch_stmt (expr_p);
544
      ret = GS_ALL_DONE;
545
      break;
546
 
547
    case CONTINUE_STMT:
548
      *expr_p = build_bc_goto (bc_continue);
549
      ret = GS_ALL_DONE;
550
      break;
551
 
552
    case BREAK_STMT:
553
      *expr_p = build_bc_goto (bc_break);
554
      ret = GS_ALL_DONE;
555
      break;
556
 
557
    case EXPR_STMT:
558
      gimplify_expr_stmt (expr_p);
559
      ret = GS_OK;
560
      break;
561
 
562
    case UNARY_PLUS_EXPR:
563
      {
564
        tree arg = TREE_OPERAND (*expr_p, 0);
565
        tree type = TREE_TYPE (*expr_p);
566
        *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
567
                                            : arg;
568
        ret = GS_OK;
569
      }
570
      break;
571
 
572
    default:
573
      ret = c_gimplify_expr (expr_p, pre_p, post_p);
574
      break;
575
    }
576
 
577
  /* Restore saved state.  */
578
  if (STATEMENT_CODE_P (code))
579
    current_stmt_tree ()->stmts_are_full_exprs_p
580
      = saved_stmts_are_full_exprs_p;
581
 
582
  return ret;
583
}
584
 
585
static inline bool
586
is_invisiref_parm (tree t)
587
{
588
  return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
589
          && DECL_BY_REFERENCE (t));
590
}
591
 
592
/* Perform any pre-gimplification lowering of C++ front end trees to
593
   GENERIC.  */
594
 
595
static tree
596
cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
597
{
598
  tree stmt = *stmt_p;
599
  struct pointer_set_t *p_set = (struct pointer_set_t*) data;
600
 
601
  if (is_invisiref_parm (stmt)
602
      /* Don't dereference parms in a thunk, pass the references through. */
603
      && !(DECL_THUNK_P (current_function_decl)
604
           && TREE_CODE (stmt) == PARM_DECL))
605
    {
606
      *stmt_p = convert_from_reference (stmt);
607
      *walk_subtrees = 0;
608
      return NULL;
609
    }
610
 
611
  /* Other than invisiref parms, don't walk the same tree twice.  */
612
  if (pointer_set_contains (p_set, stmt))
613
    {
614
      *walk_subtrees = 0;
615
      return NULL_TREE;
616
    }
617
 
618
  if (TREE_CODE (stmt) == ADDR_EXPR
619
      && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
620
    {
621
      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
622
      *walk_subtrees = 0;
623
    }
624
  else if (TREE_CODE (stmt) == RETURN_EXPR
625
           && TREE_OPERAND (stmt, 0)
626
           && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
627
    /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
628
    *walk_subtrees = 0;
629
  else if (IS_TYPE_OR_DECL_P (stmt))
630
    *walk_subtrees = 0;
631
 
632
  /* Due to the way voidify_wrapper_expr is written, we don't get a chance
633
     to lower this construct before scanning it, so we need to lower these
634
     before doing anything else.  */
635
  else if (TREE_CODE (stmt) == CLEANUP_STMT)
636
    *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
637
                                             : TRY_FINALLY_EXPR,
638
                      void_type_node,
639
                      CLEANUP_BODY (stmt),
640
                      CLEANUP_EXPR (stmt));
641
 
642
  pointer_set_insert (p_set, *stmt_p);
643
 
644
  return NULL;
645
}
646
 
647
void
648
cp_genericize (tree fndecl)
649
{
650
  tree t;
651
  struct pointer_set_t *p_set;
652
 
653
  /* Fix up the types of parms passed by invisible reference.  */
654
  for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
655
    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
656
      {
657
        /* If a function's arguments are copied to create a thunk,
658
           then DECL_BY_REFERENCE will be set -- but the type of the
659
           argument will be a pointer type, so we will never get
660
           here.  */
661
        gcc_assert (!DECL_BY_REFERENCE (t));
662
        gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
663
        TREE_TYPE (t) = DECL_ARG_TYPE (t);
664
        DECL_BY_REFERENCE (t) = 1;
665
        TREE_ADDRESSABLE (t) = 0;
666
        relayout_decl (t);
667
      }
668
 
669
  /* Do the same for the return value.  */
670
  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
671
    {
672
      t = DECL_RESULT (fndecl);
673
      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
674
      DECL_BY_REFERENCE (t) = 1;
675
      TREE_ADDRESSABLE (t) = 0;
676
      relayout_decl (t);
677
    }
678
 
679
  /* If we're a clone, the body is already GIMPLE.  */
680
  if (DECL_CLONED_FUNCTION_P (fndecl))
681
    return;
682
 
683
  /* We do want to see every occurrence of the parms, so we can't just use
684
     walk_tree's hash functionality.  */
685
  p_set = pointer_set_create ();
686
  walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
687
  pointer_set_destroy (p_set);
688
 
689
  /* Do everything else.  */
690
  push_context ();
691
  c_genericize (fndecl);
692
  pop_context ();
693
}

powered by: WebSVN 2.1.0

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