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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 710 jeremybenn
/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
 
3
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4
   Free Software Foundation, Inc.
5
   Contributed by Jason Merrill <jason@redhat.com>
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13
 
14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
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-family/c-common.h"
30
#include "tree-iterator.h"
31
#include "gimple.h"
32
#include "hashtab.h"
33
#include "pointer-set.h"
34
#include "flags.h"
35
#include "splay-tree.h"
36
 
37
/* Local declarations.  */
38
 
39
enum bc_t { bc_break = 0, bc_continue = 1 };
40
 
41
/* Stack of labels which are targets for "break" or "continue",
42
   linked through TREE_CHAIN.  */
43
static tree bc_label[2];
44
 
45
/* Begin a scope which can be exited by a break or continue statement.  BC
46
   indicates which.
47
 
48
   Just creates a label and pushes it into the current context.  */
49
 
50
static tree
51
begin_bc_block (enum bc_t bc)
52
{
53
  tree label = create_artificial_label (input_location);
54
  DECL_CHAIN (label) = bc_label[bc];
55
  bc_label[bc] = label;
56
  return label;
57
}
58
 
59
/* Finish a scope which can be exited by a break or continue statement.
60
   LABEL was returned from the most recent call to begin_bc_block.  BODY is
61
   an expression for the contents of the scope.
62
 
63
   If we saw a break (or continue) in the scope, append a LABEL_EXPR to
64
   body.  Otherwise, just forget the label.  */
65
 
66
static gimple_seq
67
finish_bc_block (enum bc_t bc, tree label, gimple_seq body)
68
{
69
  gcc_assert (label == bc_label[bc]);
70
 
71
  if (TREE_USED (label))
72
    {
73
      gimple_seq_add_stmt (&body, gimple_build_label (label));
74
    }
75
 
76
  bc_label[bc] = DECL_CHAIN (label);
77
  DECL_CHAIN (label) = NULL_TREE;
78
  return body;
79
}
80
 
81
/* Get the LABEL_EXPR to represent a break or continue statement
82
   in the current block scope.  BC indicates which.  */
83
 
84
static tree
85
get_bc_label (enum bc_t bc)
86
{
87
  tree label = bc_label[bc];
88
 
89
  /* Mark the label used for finish_bc_block.  */
90
  TREE_USED (label) = 1;
91
  return label;
92
}
93
 
94
/* Genericize a TRY_BLOCK.  */
95
 
96
static void
97
genericize_try_block (tree *stmt_p)
98
{
99
  tree body = TRY_STMTS (*stmt_p);
100
  tree cleanup = TRY_HANDLERS (*stmt_p);
101
 
102
  *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
103
}
104
 
105
/* Genericize a HANDLER by converting to a CATCH_EXPR.  */
106
 
107
static void
108
genericize_catch_block (tree *stmt_p)
109
{
110
  tree type = HANDLER_TYPE (*stmt_p);
111
  tree body = HANDLER_BODY (*stmt_p);
112
 
113
  /* FIXME should the caught type go in TREE_TYPE?  */
114
  *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
115
}
116
 
117
/* A terser interface for building a representation of an exception
118
   specification.  */
119
 
120
static tree
121
build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
122
{
123
  tree t;
124
 
125
  /* FIXME should the allowed types go in TREE_TYPE?  */
126
  t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
127
  append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
128
 
129
  t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
130
  append_to_statement_list (body, &TREE_OPERAND (t, 0));
131
 
132
  return t;
133
}
134
 
135
/* Genericize an EH_SPEC_BLOCK by converting it to a
136
   TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
137
 
138
static void
139
genericize_eh_spec_block (tree *stmt_p)
140
{
141
  tree body = EH_SPEC_STMTS (*stmt_p);
142
  tree allowed = EH_SPEC_RAISES (*stmt_p);
143
  tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
144
 
145
  *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
146
  TREE_NO_WARNING (*stmt_p) = true;
147
  TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
148
}
149
 
150
/* Genericize an IF_STMT by turning it into a COND_EXPR.  */
151
 
152
static void
153
genericize_if_stmt (tree *stmt_p)
154
{
155
  tree stmt, cond, then_, else_;
156
  location_t locus = EXPR_LOCATION (*stmt_p);
157
 
158
  stmt = *stmt_p;
159
  cond = IF_COND (stmt);
160
  then_ = THEN_CLAUSE (stmt);
161
  else_ = ELSE_CLAUSE (stmt);
162
 
163
  if (!then_)
164
    then_ = build_empty_stmt (locus);
165
  if (!else_)
166
    else_ = build_empty_stmt (locus);
167
 
168
  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
169
    stmt = then_;
170
  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
171
    stmt = else_;
172
  else
173
    stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
174
  if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
175
    SET_EXPR_LOCATION (stmt, locus);
176
  *stmt_p = stmt;
177
}
178
 
179
/* Build a generic representation of one of the C loop forms.  COND is the
180
   loop condition or NULL_TREE.  BODY is the (possibly compound) statement
181
   controlled by the loop.  INCR is the increment expression of a for-loop,
182
   or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
183
   evaluated before the loop body as in while and for loops, or after the
184
   loop body as in do-while loops.  */
185
 
186
static gimple_seq
187
gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
188
{
189
  gimple top, entry, stmt;
190
  gimple_seq stmt_list, body_seq, incr_seq, exit_seq;
191
  tree cont_block, break_block;
192
  location_t stmt_locus;
193
 
194
  stmt_locus = input_location;
195
  stmt_list = NULL;
196
  body_seq = NULL;
197
  incr_seq = NULL;
198
  exit_seq = NULL;
199
  entry = NULL;
200
 
201
  break_block = begin_bc_block (bc_break);
202
  cont_block = begin_bc_block (bc_continue);
203
 
204
  /* If condition is zero don't generate a loop construct.  */
205
  if (cond && integer_zerop (cond))
206
    {
207
      top = NULL;
208
      if (cond_is_first)
209
        {
210
          stmt = gimple_build_goto (get_bc_label (bc_break));
211
          gimple_set_location (stmt, stmt_locus);
212
          gimple_seq_add_stmt (&stmt_list, stmt);
213
        }
214
    }
215
  else
216
    {
217
      /* If we use a LOOP_EXPR here, we have to feed the whole thing
218
         back through the main gimplifier to lower it.  Given that we
219
         have to gimplify the loop body NOW so that we can resolve
220
         break/continue stmts, seems easier to just expand to gotos.  */
221
      top = gimple_build_label (create_artificial_label (stmt_locus));
222
 
223
      /* If we have an exit condition, then we build an IF with gotos either
224
         out of the loop, or to the top of it.  If there's no exit condition,
225
         then we just build a jump back to the top.  */
226
      if (cond && !integer_nonzerop (cond))
227
        {
228
          if (cond != error_mark_node)
229
            {
230
              gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue);
231
              stmt = gimple_build_cond (NE_EXPR, cond,
232
                                        build_int_cst (TREE_TYPE (cond), 0),
233
                                        gimple_label_label (top),
234
                                        get_bc_label (bc_break));
235
              gimple_seq_add_stmt (&exit_seq, stmt);
236
            }
237
 
238
          if (cond_is_first)
239
            {
240
              if (incr)
241
                {
242
                  entry = gimple_build_label
243
                    (create_artificial_label (stmt_locus));
244
                  stmt = gimple_build_goto (gimple_label_label (entry));
245
                }
246
              else
247
                stmt = gimple_build_goto (get_bc_label (bc_continue));
248
              gimple_set_location (stmt, stmt_locus);
249
              gimple_seq_add_stmt (&stmt_list, stmt);
250
            }
251
        }
252
      else
253
        {
254
          stmt = gimple_build_goto (gimple_label_label (top));
255
          gimple_seq_add_stmt (&exit_seq, stmt);
256
        }
257
    }
258
 
259
  gimplify_stmt (&body, &body_seq);
260
  gimplify_stmt (&incr, &incr_seq);
261
 
262
  body_seq = finish_bc_block (bc_continue, cont_block, body_seq);
263
 
264
  gimple_seq_add_stmt (&stmt_list, top);
265
  gimple_seq_add_seq (&stmt_list, body_seq);
266
  gimple_seq_add_seq (&stmt_list, incr_seq);
267
  gimple_seq_add_stmt (&stmt_list, entry);
268
  gimple_seq_add_seq (&stmt_list, exit_seq);
269
 
270
  annotate_all_with_location (stmt_list, stmt_locus);
271
 
272
  return finish_bc_block (bc_break, break_block, stmt_list);
273
}
274
 
275
/* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
276
   prequeue and hand off to gimplify_cp_loop.  */
277
 
278
static void
279
gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p)
280
{
281
  tree stmt = *stmt_p;
282
 
283
  if (FOR_INIT_STMT (stmt))
284
    gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
285
 
286
  gimple_seq_add_seq (pre_p,
287
                      gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
288
                                        FOR_EXPR (stmt), 1));
289
  *stmt_p = NULL_TREE;
290
}
291
 
292
/* Gimplify a WHILE_STMT node.  */
293
 
294
static void
295
gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p)
296
{
297
  tree stmt = *stmt_p;
298
  gimple_seq_add_seq (pre_p,
299
                      gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
300
                                        NULL_TREE, 1));
301
  *stmt_p = NULL_TREE;
302
}
303
 
304
/* Gimplify a DO_STMT node.  */
305
 
306
static void
307
gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p)
308
{
309
  tree stmt = *stmt_p;
310
  gimple_seq_add_seq (pre_p,
311
                      gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
312
                                        NULL_TREE, 0));
313
  *stmt_p = NULL_TREE;
314
}
315
 
316
/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
317
 
318
static void
319
gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p)
320
{
321
  tree stmt = *stmt_p;
322
  tree break_block, body, t;
323
  location_t stmt_locus = input_location;
324
  gimple_seq seq = NULL;
325
 
326
  break_block = begin_bc_block (bc_break);
327
 
328
  body = SWITCH_STMT_BODY (stmt);
329
  if (!body)
330
    body = build_empty_stmt (stmt_locus);
331
 
332
  t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
333
              SWITCH_STMT_COND (stmt), body, NULL_TREE);
334
  SET_EXPR_LOCATION (t, stmt_locus);
335
  gimplify_and_add (t, &seq);
336
 
337
  seq = finish_bc_block (bc_break, break_block, seq);
338
  gimple_seq_add_seq (pre_p, seq);
339
  *stmt_p = NULL_TREE;
340
}
341
 
342
/* Hook into the middle of gimplifying an OMP_FOR node.  This is required
343
   in order to properly gimplify CONTINUE statements.  Here we merely
344
   manage the continue stack; the rest of the job is performed by the
345
   regular gimplifier.  */
346
 
347
static enum gimplify_status
348
cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
349
{
350
  tree for_stmt = *expr_p;
351
  tree cont_block;
352
  gimple stmt;
353
  gimple_seq seq = NULL;
354
 
355
  /* Protect ourselves from recursion.  */
356
  if (OMP_FOR_GIMPLIFYING_P (for_stmt))
357
    return GS_UNHANDLED;
358
  OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
359
 
360
  /* Note that while technically the continue label is enabled too soon
361
     here, we should have already diagnosed invalid continues nested within
362
     statement expressions within the INIT, COND, or INCR expressions.  */
363
  cont_block = begin_bc_block (bc_continue);
364
 
365
  gimplify_and_add (for_stmt, &seq);
366
  stmt = gimple_seq_last_stmt (seq);
367
  if (gimple_code (stmt) == GIMPLE_OMP_FOR)
368
    gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
369
                                                gimple_omp_body (stmt)));
370
  else
371
    seq = finish_bc_block (bc_continue, cont_block, seq);
372
  gimple_seq_add_seq (pre_p, seq);
373
 
374
  OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
375
 
376
  return GS_ALL_DONE;
377
}
378
 
379
/*  Gimplify an EXPR_STMT node.  */
380
 
381
static void
382
gimplify_expr_stmt (tree *stmt_p)
383
{
384
  tree stmt = EXPR_STMT_EXPR (*stmt_p);
385
 
386
  if (stmt == error_mark_node)
387
    stmt = NULL;
388
 
389
  /* Gimplification of a statement expression will nullify the
390
     statement if all its side effects are moved to *PRE_P and *POST_P.
391
 
392
     In this case we will not want to emit the gimplified statement.
393
     However, we may still want to emit a warning, so we do that before
394
     gimplification.  */
395
  if (stmt && warn_unused_value)
396
    {
397
      if (!TREE_SIDE_EFFECTS (stmt))
398
        {
399
          if (!IS_EMPTY_STMT (stmt)
400
              && !VOID_TYPE_P (TREE_TYPE (stmt))
401
              && !TREE_NO_WARNING (stmt))
402
            warning (OPT_Wunused_value, "statement with no effect");
403
        }
404
      else
405
        warn_if_unused_value (stmt, input_location);
406
    }
407
 
408
  if (stmt == NULL_TREE)
409
    stmt = alloc_stmt_list ();
410
 
411
  *stmt_p = stmt;
412
}
413
 
414
/* Gimplify initialization from an AGGR_INIT_EXPR.  */
415
 
416
static void
417
cp_gimplify_init_expr (tree *expr_p)
418
{
419
  tree from = TREE_OPERAND (*expr_p, 1);
420
  tree to = TREE_OPERAND (*expr_p, 0);
421
  tree t;
422
 
423
  /* What about code that pulls out the temp and uses it elsewhere?  I
424
     think that such code never uses the TARGET_EXPR as an initializer.  If
425
     I'm wrong, we'll abort because the temp won't have any RTL.  In that
426
     case, I guess we'll need to replace references somehow.  */
427
  if (TREE_CODE (from) == TARGET_EXPR)
428
    from = TARGET_EXPR_INITIAL (from);
429
 
430
  /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
431
     inside the TARGET_EXPR.  */
432
  for (t = from; t; )
433
    {
434
      tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
435
 
436
      /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
437
         replace the slot operand with our target.
438
 
439
         Should we add a target parm to gimplify_expr instead?  No, as in this
440
         case we want to replace the INIT_EXPR.  */
441
      if (TREE_CODE (sub) == AGGR_INIT_EXPR
442
          || TREE_CODE (sub) == VEC_INIT_EXPR)
443
        {
444
          if (TREE_CODE (sub) == AGGR_INIT_EXPR)
445
            AGGR_INIT_EXPR_SLOT (sub) = to;
446
          else
447
            VEC_INIT_EXPR_SLOT (sub) = to;
448
          *expr_p = from;
449
 
450
          /* The initialization is now a side-effect, so the container can
451
             become void.  */
452
          if (from != sub)
453
            TREE_TYPE (from) = void_type_node;
454
        }
455
 
456
      if (t == sub)
457
        break;
458
      else
459
        t = TREE_OPERAND (t, 1);
460
    }
461
 
462
}
463
 
464
/* Gimplify a MUST_NOT_THROW_EXPR.  */
465
 
466
static enum gimplify_status
467
gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
468
{
469
  tree stmt = *expr_p;
470
  tree temp = voidify_wrapper_expr (stmt, NULL);
471
  tree body = TREE_OPERAND (stmt, 0);
472
  gimple_seq try_ = NULL;
473
  gimple_seq catch_ = NULL;
474
  gimple mnt;
475
 
476
  gimplify_and_add (body, &try_);
477
  mnt = gimple_build_eh_must_not_throw (terminate_node);
478
  gimple_seq_add_stmt_without_update (&catch_, mnt);
479
  mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
480
 
481
  gimple_seq_add_stmt_without_update (pre_p, mnt);
482
  if (temp)
483
    {
484
      *expr_p = temp;
485
      return GS_OK;
486
    }
487
 
488
  *expr_p = NULL;
489
  return GS_ALL_DONE;
490
}
491
 
492
/* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
493
 
494
int
495
cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
496
{
497
  int saved_stmts_are_full_exprs_p = 0;
498
  enum tree_code code = TREE_CODE (*expr_p);
499
  enum gimplify_status ret;
500
 
501
  if (STATEMENT_CODE_P (code))
502
    {
503
      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
504
      current_stmt_tree ()->stmts_are_full_exprs_p
505
        = STMT_IS_FULL_EXPR_P (*expr_p);
506
    }
507
 
508
  switch (code)
509
    {
510
    case PTRMEM_CST:
511
      *expr_p = cplus_expand_constant (*expr_p);
512
      ret = GS_OK;
513
      break;
514
 
515
    case AGGR_INIT_EXPR:
516
      simplify_aggr_init_expr (expr_p);
517
      ret = GS_OK;
518
      break;
519
 
520
    case VEC_INIT_EXPR:
521
      {
522
        location_t loc = input_location;
523
        tree init = VEC_INIT_EXPR_INIT (*expr_p);
524
        int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
525
        gcc_assert (EXPR_HAS_LOCATION (*expr_p));
526
        input_location = EXPR_LOCATION (*expr_p);
527
        *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
528
                                  init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
529
                                  from_array,
530
                                  tf_warning_or_error);
531
        ret = GS_OK;
532
        input_location = loc;
533
      }
534
      break;
535
 
536
    case THROW_EXPR:
537
      /* FIXME communicate throw type to back end, probably by moving
538
         THROW_EXPR into ../tree.def.  */
539
      *expr_p = TREE_OPERAND (*expr_p, 0);
540
      ret = GS_OK;
541
      break;
542
 
543
    case MUST_NOT_THROW_EXPR:
544
      ret = gimplify_must_not_throw_expr (expr_p, pre_p);
545
      break;
546
 
547
      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
548
         LHS of an assignment might also be involved in the RHS, as in bug
549
         25979.  */
550
    case INIT_EXPR:
551
      cp_gimplify_init_expr (expr_p);
552
      if (TREE_CODE (*expr_p) != INIT_EXPR)
553
        return GS_OK;
554
      /* Otherwise fall through.  */
555
    case MODIFY_EXPR:
556
      {
557
        /* If the back end isn't clever enough to know that the lhs and rhs
558
           types are the same, add an explicit conversion.  */
559
        tree op0 = TREE_OPERAND (*expr_p, 0);
560
        tree op1 = TREE_OPERAND (*expr_p, 1);
561
 
562
        if (!error_operand_p (op0)
563
            && !error_operand_p (op1)
564
            && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
565
                || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
566
            && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
567
          TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
568
                                              TREE_TYPE (op0), op1);
569
 
570
        else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
571
                  || (TREE_CODE (op1) == CONSTRUCTOR
572
                      && CONSTRUCTOR_NELTS (op1) == 0
573
                      && !TREE_CLOBBER_P (op1))
574
                  || (TREE_CODE (op1) == CALL_EXPR
575
                      && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
576
                 && is_really_empty_class (TREE_TYPE (op0)))
577
          {
578
            /* Remove any copies of empty classes.  We check that the RHS
579
               has a simple form so that TARGET_EXPRs and non-empty
580
               CONSTRUCTORs get reduced properly, and we leave the return
581
               slot optimization alone because it isn't a copy (FIXME so it
582
               shouldn't be represented as one).
583
 
584
               Also drop volatile variables on the RHS to avoid infinite
585
               recursion from gimplify_expr trying to load the value.  */
586
            if (!TREE_SIDE_EFFECTS (op1)
587
                || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
588
              *expr_p = op0;
589
            else if (TREE_CODE (op1) == MEM_REF
590
                     && TREE_THIS_VOLATILE (op1))
591
              {
592
                /* Similarly for volatile MEM_REFs on the RHS.  */
593
                if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
594
                  *expr_p = op0;
595
                else
596
                  *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
597
                                    TREE_OPERAND (op1, 0), op0);
598
              }
599
            else
600
              *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
601
                                op0, op1);
602
          }
603
      }
604
      ret = GS_OK;
605
      break;
606
 
607
    case EMPTY_CLASS_EXPR:
608
      /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
609
      *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
610
      ret = GS_OK;
611
      break;
612
 
613
    case BASELINK:
614
      *expr_p = BASELINK_FUNCTIONS (*expr_p);
615
      ret = GS_OK;
616
      break;
617
 
618
    case TRY_BLOCK:
619
      genericize_try_block (expr_p);
620
      ret = GS_OK;
621
      break;
622
 
623
    case HANDLER:
624
      genericize_catch_block (expr_p);
625
      ret = GS_OK;
626
      break;
627
 
628
    case EH_SPEC_BLOCK:
629
      genericize_eh_spec_block (expr_p);
630
      ret = GS_OK;
631
      break;
632
 
633
    case USING_STMT:
634
      gcc_unreachable ();
635
 
636
    case FOR_STMT:
637
      gimplify_for_stmt (expr_p, pre_p);
638
      ret = GS_OK;
639
      break;
640
 
641
    case WHILE_STMT:
642
      gimplify_while_stmt (expr_p, pre_p);
643
      ret = GS_OK;
644
      break;
645
 
646
    case DO_STMT:
647
      gimplify_do_stmt (expr_p, pre_p);
648
      ret = GS_OK;
649
      break;
650
 
651
    case SWITCH_STMT:
652
      gimplify_switch_stmt (expr_p, pre_p);
653
      ret = GS_OK;
654
      break;
655
 
656
    case OMP_FOR:
657
      ret = cp_gimplify_omp_for (expr_p, pre_p);
658
      break;
659
 
660
    case CONTINUE_STMT:
661
      gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN));
662
      gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue)));
663
      *expr_p = NULL_TREE;
664
      ret = GS_ALL_DONE;
665
      break;
666
 
667
    case BREAK_STMT:
668
      gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break)));
669
      *expr_p = NULL_TREE;
670
      ret = GS_ALL_DONE;
671
      break;
672
 
673
    case EXPR_STMT:
674
      gimplify_expr_stmt (expr_p);
675
      ret = GS_OK;
676
      break;
677
 
678
    case UNARY_PLUS_EXPR:
679
      {
680
        tree arg = TREE_OPERAND (*expr_p, 0);
681
        tree type = TREE_TYPE (*expr_p);
682
        *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
683
                                            : arg;
684
        ret = GS_OK;
685
      }
686
      break;
687
 
688
    default:
689
      ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
690
      break;
691
    }
692
 
693
  /* Restore saved state.  */
694
  if (STATEMENT_CODE_P (code))
695
    current_stmt_tree ()->stmts_are_full_exprs_p
696
      = saved_stmts_are_full_exprs_p;
697
 
698
  return ret;
699
}
700
 
701
static inline bool
702
is_invisiref_parm (const_tree t)
703
{
704
  return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
705
          && DECL_BY_REFERENCE (t));
706
}
707
 
708
/* Return true if the uid in both int tree maps are equal.  */
709
 
710
int
711
cxx_int_tree_map_eq (const void *va, const void *vb)
712
{
713
  const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
714
  const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
715
  return (a->uid == b->uid);
716
}
717
 
718
/* Hash a UID in a cxx_int_tree_map.  */
719
 
720
unsigned int
721
cxx_int_tree_map_hash (const void *item)
722
{
723
  return ((const struct cxx_int_tree_map *)item)->uid;
724
}
725
 
726
/* A stable comparison routine for use with splay trees and DECLs.  */
727
 
728
static int
729
splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
730
{
731
  tree a = (tree) xa;
732
  tree b = (tree) xb;
733
 
734
  return DECL_UID (a) - DECL_UID (b);
735
}
736
 
737
/* OpenMP context during genericization.  */
738
 
739
struct cp_genericize_omp_taskreg
740
{
741
  bool is_parallel;
742
  bool default_shared;
743
  struct cp_genericize_omp_taskreg *outer;
744
  splay_tree variables;
745
};
746
 
747
/* Return true if genericization should try to determine if
748
   DECL is firstprivate or shared within task regions.  */
749
 
750
static bool
751
omp_var_to_track (tree decl)
752
{
753
  tree type = TREE_TYPE (decl);
754
  if (is_invisiref_parm (decl))
755
    type = TREE_TYPE (type);
756
  while (TREE_CODE (type) == ARRAY_TYPE)
757
    type = TREE_TYPE (type);
758
  if (type == error_mark_node || !CLASS_TYPE_P (type))
759
    return false;
760
  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
761
    return false;
762
  if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
763
    return false;
764
  return true;
765
}
766
 
767
/* Note DECL use in OpenMP region OMP_CTX during genericization.  */
768
 
769
static void
770
omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
771
{
772
  splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
773
                                         (splay_tree_key) decl);
774
  if (n == NULL)
775
    {
776
      int flags = OMP_CLAUSE_DEFAULT_SHARED;
777
      if (omp_ctx->outer)
778
        omp_cxx_notice_variable (omp_ctx->outer, decl);
779
      if (!omp_ctx->default_shared)
780
        {
781
          struct cp_genericize_omp_taskreg *octx;
782
 
783
          for (octx = omp_ctx->outer; octx; octx = octx->outer)
784
            {
785
              n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
786
              if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
787
                {
788
                  flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
789
                  break;
790
                }
791
              if (octx->is_parallel)
792
                break;
793
            }
794
          if (octx == NULL
795
              && (TREE_CODE (decl) == PARM_DECL
796
                  || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
797
                      && DECL_CONTEXT (decl) == current_function_decl)))
798
            flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
799
          if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
800
            {
801
              /* DECL is implicitly determined firstprivate in
802
                 the current task construct.  Ensure copy ctor and
803
                 dtor are instantiated, because during gimplification
804
                 it will be already too late.  */
805
              tree type = TREE_TYPE (decl);
806
              if (is_invisiref_parm (decl))
807
                type = TREE_TYPE (type);
808
              while (TREE_CODE (type) == ARRAY_TYPE)
809
                type = TREE_TYPE (type);
810
              get_copy_ctor (type, tf_none);
811
              get_dtor (type, tf_none);
812
            }
813
        }
814
      splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
815
    }
816
}
817
 
818
/* Genericization context.  */
819
 
820
struct cp_genericize_data
821
{
822
  struct pointer_set_t *p_set;
823
  VEC (tree, heap) *bind_expr_stack;
824
  struct cp_genericize_omp_taskreg *omp_ctx;
825
};
826
 
827
/* Perform any pre-gimplification lowering of C++ front end trees to
828
   GENERIC.  */
829
 
830
static tree
831
cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
832
{
833
  tree stmt = *stmt_p;
834
  struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
835
  struct pointer_set_t *p_set = wtd->p_set;
836
 
837
  /* If in an OpenMP context, note var uses.  */
838
  if (__builtin_expect (wtd->omp_ctx != NULL, 0)
839
      && (TREE_CODE (stmt) == VAR_DECL
840
          || TREE_CODE (stmt) == PARM_DECL
841
          || TREE_CODE (stmt) == RESULT_DECL)
842
      && omp_var_to_track (stmt))
843
    omp_cxx_notice_variable (wtd->omp_ctx, stmt);
844
 
845
  if (is_invisiref_parm (stmt)
846
      /* Don't dereference parms in a thunk, pass the references through. */
847
      && !(DECL_THUNK_P (current_function_decl)
848
           && TREE_CODE (stmt) == PARM_DECL))
849
    {
850
      *stmt_p = convert_from_reference (stmt);
851
      *walk_subtrees = 0;
852
      return NULL;
853
    }
854
 
855
  /* Map block scope extern declarations to visible declarations with the
856
     same name and type in outer scopes if any.  */
857
  if (cp_function_chain->extern_decl_map
858
      && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
859
      && DECL_EXTERNAL (stmt))
860
    {
861
      struct cxx_int_tree_map *h, in;
862
      in.uid = DECL_UID (stmt);
863
      h = (struct cxx_int_tree_map *)
864
          htab_find_with_hash (cp_function_chain->extern_decl_map,
865
                               &in, in.uid);
866
      if (h)
867
        {
868
          *stmt_p = h->to;
869
          *walk_subtrees = 0;
870
          return NULL;
871
        }
872
    }
873
 
874
  /* Other than invisiref parms, don't walk the same tree twice.  */
875
  if (pointer_set_contains (p_set, stmt))
876
    {
877
      *walk_subtrees = 0;
878
      return NULL_TREE;
879
    }
880
 
881
  if (TREE_CODE (stmt) == ADDR_EXPR
882
      && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
883
    {
884
      /* If in an OpenMP context, note var uses.  */
885
      if (__builtin_expect (wtd->omp_ctx != NULL, 0)
886
          && omp_var_to_track (TREE_OPERAND (stmt, 0)))
887
        omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
888
      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
889
      *walk_subtrees = 0;
890
    }
891
  else if (TREE_CODE (stmt) == RETURN_EXPR
892
           && TREE_OPERAND (stmt, 0)
893
           && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
894
    /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
895
    *walk_subtrees = 0;
896
  else if (TREE_CODE (stmt) == OMP_CLAUSE)
897
    switch (OMP_CLAUSE_CODE (stmt))
898
      {
899
      case OMP_CLAUSE_LASTPRIVATE:
900
        /* Don't dereference an invisiref in OpenMP clauses.  */
901
        if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
902
          {
903
            *walk_subtrees = 0;
904
            if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
905
              cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
906
                            cp_genericize_r, data, NULL);
907
          }
908
        break;
909
      case OMP_CLAUSE_PRIVATE:
910
        /* Don't dereference an invisiref in OpenMP clauses.  */
911
        if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
912
          *walk_subtrees = 0;
913
        else if (wtd->omp_ctx != NULL)
914
          {
915
            /* Private clause doesn't cause any references to the
916
               var in outer contexts, avoid calling
917
               omp_cxx_notice_variable for it.  */
918
            struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
919
            wtd->omp_ctx = NULL;
920
            cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
921
                          data, NULL);
922
            wtd->omp_ctx = old;
923
            *walk_subtrees = 0;
924
          }
925
        break;
926
      case OMP_CLAUSE_SHARED:
927
      case OMP_CLAUSE_FIRSTPRIVATE:
928
      case OMP_CLAUSE_COPYIN:
929
      case OMP_CLAUSE_COPYPRIVATE:
930
        /* Don't dereference an invisiref in OpenMP clauses.  */
931
        if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
932
          *walk_subtrees = 0;
933
        break;
934
      case OMP_CLAUSE_REDUCTION:
935
        gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
936
        break;
937
      default:
938
        break;
939
      }
940
  else if (IS_TYPE_OR_DECL_P (stmt))
941
    *walk_subtrees = 0;
942
 
943
  /* Due to the way voidify_wrapper_expr is written, we don't get a chance
944
     to lower this construct before scanning it, so we need to lower these
945
     before doing anything else.  */
946
  else if (TREE_CODE (stmt) == CLEANUP_STMT)
947
    *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
948
                                             : TRY_FINALLY_EXPR,
949
                      void_type_node,
950
                      CLEANUP_BODY (stmt),
951
                      CLEANUP_EXPR (stmt));
952
 
953
  else if (TREE_CODE (stmt) == IF_STMT)
954
    {
955
      genericize_if_stmt (stmt_p);
956
      /* *stmt_p has changed, tail recurse to handle it again.  */
957
      return cp_genericize_r (stmt_p, walk_subtrees, data);
958
    }
959
 
960
  /* COND_EXPR might have incompatible types in branches if one or both
961
     arms are bitfields.  Fix it up now.  */
962
  else if (TREE_CODE (stmt) == COND_EXPR)
963
    {
964
      tree type_left
965
        = (TREE_OPERAND (stmt, 1)
966
           ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
967
           : NULL_TREE);
968
      tree type_right
969
        = (TREE_OPERAND (stmt, 2)
970
           ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
971
           : NULL_TREE);
972
      if (type_left
973
          && !useless_type_conversion_p (TREE_TYPE (stmt),
974
                                         TREE_TYPE (TREE_OPERAND (stmt, 1))))
975
        {
976
          TREE_OPERAND (stmt, 1)
977
            = fold_convert (type_left, TREE_OPERAND (stmt, 1));
978
          gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
979
                                                 type_left));
980
        }
981
      if (type_right
982
          && !useless_type_conversion_p (TREE_TYPE (stmt),
983
                                         TREE_TYPE (TREE_OPERAND (stmt, 2))))
984
        {
985
          TREE_OPERAND (stmt, 2)
986
            = fold_convert (type_right, TREE_OPERAND (stmt, 2));
987
          gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
988
                                                 type_right));
989
        }
990
    }
991
 
992
  else if (TREE_CODE (stmt) == BIND_EXPR)
993
    {
994
      if (__builtin_expect (wtd->omp_ctx != NULL, 0))
995
        {
996
          tree decl;
997
          for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
998
            if (TREE_CODE (decl) == VAR_DECL
999
                && !DECL_EXTERNAL (decl)
1000
                && omp_var_to_track (decl))
1001
              {
1002
                splay_tree_node n
1003
                  = splay_tree_lookup (wtd->omp_ctx->variables,
1004
                                       (splay_tree_key) decl);
1005
                if (n == NULL)
1006
                  splay_tree_insert (wtd->omp_ctx->variables,
1007
                                     (splay_tree_key) decl,
1008
                                     TREE_STATIC (decl)
1009
                                     ? OMP_CLAUSE_DEFAULT_SHARED
1010
                                     : OMP_CLAUSE_DEFAULT_PRIVATE);
1011
              }
1012
        }
1013
      VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt);
1014
      cp_walk_tree (&BIND_EXPR_BODY (stmt),
1015
                    cp_genericize_r, data, NULL);
1016
      VEC_pop (tree, wtd->bind_expr_stack);
1017
    }
1018
 
1019
  else if (TREE_CODE (stmt) == USING_STMT)
1020
    {
1021
      tree block = NULL_TREE;
1022
 
1023
      /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1024
         BLOCK, and append an IMPORTED_DECL to its
1025
         BLOCK_VARS chained list.  */
1026
      if (wtd->bind_expr_stack)
1027
        {
1028
          int i;
1029
          for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--)
1030
            if ((block = BIND_EXPR_BLOCK (VEC_index (tree,
1031
                                                     wtd->bind_expr_stack, i))))
1032
              break;
1033
        }
1034
      if (block)
1035
        {
1036
          tree using_directive;
1037
          gcc_assert (TREE_OPERAND (stmt, 0));
1038
 
1039
          using_directive = make_node (IMPORTED_DECL);
1040
          TREE_TYPE (using_directive) = void_type_node;
1041
 
1042
          IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
1043
            = TREE_OPERAND (stmt, 0);
1044
          DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1045
          BLOCK_VARS (block) = using_directive;
1046
        }
1047
      /* The USING_STMT won't appear in GENERIC.  */
1048
      *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1049
      *walk_subtrees = 0;
1050
    }
1051
 
1052
  else if (TREE_CODE (stmt) == DECL_EXPR
1053
           && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1054
    {
1055
      /* Using decls inside DECL_EXPRs are just dropped on the floor.  */
1056
      *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1057
      *walk_subtrees = 0;
1058
    }
1059
  else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
1060
    {
1061
      struct cp_genericize_omp_taskreg omp_ctx;
1062
      tree c, decl;
1063
      splay_tree_node n;
1064
 
1065
      *walk_subtrees = 0;
1066
      cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1067
      omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1068
      omp_ctx.default_shared = omp_ctx.is_parallel;
1069
      omp_ctx.outer = wtd->omp_ctx;
1070
      omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1071
      wtd->omp_ctx = &omp_ctx;
1072
      for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1073
        switch (OMP_CLAUSE_CODE (c))
1074
          {
1075
          case OMP_CLAUSE_SHARED:
1076
          case OMP_CLAUSE_PRIVATE:
1077
          case OMP_CLAUSE_FIRSTPRIVATE:
1078
          case OMP_CLAUSE_LASTPRIVATE:
1079
            decl = OMP_CLAUSE_DECL (c);
1080
            if (decl == error_mark_node || !omp_var_to_track (decl))
1081
              break;
1082
            n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1083
            if (n != NULL)
1084
              break;
1085
            splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1086
                               OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1087
                               ? OMP_CLAUSE_DEFAULT_SHARED
1088
                               : OMP_CLAUSE_DEFAULT_PRIVATE);
1089
            if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
1090
                && omp_ctx.outer)
1091
              omp_cxx_notice_variable (omp_ctx.outer, decl);
1092
            break;
1093
          case OMP_CLAUSE_DEFAULT:
1094
            if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1095
              omp_ctx.default_shared = true;
1096
          default:
1097
            break;
1098
          }
1099
      cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1100
      wtd->omp_ctx = omp_ctx.outer;
1101
      splay_tree_delete (omp_ctx.variables);
1102
    }
1103
  else if (TREE_CODE (stmt) == CONVERT_EXPR)
1104
    gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
1105
 
1106
  pointer_set_insert (p_set, *stmt_p);
1107
 
1108
  return NULL;
1109
}
1110
 
1111
void
1112
cp_genericize (tree fndecl)
1113
{
1114
  tree t;
1115
  struct cp_genericize_data wtd;
1116
 
1117
  /* Fix up the types of parms passed by invisible reference.  */
1118
  for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
1119
    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
1120
      {
1121
        /* If a function's arguments are copied to create a thunk,
1122
           then DECL_BY_REFERENCE will be set -- but the type of the
1123
           argument will be a pointer type, so we will never get
1124
           here.  */
1125
        gcc_assert (!DECL_BY_REFERENCE (t));
1126
        gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
1127
        TREE_TYPE (t) = DECL_ARG_TYPE (t);
1128
        DECL_BY_REFERENCE (t) = 1;
1129
        TREE_ADDRESSABLE (t) = 0;
1130
        relayout_decl (t);
1131
      }
1132
 
1133
  /* Do the same for the return value.  */
1134
  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
1135
    {
1136
      t = DECL_RESULT (fndecl);
1137
      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
1138
      DECL_BY_REFERENCE (t) = 1;
1139
      TREE_ADDRESSABLE (t) = 0;
1140
      relayout_decl (t);
1141
      if (DECL_NAME (t))
1142
        {
1143
          /* Adjust DECL_VALUE_EXPR of the original var.  */
1144
          tree outer = outer_curly_brace_block (current_function_decl);
1145
          tree var;
1146
 
1147
          if (outer)
1148
            for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1149
              if (DECL_NAME (t) == DECL_NAME (var)
1150
                  && DECL_HAS_VALUE_EXPR_P (var)
1151
                  && DECL_VALUE_EXPR (var) == t)
1152
                {
1153
                  tree val = convert_from_reference (t);
1154
                  SET_DECL_VALUE_EXPR (var, val);
1155
                  break;
1156
                }
1157
        }
1158
    }
1159
 
1160
  /* If we're a clone, the body is already GIMPLE.  */
1161
  if (DECL_CLONED_FUNCTION_P (fndecl))
1162
    return;
1163
 
1164
  /* We do want to see every occurrence of the parms, so we can't just use
1165
     walk_tree's hash functionality.  */
1166
  wtd.p_set = pointer_set_create ();
1167
  wtd.bind_expr_stack = NULL;
1168
  wtd.omp_ctx = NULL;
1169
  cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL);
1170
  pointer_set_destroy (wtd.p_set);
1171
  VEC_free (tree, heap, wtd.bind_expr_stack);
1172
 
1173
  /* Do everything else.  */
1174
  c_genericize (fndecl);
1175
 
1176
  gcc_assert (bc_label[bc_break] == NULL);
1177
  gcc_assert (bc_label[bc_continue] == NULL);
1178
}
1179
 
1180
/* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
1181
   NULL if there is in fact nothing to do.  ARG2 may be null if FN
1182
   actually only takes one argument.  */
1183
 
1184
static tree
1185
cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
1186
{
1187
  tree defparm, parm, t;
1188
  int i = 0;
1189
  int nargs;
1190
  tree *argarray;
1191
 
1192
  if (fn == NULL)
1193
    return NULL;
1194
 
1195
  nargs = list_length (DECL_ARGUMENTS (fn));
1196
  argarray = XALLOCAVEC (tree, nargs);
1197
 
1198
  defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
1199
  if (arg2)
1200
    defparm = TREE_CHAIN (defparm);
1201
 
1202
  if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
1203
    {
1204
      tree inner_type = TREE_TYPE (arg1);
1205
      tree start1, end1, p1;
1206
      tree start2 = NULL, p2 = NULL;
1207
      tree ret = NULL, lab;
1208
 
1209
      start1 = arg1;
1210
      start2 = arg2;
1211
      do
1212
        {
1213
          inner_type = TREE_TYPE (inner_type);
1214
          start1 = build4 (ARRAY_REF, inner_type, start1,
1215
                           size_zero_node, NULL, NULL);
1216
          if (arg2)
1217
            start2 = build4 (ARRAY_REF, inner_type, start2,
1218
                             size_zero_node, NULL, NULL);
1219
        }
1220
      while (TREE_CODE (inner_type) == ARRAY_TYPE);
1221
      start1 = build_fold_addr_expr_loc (input_location, start1);
1222
      if (arg2)
1223
        start2 = build_fold_addr_expr_loc (input_location, start2);
1224
 
1225
      end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
1226
      end1 = fold_build_pointer_plus (start1, end1);
1227
 
1228
      p1 = create_tmp_var (TREE_TYPE (start1), NULL);
1229
      t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
1230
      append_to_statement_list (t, &ret);
1231
 
1232
      if (arg2)
1233
        {
1234
          p2 = create_tmp_var (TREE_TYPE (start2), NULL);
1235
          t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
1236
          append_to_statement_list (t, &ret);
1237
        }
1238
 
1239
      lab = create_artificial_label (input_location);
1240
      t = build1 (LABEL_EXPR, void_type_node, lab);
1241
      append_to_statement_list (t, &ret);
1242
 
1243
      argarray[i++] = p1;
1244
      if (arg2)
1245
        argarray[i++] = p2;
1246
      /* Handle default arguments.  */
1247
      for (parm = defparm; parm && parm != void_list_node;
1248
           parm = TREE_CHAIN (parm), i++)
1249
        argarray[i] = convert_default_arg (TREE_VALUE (parm),
1250
                                           TREE_PURPOSE (parm), fn, i);
1251
      t = build_call_a (fn, i, argarray);
1252
      t = fold_convert (void_type_node, t);
1253
      t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1254
      append_to_statement_list (t, &ret);
1255
 
1256
      t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
1257
      t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
1258
      append_to_statement_list (t, &ret);
1259
 
1260
      if (arg2)
1261
        {
1262
          t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
1263
          t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
1264
          append_to_statement_list (t, &ret);
1265
        }
1266
 
1267
      t = build2 (NE_EXPR, boolean_type_node, p1, end1);
1268
      t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
1269
      append_to_statement_list (t, &ret);
1270
 
1271
      return ret;
1272
    }
1273
  else
1274
    {
1275
      argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
1276
      if (arg2)
1277
        argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
1278
      /* Handle default arguments.  */
1279
      for (parm = defparm; parm && parm != void_list_node;
1280
           parm = TREE_CHAIN (parm), i++)
1281
        argarray[i] = convert_default_arg (TREE_VALUE (parm),
1282
                                           TREE_PURPOSE (parm),
1283
                                           fn, i);
1284
      t = build_call_a (fn, i, argarray);
1285
      t = fold_convert (void_type_node, t);
1286
      return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1287
    }
1288
}
1289
 
1290
/* Return code to initialize DECL with its default constructor, or
1291
   NULL if there's nothing to do.  */
1292
 
1293
tree
1294
cxx_omp_clause_default_ctor (tree clause, tree decl,
1295
                             tree outer ATTRIBUTE_UNUSED)
1296
{
1297
  tree info = CP_OMP_CLAUSE_INFO (clause);
1298
  tree ret = NULL;
1299
 
1300
  if (info)
1301
    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1302
 
1303
  return ret;
1304
}
1305
 
1306
/* Return code to initialize DST with a copy constructor from SRC.  */
1307
 
1308
tree
1309
cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1310
{
1311
  tree info = CP_OMP_CLAUSE_INFO (clause);
1312
  tree ret = NULL;
1313
 
1314
  if (info)
1315
    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1316
  if (ret == NULL)
1317
    ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1318
 
1319
  return ret;
1320
}
1321
 
1322
/* Similarly, except use an assignment operator instead.  */
1323
 
1324
tree
1325
cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1326
{
1327
  tree info = CP_OMP_CLAUSE_INFO (clause);
1328
  tree ret = NULL;
1329
 
1330
  if (info)
1331
    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1332
  if (ret == NULL)
1333
    ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1334
 
1335
  return ret;
1336
}
1337
 
1338
/* Return code to destroy DECL.  */
1339
 
1340
tree
1341
cxx_omp_clause_dtor (tree clause, tree decl)
1342
{
1343
  tree info = CP_OMP_CLAUSE_INFO (clause);
1344
  tree ret = NULL;
1345
 
1346
  if (info)
1347
    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1348
 
1349
  return ret;
1350
}
1351
 
1352
/* True if OpenMP should privatize what this DECL points to rather
1353
   than the DECL itself.  */
1354
 
1355
bool
1356
cxx_omp_privatize_by_reference (const_tree decl)
1357
{
1358
  return is_invisiref_parm (decl);
1359
}
1360
 
1361
/* Return true if DECL is const qualified var having no mutable member.  */
1362
bool
1363
cxx_omp_const_qual_no_mutable (tree decl)
1364
{
1365
  tree type = TREE_TYPE (decl);
1366
  if (TREE_CODE (type) == REFERENCE_TYPE)
1367
    {
1368
      if (!is_invisiref_parm (decl))
1369
        return false;
1370
      type = TREE_TYPE (type);
1371
 
1372
      if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1373
        {
1374
          /* NVR doesn't preserve const qualification of the
1375
             variable's type.  */
1376
          tree outer = outer_curly_brace_block (current_function_decl);
1377
          tree var;
1378
 
1379
          if (outer)
1380
            for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1381
              if (DECL_NAME (decl) == DECL_NAME (var)
1382
                  && (TYPE_MAIN_VARIANT (type)
1383
                      == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1384
                {
1385
                  if (TYPE_READONLY (TREE_TYPE (var)))
1386
                    type = TREE_TYPE (var);
1387
                  break;
1388
                }
1389
        }
1390
    }
1391
 
1392
  if (type == error_mark_node)
1393
    return false;
1394
 
1395
  /* Variables with const-qualified type having no mutable member
1396
     are predetermined shared.  */
1397
  if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1398
    return true;
1399
 
1400
  return false;
1401
}
1402
 
1403
/* True if OpenMP sharing attribute of DECL is predetermined.  */
1404
 
1405
enum omp_clause_default_kind
1406
cxx_omp_predetermined_sharing (tree decl)
1407
{
1408
  /* Static data members are predetermined shared.  */
1409
  if (TREE_STATIC (decl))
1410
    {
1411
      tree ctx = CP_DECL_CONTEXT (decl);
1412
      if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1413
        return OMP_CLAUSE_DEFAULT_SHARED;
1414
    }
1415
 
1416
  /* Const qualified vars having no mutable member are predetermined
1417
     shared.  */
1418
  if (cxx_omp_const_qual_no_mutable (decl))
1419
    return OMP_CLAUSE_DEFAULT_SHARED;
1420
 
1421
  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1422
}
1423
 
1424
/* Finalize an implicitly determined clause.  */
1425
 
1426
void
1427
cxx_omp_finish_clause (tree c)
1428
{
1429
  tree decl, inner_type;
1430
  bool make_shared = false;
1431
 
1432
  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1433
    return;
1434
 
1435
  decl = OMP_CLAUSE_DECL (c);
1436
  decl = require_complete_type (decl);
1437
  inner_type = TREE_TYPE (decl);
1438
  if (decl == error_mark_node)
1439
    make_shared = true;
1440
  else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1441
    {
1442
      if (is_invisiref_parm (decl))
1443
        inner_type = TREE_TYPE (inner_type);
1444
      else
1445
        {
1446
          error ("%qE implicitly determined as %<firstprivate%> has reference type",
1447
                 decl);
1448
          make_shared = true;
1449
        }
1450
    }
1451
 
1452
  /* We're interested in the base element, not arrays.  */
1453
  while (TREE_CODE (inner_type) == ARRAY_TYPE)
1454
    inner_type = TREE_TYPE (inner_type);
1455
 
1456
  /* Check for special function availability by building a call to one.
1457
     Save the results, because later we won't be in the right context
1458
     for making these queries.  */
1459
  if (!make_shared
1460
      && CLASS_TYPE_P (inner_type)
1461
      && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1462
    make_shared = true;
1463
 
1464
  if (make_shared)
1465
    OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
1466
}

powered by: WebSVN 2.1.0

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