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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [fortran/] [trans.c] - Blame information for rev 867

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

Line No. Rev Author Line
1 712 jeremybenn
/* Code translation -- generate GCC trees from gfc_code.
2
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
3
   Free Software Foundation, Inc.
4
   Contributed by Paul Brook
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 3, 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 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 "tree.h"
26
#include "gimple.h"     /* For create_tmp_var_raw.  */
27
#include "tree-iterator.h"
28
#include "diagnostic-core.h"  /* For internal_error.  */
29
#include "defaults.h"
30
#include "flags.h"
31
#include "gfortran.h"
32
#include "trans.h"
33
#include "trans-stmt.h"
34
#include "trans-array.h"
35
#include "trans-types.h"
36
#include "trans-const.h"
37
 
38
/* Naming convention for backend interface code:
39
 
40
   gfc_trans_*  translate gfc_code into STMT trees.
41
 
42
   gfc_conv_*   expression conversion
43
 
44
   gfc_get_*    get a backend tree representation of a decl or type  */
45
 
46
static gfc_file *gfc_current_backend_file;
47
 
48
const char gfc_msg_fault[] = N_("Array reference out of bounds");
49
const char gfc_msg_wrong_return[] = N_("Incorrect function return value");
50
 
51
 
52
/* Advance along TREE_CHAIN n times.  */
53
 
54
tree
55
gfc_advance_chain (tree t, int n)
56
{
57
  for (; n > 0; n--)
58
    {
59
      gcc_assert (t != NULL_TREE);
60
      t = DECL_CHAIN (t);
61
    }
62
  return t;
63
}
64
 
65
 
66
/* Strip off a legitimate source ending from the input
67
   string NAME of length LEN.  */
68
 
69
static inline void
70
remove_suffix (char *name, int len)
71
{
72
  int i;
73
 
74
  for (i = 2; i < 8 && len > i; i++)
75
    {
76
      if (name[len - i] == '.')
77
        {
78
          name[len - i] = '\0';
79
          break;
80
        }
81
    }
82
}
83
 
84
 
85
/* Creates a variable declaration with a given TYPE.  */
86
 
87
tree
88
gfc_create_var_np (tree type, const char *prefix)
89
{
90
  tree t;
91
 
92
  t = create_tmp_var_raw (type, prefix);
93
 
94
  /* No warnings for anonymous variables.  */
95
  if (prefix == NULL)
96
    TREE_NO_WARNING (t) = 1;
97
 
98
  return t;
99
}
100
 
101
 
102
/* Like above, but also adds it to the current scope.  */
103
 
104
tree
105
gfc_create_var (tree type, const char *prefix)
106
{
107
  tree tmp;
108
 
109
  tmp = gfc_create_var_np (type, prefix);
110
 
111
  pushdecl (tmp);
112
 
113
  return tmp;
114
}
115
 
116
 
117
/* If the expression is not constant, evaluate it now.  We assign the
118
   result of the expression to an artificially created variable VAR, and
119
   return a pointer to the VAR_DECL node for this variable.  */
120
 
121
tree
122
gfc_evaluate_now_loc (location_t loc, tree expr, stmtblock_t * pblock)
123
{
124
  tree var;
125
 
126
  if (CONSTANT_CLASS_P (expr))
127
    return expr;
128
 
129
  var = gfc_create_var (TREE_TYPE (expr), NULL);
130
  gfc_add_modify_loc (loc, pblock, var, expr);
131
 
132
  return var;
133
}
134
 
135
 
136
tree
137
gfc_evaluate_now (tree expr, stmtblock_t * pblock)
138
{
139
  return gfc_evaluate_now_loc (input_location, expr, pblock);
140
}
141
 
142
 
143
/* Build a MODIFY_EXPR node and add it to a given statement block PBLOCK.
144
   A MODIFY_EXPR is an assignment:
145
   LHS <- RHS.  */
146
 
147
void
148
gfc_add_modify_loc (location_t loc, stmtblock_t * pblock, tree lhs, tree rhs)
149
{
150
  tree tmp;
151
 
152
#ifdef ENABLE_CHECKING
153
  tree t1, t2;
154
  t1 = TREE_TYPE (rhs);
155
  t2 = TREE_TYPE (lhs);
156
  /* Make sure that the types of the rhs and the lhs are the same
157
     for scalar assignments.  We should probably have something
158
     similar for aggregates, but right now removing that check just
159
     breaks everything.  */
160
  gcc_assert (t1 == t2
161
              || AGGREGATE_TYPE_P (TREE_TYPE (lhs)));
162
#endif
163
 
164
  tmp = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, lhs,
165
                         rhs);
166
  gfc_add_expr_to_block (pblock, tmp);
167
}
168
 
169
 
170
void
171
gfc_add_modify (stmtblock_t * pblock, tree lhs, tree rhs)
172
{
173
  gfc_add_modify_loc (input_location, pblock, lhs, rhs);
174
}
175
 
176
 
177
/* Create a new scope/binding level and initialize a block.  Care must be
178
   taken when translating expressions as any temporaries will be placed in
179
   the innermost scope.  */
180
 
181
void
182
gfc_start_block (stmtblock_t * block)
183
{
184
  /* Start a new binding level.  */
185
  pushlevel (0);
186
  block->has_scope = 1;
187
 
188
  /* The block is empty.  */
189
  block->head = NULL_TREE;
190
}
191
 
192
 
193
/* Initialize a block without creating a new scope.  */
194
 
195
void
196
gfc_init_block (stmtblock_t * block)
197
{
198
  block->head = NULL_TREE;
199
  block->has_scope = 0;
200
}
201
 
202
 
203
/* Sometimes we create a scope but it turns out that we don't actually
204
   need it.  This function merges the scope of BLOCK with its parent.
205
   Only variable decls will be merged, you still need to add the code.  */
206
 
207
void
208
gfc_merge_block_scope (stmtblock_t * block)
209
{
210
  tree decl;
211
  tree next;
212
 
213
  gcc_assert (block->has_scope);
214
  block->has_scope = 0;
215
 
216
  /* Remember the decls in this scope.  */
217
  decl = getdecls ();
218
  poplevel (0, 0, 0);
219
 
220
  /* Add them to the parent scope.  */
221
  while (decl != NULL_TREE)
222
    {
223
      next = DECL_CHAIN (decl);
224
      DECL_CHAIN (decl) = NULL_TREE;
225
 
226
      pushdecl (decl);
227
      decl = next;
228
    }
229
}
230
 
231
 
232
/* Finish a scope containing a block of statements.  */
233
 
234
tree
235
gfc_finish_block (stmtblock_t * stmtblock)
236
{
237
  tree decl;
238
  tree expr;
239
  tree block;
240
 
241
  expr = stmtblock->head;
242
  if (!expr)
243
    expr = build_empty_stmt (input_location);
244
 
245
  stmtblock->head = NULL_TREE;
246
 
247
  if (stmtblock->has_scope)
248
    {
249
      decl = getdecls ();
250
 
251
      if (decl)
252
        {
253
          block = poplevel (1, 0, 0);
254
          expr = build3_v (BIND_EXPR, decl, expr, block);
255
        }
256
      else
257
        poplevel (0, 0, 0);
258
    }
259
 
260
  return expr;
261
}
262
 
263
 
264
/* Build an ADDR_EXPR and cast the result to TYPE.  If TYPE is NULL, the
265
   natural type is used.  */
266
 
267
tree
268
gfc_build_addr_expr (tree type, tree t)
269
{
270
  tree base_type = TREE_TYPE (t);
271
  tree natural_type;
272
 
273
  if (type && POINTER_TYPE_P (type)
274
      && TREE_CODE (base_type) == ARRAY_TYPE
275
      && TYPE_MAIN_VARIANT (TREE_TYPE (type))
276
         == TYPE_MAIN_VARIANT (TREE_TYPE (base_type)))
277
    {
278
      tree min_val = size_zero_node;
279
      tree type_domain = TYPE_DOMAIN (base_type);
280
      if (type_domain && TYPE_MIN_VALUE (type_domain))
281
        min_val = TYPE_MIN_VALUE (type_domain);
282
      t = fold (build4_loc (input_location, ARRAY_REF, TREE_TYPE (type),
283
                            t, min_val, NULL_TREE, NULL_TREE));
284
      natural_type = type;
285
    }
286
  else
287
    natural_type = build_pointer_type (base_type);
288
 
289
  if (TREE_CODE (t) == INDIRECT_REF)
290
    {
291
      if (!type)
292
        type = natural_type;
293
      t = TREE_OPERAND (t, 0);
294
      natural_type = TREE_TYPE (t);
295
    }
296
  else
297
    {
298
      tree base = get_base_address (t);
299
      if (base && DECL_P (base))
300
        TREE_ADDRESSABLE (base) = 1;
301
      t = fold_build1_loc (input_location, ADDR_EXPR, natural_type, t);
302
    }
303
 
304
  if (type && natural_type != type)
305
    t = convert (type, t);
306
 
307
  return t;
308
}
309
 
310
 
311
/* Build an ARRAY_REF with its natural type.  */
312
 
313
tree
314
gfc_build_array_ref (tree base, tree offset, tree decl)
315
{
316
  tree type = TREE_TYPE (base);
317
  tree tmp;
318
  tree span;
319
 
320
  if (GFC_ARRAY_TYPE_P (type) && GFC_TYPE_ARRAY_RANK (type) == 0)
321
    {
322
      gcc_assert (GFC_TYPE_ARRAY_CORANK (type) > 0);
323
 
324
      return fold_convert (TYPE_MAIN_VARIANT (type), base);
325
    }
326
 
327
  /* Scalar coarray, there is nothing to do.  */
328
  if (TREE_CODE (type) != ARRAY_TYPE)
329
    {
330
      gcc_assert (decl == NULL_TREE);
331
      gcc_assert (integer_zerop (offset));
332
      return base;
333
    }
334
 
335
  type = TREE_TYPE (type);
336
 
337
  if (DECL_P (base))
338
    TREE_ADDRESSABLE (base) = 1;
339
 
340
  /* Strip NON_LVALUE_EXPR nodes.  */
341
  STRIP_TYPE_NOPS (offset);
342
 
343
  /* If the array reference is to a pointer, whose target contains a
344
     subreference, use the span that is stored with the backend decl
345
     and reference the element with pointer arithmetic.  */
346
  if (decl && (TREE_CODE (decl) == FIELD_DECL
347
                 || TREE_CODE (decl) == VAR_DECL
348
                 || TREE_CODE (decl) == PARM_DECL)
349
        && ((GFC_DECL_SUBREF_ARRAY_P (decl)
350
              && !integer_zerop (GFC_DECL_SPAN(decl)))
351
           || GFC_DECL_CLASS (decl)))
352
    {
353
      if (GFC_DECL_CLASS (decl))
354
        {
355
          /* Allow for dummy arguments and other good things.  */
356
          if (POINTER_TYPE_P (TREE_TYPE (decl)))
357
            decl = build_fold_indirect_ref_loc (input_location, decl);
358
 
359
          /* Check if '_data' is an array descriptor. If it is not,
360
             the array must be one of the components of the class object,
361
             so return a normal array reference.  */
362
          if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (decl))))
363
            return build4_loc (input_location, ARRAY_REF, type, base,
364
                               offset, NULL_TREE, NULL_TREE);
365
 
366
          span = gfc_vtable_size_get (decl);
367
        }
368
      else if (GFC_DECL_SUBREF_ARRAY_P (decl))
369
        span = GFC_DECL_SPAN(decl);
370
      else
371
        gcc_unreachable ();
372
 
373
      offset = fold_build2_loc (input_location, MULT_EXPR,
374
                                gfc_array_index_type,
375
                                offset, span);
376
      tmp = gfc_build_addr_expr (pvoid_type_node, base);
377
      tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
378
      tmp = fold_convert (build_pointer_type (type), tmp);
379
      if (!TYPE_STRING_FLAG (type))
380
        tmp = build_fold_indirect_ref_loc (input_location, tmp);
381
      return tmp;
382
    }
383
  else
384
    /* Otherwise use a straightforward array reference.  */
385
    return build4_loc (input_location, ARRAY_REF, type, base, offset,
386
                       NULL_TREE, NULL_TREE);
387
}
388
 
389
 
390
/* Generate a call to print a runtime error possibly including multiple
391
   arguments and a locus.  */
392
 
393
static tree
394
trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
395
                            va_list ap)
396
{
397
  stmtblock_t block;
398
  tree tmp;
399
  tree arg, arg2;
400
  tree *argarray;
401
  tree fntype;
402
  char *message;
403
  const char *p;
404
  int line, nargs, i;
405
  location_t loc;
406
 
407
  /* Compute the number of extra arguments from the format string.  */
408
  for (p = msgid, nargs = 0; *p; p++)
409
    if (*p == '%')
410
      {
411
        p++;
412
        if (*p != '%')
413
          nargs++;
414
      }
415
 
416
  /* The code to generate the error.  */
417
  gfc_start_block (&block);
418
 
419
  if (where)
420
    {
421
      line = LOCATION_LINE (where->lb->location);
422
      asprintf (&message, "At line %d of file %s",  line,
423
                where->lb->file->filename);
424
    }
425
  else
426
    asprintf (&message, "In file '%s', around line %d",
427
              gfc_source_file, input_line + 1);
428
 
429
  arg = gfc_build_addr_expr (pchar_type_node,
430
                             gfc_build_localized_cstring_const (message));
431
  free (message);
432
 
433
  asprintf (&message, "%s", _(msgid));
434
  arg2 = gfc_build_addr_expr (pchar_type_node,
435
                              gfc_build_localized_cstring_const (message));
436
  free (message);
437
 
438
  /* Build the argument array.  */
439
  argarray = XALLOCAVEC (tree, nargs + 2);
440
  argarray[0] = arg;
441
  argarray[1] = arg2;
442
  for (i = 0; i < nargs; i++)
443
    argarray[2 + i] = va_arg (ap, tree);
444
 
445
  /* Build the function call to runtime_(warning,error)_at; because of the
446
     variable number of arguments, we can't use build_call_expr_loc dinput_location,
447
     irectly.  */
448
  if (error)
449
    fntype = TREE_TYPE (gfor_fndecl_runtime_error_at);
450
  else
451
    fntype = TREE_TYPE (gfor_fndecl_runtime_warning_at);
452
 
453
  loc = where ? where->lb->location : input_location;
454
  tmp = fold_builtin_call_array (loc, TREE_TYPE (fntype),
455
                                 fold_build1_loc (loc, ADDR_EXPR,
456
                                             build_pointer_type (fntype),
457
                                             error
458
                                             ? gfor_fndecl_runtime_error_at
459
                                             : gfor_fndecl_runtime_warning_at),
460
                                 nargs + 2, argarray);
461
  gfc_add_expr_to_block (&block, tmp);
462
 
463
  return gfc_finish_block (&block);
464
}
465
 
466
 
467
tree
468
gfc_trans_runtime_error (bool error, locus* where, const char* msgid, ...)
469
{
470
  va_list ap;
471
  tree result;
472
 
473
  va_start (ap, msgid);
474
  result = trans_runtime_error_vararg (error, where, msgid, ap);
475
  va_end (ap);
476
  return result;
477
}
478
 
479
 
480
/* Generate a runtime error if COND is true.  */
481
 
482
void
483
gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
484
                         locus * where, const char * msgid, ...)
485
{
486
  va_list ap;
487
  stmtblock_t block;
488
  tree body;
489
  tree tmp;
490
  tree tmpvar = NULL;
491
 
492
  if (integer_zerop (cond))
493
    return;
494
 
495
  if (once)
496
    {
497
       tmpvar = gfc_create_var (boolean_type_node, "print_warning");
498
       TREE_STATIC (tmpvar) = 1;
499
       DECL_INITIAL (tmpvar) = boolean_true_node;
500
       gfc_add_expr_to_block (pblock, tmpvar);
501
    }
502
 
503
  gfc_start_block (&block);
504
 
505
  /* The code to generate the error.  */
506
  va_start (ap, msgid);
507
  gfc_add_expr_to_block (&block,
508
                         trans_runtime_error_vararg (error, where,
509
                                                     msgid, ap));
510
 
511
  if (once)
512
    gfc_add_modify (&block, tmpvar, boolean_false_node);
513
 
514
  body = gfc_finish_block (&block);
515
 
516
  if (integer_onep (cond))
517
    {
518
      gfc_add_expr_to_block (pblock, body);
519
    }
520
  else
521
    {
522
      /* Tell the compiler that this isn't likely.  */
523
      if (once)
524
        cond = fold_build2_loc (where->lb->location, TRUTH_AND_EXPR,
525
                                long_integer_type_node, tmpvar, cond);
526
      else
527
        cond = fold_convert (long_integer_type_node, cond);
528
 
529
      cond = gfc_unlikely (cond);
530
      tmp = fold_build3_loc (where->lb->location, COND_EXPR, void_type_node,
531
                             cond, body,
532
                             build_empty_stmt (where->lb->location));
533
      gfc_add_expr_to_block (pblock, tmp);
534
    }
535
}
536
 
537
 
538
/* Call malloc to allocate size bytes of memory, with special conditions:
539
      + if size == 0, return a malloced area of size 1,
540
      + if malloc returns NULL, issue a runtime error.  */
541
tree
542
gfc_call_malloc (stmtblock_t * block, tree type, tree size)
543
{
544
  tree tmp, msg, malloc_result, null_result, res, malloc_tree;
545
  stmtblock_t block2;
546
 
547
  size = gfc_evaluate_now (size, block);
548
 
549
  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
550
    size = fold_convert (size_type_node, size);
551
 
552
  /* Create a variable to hold the result.  */
553
  res = gfc_create_var (prvoid_type_node, NULL);
554
 
555
  /* Call malloc.  */
556
  gfc_start_block (&block2);
557
 
558
  size = fold_build2_loc (input_location, MAX_EXPR, size_type_node, size,
559
                          build_int_cst (size_type_node, 1));
560
 
561
  malloc_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
562
  gfc_add_modify (&block2, res,
563
                  fold_convert (prvoid_type_node,
564
                                build_call_expr_loc (input_location,
565
                                                     malloc_tree, 1, size)));
566
 
567
  /* Optionally check whether malloc was successful.  */
568
  if (gfc_option.rtcheck & GFC_RTCHECK_MEM)
569
    {
570
      null_result = fold_build2_loc (input_location, EQ_EXPR,
571
                                     boolean_type_node, res,
572
                                     build_int_cst (pvoid_type_node, 0));
573
      msg = gfc_build_addr_expr (pchar_type_node,
574
              gfc_build_localized_cstring_const ("Memory allocation failed"));
575
      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
576
                             null_result,
577
              build_call_expr_loc (input_location,
578
                                   gfor_fndecl_os_error, 1, msg),
579
                                   build_empty_stmt (input_location));
580
      gfc_add_expr_to_block (&block2, tmp);
581
    }
582
 
583
  malloc_result = gfc_finish_block (&block2);
584
 
585
  gfc_add_expr_to_block (block, malloc_result);
586
 
587
  if (type != NULL)
588
    res = fold_convert (type, res);
589
  return res;
590
}
591
 
592
 
593
/* Allocate memory, using an optional status argument.
594
 
595
   This function follows the following pseudo-code:
596
 
597
    void *
598
    allocate (size_t size, integer_type stat)
599
    {
600
      void *newmem;
601
 
602
      if (stat requested)
603
        stat = 0;
604
 
605
      newmem = malloc (MAX (size, 1));
606
      if (newmem == NULL)
607
      {
608
        if (stat)
609
          *stat = LIBERROR_ALLOCATION;
610
        else
611
          runtime_error ("Allocation would exceed memory limit");
612
      }
613
      return newmem;
614
    }  */
615
void
616
gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
617
                           tree size, tree status)
618
{
619
  tree tmp, on_error, error_cond;
620
  tree status_type = status ? TREE_TYPE (status) : NULL_TREE;
621
 
622
  /* Evaluate size only once, and make sure it has the right type.  */
623
  size = gfc_evaluate_now (size, block);
624
  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
625
    size = fold_convert (size_type_node, size);
626
 
627
  /* If successful and stat= is given, set status to 0.  */
628
  if (status != NULL_TREE)
629
      gfc_add_expr_to_block (block,
630
             fold_build2_loc (input_location, MODIFY_EXPR, status_type,
631
                              status, build_int_cst (status_type, 0)));
632
 
633
  /* The allocation itself.  */
634
  gfc_add_modify (block, pointer,
635
          fold_convert (TREE_TYPE (pointer),
636
                build_call_expr_loc (input_location,
637
                             builtin_decl_explicit (BUILT_IN_MALLOC), 1,
638
                             fold_build2_loc (input_location,
639
                                      MAX_EXPR, size_type_node, size,
640
                                      build_int_cst (size_type_node, 1)))));
641
 
642
  /* What to do in case of error.  */
643
  if (status != NULL_TREE)
644
    on_error = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
645
                        status, build_int_cst (status_type, LIBERROR_ALLOCATION));
646
  else
647
    on_error = build_call_expr_loc (input_location, gfor_fndecl_os_error, 1,
648
                    gfc_build_addr_expr (pchar_type_node,
649
                                 gfc_build_localized_cstring_const
650
                                 ("Allocation would exceed memory limit")));
651
 
652
  error_cond = fold_build2_loc (input_location, EQ_EXPR,
653
                                boolean_type_node, pointer,
654
                                build_int_cst (prvoid_type_node, 0));
655
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
656
                         gfc_unlikely (error_cond), on_error,
657
                         build_empty_stmt (input_location));
658
 
659
  gfc_add_expr_to_block (block, tmp);
660
}
661
 
662
 
663
/* Allocate memory, using an optional status argument.
664
 
665
   This function follows the following pseudo-code:
666
 
667
    void *
668
    allocate (size_t size, void** token, int *stat, char* errmsg, int errlen)
669
    {
670
      void *newmem;
671
 
672
      newmem = _caf_register (size, regtype, token, &stat, errmsg, errlen);
673
      return newmem;
674
    }  */
675
static void
676
gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
677
                        tree token, tree status, tree errmsg, tree errlen)
678
{
679
  tree tmp, pstat;
680
 
681
  gcc_assert (token != NULL_TREE);
682
 
683
  /* Evaluate size only once, and make sure it has the right type.  */
684
  size = gfc_evaluate_now (size, block);
685
  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
686
    size = fold_convert (size_type_node, size);
687
 
688
  /* The allocation itself.  */
689
  if (status == NULL_TREE)
690
    pstat  = null_pointer_node;
691
  else
692
    pstat  = gfc_build_addr_expr (NULL_TREE, status);
693
 
694
  if (errmsg == NULL_TREE)
695
    {
696
      gcc_assert(errlen == NULL_TREE);
697
      errmsg = null_pointer_node;
698
      errlen = build_int_cst (integer_type_node, 0);
699
    }
700
 
701
  tmp = build_call_expr_loc (input_location,
702
             gfor_fndecl_caf_register, 6,
703
             fold_build2_loc (input_location,
704
                              MAX_EXPR, size_type_node, size,
705
                              build_int_cst (size_type_node, 1)),
706
             build_int_cst (integer_type_node,
707
                            GFC_CAF_COARRAY_ALLOC),
708
             token, pstat, errmsg, errlen);
709
 
710
  tmp = fold_build2_loc (input_location, MODIFY_EXPR,
711
                         TREE_TYPE (pointer), pointer,
712
                         fold_convert ( TREE_TYPE (pointer), tmp));
713
  gfc_add_expr_to_block (block, tmp);
714
}
715
 
716
 
717
/* Generate code for an ALLOCATE statement when the argument is an
718
   allocatable variable.  If the variable is currently allocated, it is an
719
   error to allocate it again.
720
 
721
   This function follows the following pseudo-code:
722
 
723
    void *
724
    allocate_allocatable (void *mem, size_t size, integer_type stat)
725
    {
726
      if (mem == NULL)
727
        return allocate (size, stat);
728
      else
729
      {
730
        if (stat)
731
          stat = LIBERROR_ALLOCATION;
732
        else
733
          runtime_error ("Attempting to allocate already allocated variable");
734
      }
735
    }
736
 
737
    expr must be set to the original expression being allocated for its locus
738
    and variable name in case a runtime error has to be printed.  */
739
void
740
gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
741
                          tree status, tree errmsg, tree errlen, tree label_finish,
742
                          gfc_expr* expr)
743
{
744
  stmtblock_t alloc_block;
745
  tree tmp, null_mem, alloc, error;
746
  tree type = TREE_TYPE (mem);
747
 
748
  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
749
    size = fold_convert (size_type_node, size);
750
 
751
  null_mem = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
752
                                            boolean_type_node, mem,
753
                                            build_int_cst (type, 0)));
754
 
755
  /* If mem is NULL, we call gfc_allocate_using_malloc or
756
     gfc_allocate_using_lib.  */
757
  gfc_start_block (&alloc_block);
758
 
759
  if (gfc_option.coarray == GFC_FCOARRAY_LIB
760
      && gfc_expr_attr (expr).codimension)
761
    {
762
      tree cond;
763
 
764
      gfc_allocate_using_lib (&alloc_block, mem, size, token, status,
765
                              errmsg, errlen);
766
      if (status != NULL_TREE)
767
        {
768
          TREE_USED (label_finish) = 1;
769
          tmp = build1_v (GOTO_EXPR, label_finish);
770
          cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
771
                                  status, build_zero_cst (TREE_TYPE (status)));
772
          tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
773
                                 gfc_unlikely (cond), tmp,
774
                                 build_empty_stmt (input_location));
775
          gfc_add_expr_to_block (&alloc_block, tmp);
776
        }
777
    }
778
  else
779
    gfc_allocate_using_malloc (&alloc_block, mem, size, status);
780
 
781
  alloc = gfc_finish_block (&alloc_block);
782
 
783
  /* If mem is not NULL, we issue a runtime error or set the
784
     status variable.  */
785
  if (expr)
786
    {
787
      tree varname;
788
 
789
      gcc_assert (expr->expr_type == EXPR_VARIABLE && expr->symtree);
790
      varname = gfc_build_cstring_const (expr->symtree->name);
791
      varname = gfc_build_addr_expr (pchar_type_node, varname);
792
 
793
      error = gfc_trans_runtime_error (true, &expr->where,
794
                                       "Attempting to allocate already"
795
                                       " allocated variable '%s'",
796
                                       varname);
797
    }
798
  else
799
    error = gfc_trans_runtime_error (true, NULL,
800
                                     "Attempting to allocate already allocated"
801
                                     " variable");
802
 
803
  if (status != NULL_TREE)
804
    {
805
      tree status_type = TREE_TYPE (status);
806
 
807
      error = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
808
              status, build_int_cst (status_type, LIBERROR_ALLOCATION));
809
    }
810
 
811
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, null_mem,
812
                         error, alloc);
813
  gfc_add_expr_to_block (block, tmp);
814
}
815
 
816
 
817
/* Free a given variable, if it's not NULL.  */
818
tree
819
gfc_call_free (tree var)
820
{
821
  stmtblock_t block;
822
  tree tmp, cond, call;
823
 
824
  if (TREE_TYPE (var) != TREE_TYPE (pvoid_type_node))
825
    var = fold_convert (pvoid_type_node, var);
826
 
827
  gfc_start_block (&block);
828
  var = gfc_evaluate_now (var, &block);
829
  cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var,
830
                          build_int_cst (pvoid_type_node, 0));
831
  call = build_call_expr_loc (input_location,
832
                              builtin_decl_explicit (BUILT_IN_FREE),
833
                              1, var);
834
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, call,
835
                         build_empty_stmt (input_location));
836
  gfc_add_expr_to_block (&block, tmp);
837
 
838
  return gfc_finish_block (&block);
839
}
840
 
841
 
842
 
843
/* User-deallocate; we emit the code directly from the front-end, and the
844
   logic is the same as the previous library function:
845
 
846
    void
847
    deallocate (void *pointer, GFC_INTEGER_4 * stat)
848
    {
849
      if (!pointer)
850
        {
851
          if (stat)
852
            *stat = 1;
853
          else
854
            runtime_error ("Attempt to DEALLOCATE unallocated memory.");
855
        }
856
      else
857
        {
858
          free (pointer);
859
          if (stat)
860
            *stat = 0;
861
        }
862
    }
863
 
864
   In this front-end version, status doesn't have to be GFC_INTEGER_4.
865
   Moreover, if CAN_FAIL is true, then we will not emit a runtime error,
866
   even when no status variable is passed to us (this is used for
867
   unconditional deallocation generated by the front-end at end of
868
   each procedure).
869
 
870
   If a runtime-message is possible, `expr' must point to the original
871
   expression being deallocated for its locus and variable name.
872
 
873
   For coarrays, "pointer" must be the array descriptor and not its
874
   "data" component.  */
875
tree
876
gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
877
                            tree errlen, tree label_finish,
878
                            bool can_fail, gfc_expr* expr, bool coarray)
879
{
880
  stmtblock_t null, non_null;
881
  tree cond, tmp, error;
882
  tree status_type = NULL_TREE;
883
  tree caf_decl = NULL_TREE;
884
 
885
  if (coarray)
886
    {
887
      gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)));
888
      caf_decl = pointer;
889
      pointer = gfc_conv_descriptor_data_get (caf_decl);
890
      STRIP_NOPS (pointer);
891
    }
892
 
893
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pointer,
894
                          build_int_cst (TREE_TYPE (pointer), 0));
895
 
896
  /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
897
     we emit a runtime error.  */
898
  gfc_start_block (&null);
899
  if (!can_fail)
900
    {
901
      tree varname;
902
 
903
      gcc_assert (expr && expr->expr_type == EXPR_VARIABLE && expr->symtree);
904
 
905
      varname = gfc_build_cstring_const (expr->symtree->name);
906
      varname = gfc_build_addr_expr (pchar_type_node, varname);
907
 
908
      error = gfc_trans_runtime_error (true, &expr->where,
909
                                       "Attempt to DEALLOCATE unallocated '%s'",
910
                                       varname);
911
    }
912
  else
913
    error = build_empty_stmt (input_location);
914
 
915
  if (status != NULL_TREE && !integer_zerop (status))
916
    {
917
      tree cond2;
918
 
919
      status_type = TREE_TYPE (TREE_TYPE (status));
920
      cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
921
                               status, build_int_cst (TREE_TYPE (status), 0));
922
      tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
923
                             fold_build1_loc (input_location, INDIRECT_REF,
924
                                              status_type, status),
925
                             build_int_cst (status_type, 1));
926
      error = fold_build3_loc (input_location, COND_EXPR, void_type_node,
927
                               cond2, tmp, error);
928
    }
929
 
930
  gfc_add_expr_to_block (&null, error);
931
 
932
  /* When POINTER is not NULL, we free it.  */
933
  gfc_start_block (&non_null);
934
  if (!coarray || gfc_option.coarray != GFC_FCOARRAY_LIB)
935
    {
936
      tmp = build_call_expr_loc (input_location,
937
                                 builtin_decl_explicit (BUILT_IN_FREE), 1,
938
                                 fold_convert (pvoid_type_node, pointer));
939
      gfc_add_expr_to_block (&non_null, tmp);
940
 
941
      if (status != NULL_TREE && !integer_zerop (status))
942
        {
943
          /* We set STATUS to zero if it is present.  */
944
          tree status_type = TREE_TYPE (TREE_TYPE (status));
945
          tree cond2;
946
 
947
          cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
948
                                   status,
949
                                   build_int_cst (TREE_TYPE (status), 0));
950
          tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
951
                                 fold_build1_loc (input_location, INDIRECT_REF,
952
                                                  status_type, status),
953
                                 build_int_cst (status_type, 0));
954
          tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
955
                                 gfc_unlikely (cond2), tmp,
956
                                 build_empty_stmt (input_location));
957
          gfc_add_expr_to_block (&non_null, tmp);
958
        }
959
    }
960
  else
961
    {
962
      tree caf_type, token, cond2;
963
      tree pstat = null_pointer_node;
964
 
965
      if (errmsg == NULL_TREE)
966
        {
967
          gcc_assert (errlen == NULL_TREE);
968
          errmsg = null_pointer_node;
969
          errlen = build_zero_cst (integer_type_node);
970
        }
971
      else
972
        {
973
          gcc_assert (errlen != NULL_TREE);
974
          if (!POINTER_TYPE_P (TREE_TYPE (errmsg)))
975
            errmsg = gfc_build_addr_expr (NULL_TREE, errmsg);
976
        }
977
 
978
      caf_type = TREE_TYPE (caf_decl);
979
 
980
      if (status != NULL_TREE && !integer_zerop (status))
981
        {
982
          gcc_assert (status_type == integer_type_node);
983
          pstat = status;
984
        }
985
 
986
      if (GFC_DESCRIPTOR_TYPE_P (caf_type)
987
          && GFC_TYPE_ARRAY_AKIND (caf_type) == GFC_ARRAY_ALLOCATABLE)
988
        token = gfc_conv_descriptor_token (caf_decl);
989
      else if (DECL_LANG_SPECIFIC (caf_decl)
990
               && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
991
        token = GFC_DECL_TOKEN (caf_decl);
992
      else
993
        {
994
          gcc_assert (GFC_ARRAY_TYPE_P (caf_type)
995
                      && GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) != NULL_TREE);
996
          token = GFC_TYPE_ARRAY_CAF_TOKEN (caf_type);
997
        }
998
 
999
      token = gfc_build_addr_expr  (NULL_TREE, token);
1000
      tmp = build_call_expr_loc (input_location,
1001
             gfor_fndecl_caf_deregister, 4,
1002
             token, pstat, errmsg, errlen);
1003
      gfc_add_expr_to_block (&non_null, tmp);
1004
 
1005
      if (status != NULL_TREE)
1006
        {
1007
          tree stat = build_fold_indirect_ref_loc (input_location, status);
1008
 
1009
          TREE_USED (label_finish) = 1;
1010
          tmp = build1_v (GOTO_EXPR, label_finish);
1011
          cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1012
                                   stat, build_zero_cst (TREE_TYPE (stat)));
1013
          tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1014
                                 gfc_unlikely (cond2), tmp,
1015
                                 build_empty_stmt (input_location));
1016
          gfc_add_expr_to_block (&non_null, tmp);
1017
        }
1018
    }
1019
 
1020
  return fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
1021
                          gfc_finish_block (&null),
1022
                          gfc_finish_block (&non_null));
1023
}
1024
 
1025
 
1026
/* Generate code for deallocation of allocatable scalars (variables or
1027
   components). Before the object itself is freed, any allocatable
1028
   subcomponents are being deallocated.  */
1029
 
1030
tree
1031
gfc_deallocate_scalar_with_status (tree pointer, tree status, bool can_fail,
1032
                                   gfc_expr* expr, gfc_typespec ts)
1033
{
1034
  stmtblock_t null, non_null;
1035
  tree cond, tmp, error;
1036
 
1037
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pointer,
1038
                          build_int_cst (TREE_TYPE (pointer), 0));
1039
 
1040
  /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
1041
     we emit a runtime error.  */
1042
  gfc_start_block (&null);
1043
  if (!can_fail)
1044
    {
1045
      tree varname;
1046
 
1047
      gcc_assert (expr && expr->expr_type == EXPR_VARIABLE && expr->symtree);
1048
 
1049
      varname = gfc_build_cstring_const (expr->symtree->name);
1050
      varname = gfc_build_addr_expr (pchar_type_node, varname);
1051
 
1052
      error = gfc_trans_runtime_error (true, &expr->where,
1053
                                       "Attempt to DEALLOCATE unallocated '%s'",
1054
                                       varname);
1055
    }
1056
  else
1057
    error = build_empty_stmt (input_location);
1058
 
1059
  if (status != NULL_TREE && !integer_zerop (status))
1060
    {
1061
      tree status_type = TREE_TYPE (TREE_TYPE (status));
1062
      tree cond2;
1063
 
1064
      cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1065
                               status, build_int_cst (TREE_TYPE (status), 0));
1066
      tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
1067
                             fold_build1_loc (input_location, INDIRECT_REF,
1068
                                              status_type, status),
1069
                             build_int_cst (status_type, 1));
1070
      error = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1071
                               cond2, tmp, error);
1072
    }
1073
 
1074
  gfc_add_expr_to_block (&null, error);
1075
 
1076
  /* When POINTER is not NULL, we free it.  */
1077
  gfc_start_block (&non_null);
1078
 
1079
  /* Free allocatable components.  */
1080
  if (ts.type == BT_DERIVED && ts.u.derived->attr.alloc_comp)
1081
    {
1082
      tmp = build_fold_indirect_ref_loc (input_location, pointer);
1083
      tmp = gfc_deallocate_alloc_comp (ts.u.derived, tmp, 0);
1084
      gfc_add_expr_to_block (&non_null, tmp);
1085
    }
1086
  else if (ts.type == BT_CLASS
1087
           && ts.u.derived->components->ts.u.derived->attr.alloc_comp)
1088
    {
1089
      tmp = build_fold_indirect_ref_loc (input_location, pointer);
1090
      tmp = gfc_deallocate_alloc_comp (ts.u.derived->components->ts.u.derived,
1091
                                       tmp, 0);
1092
      gfc_add_expr_to_block (&non_null, tmp);
1093
    }
1094
 
1095
  tmp = build_call_expr_loc (input_location,
1096
                             builtin_decl_explicit (BUILT_IN_FREE), 1,
1097
                             fold_convert (pvoid_type_node, pointer));
1098
  gfc_add_expr_to_block (&non_null, tmp);
1099
 
1100
  if (status != NULL_TREE && !integer_zerop (status))
1101
    {
1102
      /* We set STATUS to zero if it is present.  */
1103
      tree status_type = TREE_TYPE (TREE_TYPE (status));
1104
      tree cond2;
1105
 
1106
      cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1107
                               status, build_int_cst (TREE_TYPE (status), 0));
1108
      tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
1109
                             fold_build1_loc (input_location, INDIRECT_REF,
1110
                                              status_type, status),
1111
                             build_int_cst (status_type, 0));
1112
      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
1113
                             tmp, build_empty_stmt (input_location));
1114
      gfc_add_expr_to_block (&non_null, tmp);
1115
    }
1116
 
1117
  return fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
1118
                          gfc_finish_block (&null),
1119
                          gfc_finish_block (&non_null));
1120
}
1121
 
1122
 
1123
/* Reallocate MEM so it has SIZE bytes of data.  This behaves like the
1124
   following pseudo-code:
1125
 
1126
void *
1127
internal_realloc (void *mem, size_t size)
1128
{
1129
  res = realloc (mem, size);
1130
  if (!res && size != 0)
1131
    _gfortran_os_error ("Allocation would exceed memory limit");
1132
 
1133
  if (size == 0)
1134
    return NULL;
1135
 
1136
  return res;
1137
}  */
1138
tree
1139
gfc_call_realloc (stmtblock_t * block, tree mem, tree size)
1140
{
1141
  tree msg, res, nonzero, zero, null_result, tmp;
1142
  tree type = TREE_TYPE (mem);
1143
 
1144
  size = gfc_evaluate_now (size, block);
1145
 
1146
  if (TREE_TYPE (size) != TREE_TYPE (size_type_node))
1147
    size = fold_convert (size_type_node, size);
1148
 
1149
  /* Create a variable to hold the result.  */
1150
  res = gfc_create_var (type, NULL);
1151
 
1152
  /* Call realloc and check the result.  */
1153
  tmp = build_call_expr_loc (input_location,
1154
                         builtin_decl_explicit (BUILT_IN_REALLOC), 2,
1155
                         fold_convert (pvoid_type_node, mem), size);
1156
  gfc_add_modify (block, res, fold_convert (type, tmp));
1157
  null_result = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1158
                                 res, build_int_cst (pvoid_type_node, 0));
1159
  nonzero = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, size,
1160
                             build_int_cst (size_type_node, 0));
1161
  null_result = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
1162
                                 null_result, nonzero);
1163
  msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const
1164
                             ("Allocation would exceed memory limit"));
1165
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1166
                         null_result,
1167
                         build_call_expr_loc (input_location,
1168
                                              gfor_fndecl_os_error, 1, msg),
1169
                         build_empty_stmt (input_location));
1170
  gfc_add_expr_to_block (block, tmp);
1171
 
1172
  /* if (size == 0) then the result is NULL.  */
1173
  tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, res,
1174
                         build_int_cst (type, 0));
1175
  zero = fold_build1_loc (input_location, TRUTH_NOT_EXPR, boolean_type_node,
1176
                          nonzero);
1177
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, zero, tmp,
1178
                         build_empty_stmt (input_location));
1179
  gfc_add_expr_to_block (block, tmp);
1180
 
1181
  return res;
1182
}
1183
 
1184
 
1185
/* Add an expression to another one, either at the front or the back.  */
1186
 
1187
static void
1188
add_expr_to_chain (tree* chain, tree expr, bool front)
1189
{
1190
  if (expr == NULL_TREE || IS_EMPTY_STMT (expr))
1191
    return;
1192
 
1193
  if (*chain)
1194
    {
1195
      if (TREE_CODE (*chain) != STATEMENT_LIST)
1196
        {
1197
          tree tmp;
1198
 
1199
          tmp = *chain;
1200
          *chain = NULL_TREE;
1201
          append_to_statement_list (tmp, chain);
1202
        }
1203
 
1204
      if (front)
1205
        {
1206
          tree_stmt_iterator i;
1207
 
1208
          i = tsi_start (*chain);
1209
          tsi_link_before (&i, expr, TSI_CONTINUE_LINKING);
1210
        }
1211
      else
1212
        append_to_statement_list (expr, chain);
1213
    }
1214
  else
1215
    *chain = expr;
1216
}
1217
 
1218
 
1219
/* Add a statement at the end of a block.  */
1220
 
1221
void
1222
gfc_add_expr_to_block (stmtblock_t * block, tree expr)
1223
{
1224
  gcc_assert (block);
1225
  add_expr_to_chain (&block->head, expr, false);
1226
}
1227
 
1228
 
1229
/* Add a statement at the beginning of a block.  */
1230
 
1231
void
1232
gfc_prepend_expr_to_block (stmtblock_t * block, tree expr)
1233
{
1234
  gcc_assert (block);
1235
  add_expr_to_chain (&block->head, expr, true);
1236
}
1237
 
1238
 
1239
/* Add a block the end of a block.  */
1240
 
1241
void
1242
gfc_add_block_to_block (stmtblock_t * block, stmtblock_t * append)
1243
{
1244
  gcc_assert (append);
1245
  gcc_assert (!append->has_scope);
1246
 
1247
  gfc_add_expr_to_block (block, append->head);
1248
  append->head = NULL_TREE;
1249
}
1250
 
1251
 
1252
/* Save the current locus.  The structure may not be complete, and should
1253
   only be used with gfc_restore_backend_locus.  */
1254
 
1255
void
1256
gfc_save_backend_locus (locus * loc)
1257
{
1258
  loc->lb = XCNEW (gfc_linebuf);
1259
  loc->lb->location = input_location;
1260
  loc->lb->file = gfc_current_backend_file;
1261
}
1262
 
1263
 
1264
/* Set the current locus.  */
1265
 
1266
void
1267
gfc_set_backend_locus (locus * loc)
1268
{
1269
  gfc_current_backend_file = loc->lb->file;
1270
  input_location = loc->lb->location;
1271
}
1272
 
1273
 
1274
/* Restore the saved locus. Only used in conjonction with
1275
   gfc_save_backend_locus, to free the memory when we are done.  */
1276
 
1277
void
1278
gfc_restore_backend_locus (locus * loc)
1279
{
1280
  gfc_set_backend_locus (loc);
1281
  free (loc->lb);
1282
}
1283
 
1284
 
1285
/* Translate an executable statement. The tree cond is used by gfc_trans_do.
1286
   This static function is wrapped by gfc_trans_code_cond and
1287
   gfc_trans_code.  */
1288
 
1289
static tree
1290
trans_code (gfc_code * code, tree cond)
1291
{
1292
  stmtblock_t block;
1293
  tree res;
1294
 
1295
  if (!code)
1296
    return build_empty_stmt (input_location);
1297
 
1298
  gfc_start_block (&block);
1299
 
1300
  /* Translate statements one by one into GENERIC trees until we reach
1301
     the end of this gfc_code branch.  */
1302
  for (; code; code = code->next)
1303
    {
1304
      if (code->here != 0)
1305
        {
1306
          res = gfc_trans_label_here (code);
1307
          gfc_add_expr_to_block (&block, res);
1308
        }
1309
 
1310
      gfc_set_backend_locus (&code->loc);
1311
 
1312
      switch (code->op)
1313
        {
1314
        case EXEC_NOP:
1315
        case EXEC_END_BLOCK:
1316
        case EXEC_END_NESTED_BLOCK:
1317
        case EXEC_END_PROCEDURE:
1318
          res = NULL_TREE;
1319
          break;
1320
 
1321
        case EXEC_ASSIGN:
1322
          if (code->expr1->ts.type == BT_CLASS)
1323
            res = gfc_trans_class_assign (code->expr1, code->expr2, code->op);
1324
          else
1325
            res = gfc_trans_assign (code);
1326
          break;
1327
 
1328
        case EXEC_LABEL_ASSIGN:
1329
          res = gfc_trans_label_assign (code);
1330
          break;
1331
 
1332
        case EXEC_POINTER_ASSIGN:
1333
          if (code->expr1->ts.type == BT_CLASS)
1334
            res = gfc_trans_class_assign (code->expr1, code->expr2, code->op);
1335
          else
1336
            res = gfc_trans_pointer_assign (code);
1337
          break;
1338
 
1339
        case EXEC_INIT_ASSIGN:
1340
          if (code->expr1->ts.type == BT_CLASS)
1341
            res = gfc_trans_class_init_assign (code);
1342
          else
1343
            res = gfc_trans_init_assign (code);
1344
          break;
1345
 
1346
        case EXEC_CONTINUE:
1347
          res = NULL_TREE;
1348
          break;
1349
 
1350
        case EXEC_CRITICAL:
1351
          res = gfc_trans_critical (code);
1352
          break;
1353
 
1354
        case EXEC_CYCLE:
1355
          res = gfc_trans_cycle (code);
1356
          break;
1357
 
1358
        case EXEC_EXIT:
1359
          res = gfc_trans_exit (code);
1360
          break;
1361
 
1362
        case EXEC_GOTO:
1363
          res = gfc_trans_goto (code);
1364
          break;
1365
 
1366
        case EXEC_ENTRY:
1367
          res = gfc_trans_entry (code);
1368
          break;
1369
 
1370
        case EXEC_PAUSE:
1371
          res = gfc_trans_pause (code);
1372
          break;
1373
 
1374
        case EXEC_STOP:
1375
        case EXEC_ERROR_STOP:
1376
          res = gfc_trans_stop (code, code->op == EXEC_ERROR_STOP);
1377
          break;
1378
 
1379
        case EXEC_CALL:
1380
          /* For MVBITS we've got the special exception that we need a
1381
             dependency check, too.  */
1382
          {
1383
            bool is_mvbits = false;
1384
 
1385
            if (code->resolved_isym)
1386
              {
1387
                res = gfc_conv_intrinsic_subroutine (code);
1388
                if (res != NULL_TREE)
1389
                  break;
1390
              }
1391
 
1392
            if (code->resolved_isym
1393
                && code->resolved_isym->id == GFC_ISYM_MVBITS)
1394
              is_mvbits = true;
1395
 
1396
            res = gfc_trans_call (code, is_mvbits, NULL_TREE,
1397
                                  NULL_TREE, false);
1398
          }
1399
          break;
1400
 
1401
        case EXEC_CALL_PPC:
1402
          res = gfc_trans_call (code, false, NULL_TREE,
1403
                                NULL_TREE, false);
1404
          break;
1405
 
1406
        case EXEC_ASSIGN_CALL:
1407
          res = gfc_trans_call (code, true, NULL_TREE,
1408
                                NULL_TREE, false);
1409
          break;
1410
 
1411
        case EXEC_RETURN:
1412
          res = gfc_trans_return (code);
1413
          break;
1414
 
1415
        case EXEC_IF:
1416
          res = gfc_trans_if (code);
1417
          break;
1418
 
1419
        case EXEC_ARITHMETIC_IF:
1420
          res = gfc_trans_arithmetic_if (code);
1421
          break;
1422
 
1423
        case EXEC_BLOCK:
1424
          res = gfc_trans_block_construct (code);
1425
          break;
1426
 
1427
        case EXEC_DO:
1428
          res = gfc_trans_do (code, cond);
1429
          break;
1430
 
1431
        case EXEC_DO_CONCURRENT:
1432
          res = gfc_trans_do_concurrent (code);
1433
          break;
1434
 
1435
        case EXEC_DO_WHILE:
1436
          res = gfc_trans_do_while (code);
1437
          break;
1438
 
1439
        case EXEC_SELECT:
1440
          res = gfc_trans_select (code);
1441
          break;
1442
 
1443
        case EXEC_SELECT_TYPE:
1444
          /* Do nothing. SELECT TYPE statements should be transformed into
1445
          an ordinary SELECT CASE at resolution stage.
1446
          TODO: Add an error message here once this is done.  */
1447
          res = NULL_TREE;
1448
          break;
1449
 
1450
        case EXEC_FLUSH:
1451
          res = gfc_trans_flush (code);
1452
          break;
1453
 
1454
        case EXEC_SYNC_ALL:
1455
        case EXEC_SYNC_IMAGES:
1456
        case EXEC_SYNC_MEMORY:
1457
          res = gfc_trans_sync (code, code->op);
1458
          break;
1459
 
1460
        case EXEC_LOCK:
1461
        case EXEC_UNLOCK:
1462
          res = gfc_trans_lock_unlock (code, code->op);
1463
          break;
1464
 
1465
        case EXEC_FORALL:
1466
          res = gfc_trans_forall (code);
1467
          break;
1468
 
1469
        case EXEC_WHERE:
1470
          res = gfc_trans_where (code);
1471
          break;
1472
 
1473
        case EXEC_ALLOCATE:
1474
          res = gfc_trans_allocate (code);
1475
          break;
1476
 
1477
        case EXEC_DEALLOCATE:
1478
          res = gfc_trans_deallocate (code);
1479
          break;
1480
 
1481
        case EXEC_OPEN:
1482
          res = gfc_trans_open (code);
1483
          break;
1484
 
1485
        case EXEC_CLOSE:
1486
          res = gfc_trans_close (code);
1487
          break;
1488
 
1489
        case EXEC_READ:
1490
          res = gfc_trans_read (code);
1491
          break;
1492
 
1493
        case EXEC_WRITE:
1494
          res = gfc_trans_write (code);
1495
          break;
1496
 
1497
        case EXEC_IOLENGTH:
1498
          res = gfc_trans_iolength (code);
1499
          break;
1500
 
1501
        case EXEC_BACKSPACE:
1502
          res = gfc_trans_backspace (code);
1503
          break;
1504
 
1505
        case EXEC_ENDFILE:
1506
          res = gfc_trans_endfile (code);
1507
          break;
1508
 
1509
        case EXEC_INQUIRE:
1510
          res = gfc_trans_inquire (code);
1511
          break;
1512
 
1513
        case EXEC_WAIT:
1514
          res = gfc_trans_wait (code);
1515
          break;
1516
 
1517
        case EXEC_REWIND:
1518
          res = gfc_trans_rewind (code);
1519
          break;
1520
 
1521
        case EXEC_TRANSFER:
1522
          res = gfc_trans_transfer (code);
1523
          break;
1524
 
1525
        case EXEC_DT_END:
1526
          res = gfc_trans_dt_end (code);
1527
          break;
1528
 
1529
        case EXEC_OMP_ATOMIC:
1530
        case EXEC_OMP_BARRIER:
1531
        case EXEC_OMP_CRITICAL:
1532
        case EXEC_OMP_DO:
1533
        case EXEC_OMP_FLUSH:
1534
        case EXEC_OMP_MASTER:
1535
        case EXEC_OMP_ORDERED:
1536
        case EXEC_OMP_PARALLEL:
1537
        case EXEC_OMP_PARALLEL_DO:
1538
        case EXEC_OMP_PARALLEL_SECTIONS:
1539
        case EXEC_OMP_PARALLEL_WORKSHARE:
1540
        case EXEC_OMP_SECTIONS:
1541
        case EXEC_OMP_SINGLE:
1542
        case EXEC_OMP_TASK:
1543
        case EXEC_OMP_TASKWAIT:
1544
        case EXEC_OMP_TASKYIELD:
1545
        case EXEC_OMP_WORKSHARE:
1546
          res = gfc_trans_omp_directive (code);
1547
          break;
1548
 
1549
        default:
1550
          internal_error ("gfc_trans_code(): Bad statement code");
1551
        }
1552
 
1553
      gfc_set_backend_locus (&code->loc);
1554
 
1555
      if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
1556
        {
1557
          if (TREE_CODE (res) != STATEMENT_LIST)
1558
            SET_EXPR_LOCATION (res, input_location);
1559
 
1560
          /* Add the new statement to the block.  */
1561
          gfc_add_expr_to_block (&block, res);
1562
        }
1563
    }
1564
 
1565
  /* Return the finished block.  */
1566
  return gfc_finish_block (&block);
1567
}
1568
 
1569
 
1570
/* Translate an executable statement with condition, cond.  The condition is
1571
   used by gfc_trans_do to test for IO result conditions inside implied
1572
   DO loops of READ and WRITE statements.  See build_dt in trans-io.c.  */
1573
 
1574
tree
1575
gfc_trans_code_cond (gfc_code * code, tree cond)
1576
{
1577
  return trans_code (code, cond);
1578
}
1579
 
1580
/* Translate an executable statement without condition.  */
1581
 
1582
tree
1583
gfc_trans_code (gfc_code * code)
1584
{
1585
  return trans_code (code, NULL_TREE);
1586
}
1587
 
1588
 
1589
/* This function is called after a complete program unit has been parsed
1590
   and resolved.  */
1591
 
1592
void
1593
gfc_generate_code (gfc_namespace * ns)
1594
{
1595
  ompws_flags = 0;
1596
  if (ns->is_block_data)
1597
    {
1598
      gfc_generate_block_data (ns);
1599
      return;
1600
    }
1601
 
1602
  gfc_generate_function_code (ns);
1603
}
1604
 
1605
 
1606
/* This function is called after a complete module has been parsed
1607
   and resolved.  */
1608
 
1609
void
1610
gfc_generate_module_code (gfc_namespace * ns)
1611
{
1612
  gfc_namespace *n;
1613
  struct module_htab_entry *entry;
1614
 
1615
  gcc_assert (ns->proc_name->backend_decl == NULL);
1616
  ns->proc_name->backend_decl
1617
    = build_decl (ns->proc_name->declared_at.lb->location,
1618
                  NAMESPACE_DECL, get_identifier (ns->proc_name->name),
1619
                  void_type_node);
1620
  entry = gfc_find_module (ns->proc_name->name);
1621
  if (entry->namespace_decl)
1622
    /* Buggy sourcecode, using a module before defining it?  */
1623
    htab_empty (entry->decls);
1624
  entry->namespace_decl = ns->proc_name->backend_decl;
1625
 
1626
  gfc_generate_module_vars (ns);
1627
 
1628
  /* We need to generate all module function prototypes first, to allow
1629
     sibling calls.  */
1630
  for (n = ns->contained; n; n = n->sibling)
1631
    {
1632
      gfc_entry_list *el;
1633
 
1634
      if (!n->proc_name)
1635
        continue;
1636
 
1637
      gfc_create_function_decl (n, false);
1638
      DECL_CONTEXT (n->proc_name->backend_decl) = ns->proc_name->backend_decl;
1639
      gfc_module_add_decl (entry, n->proc_name->backend_decl);
1640
      for (el = ns->entries; el; el = el->next)
1641
        {
1642
          DECL_CONTEXT (el->sym->backend_decl) = ns->proc_name->backend_decl;
1643
          gfc_module_add_decl (entry, el->sym->backend_decl);
1644
        }
1645
    }
1646
 
1647
  for (n = ns->contained; n; n = n->sibling)
1648
    {
1649
      if (!n->proc_name)
1650
        continue;
1651
 
1652
      gfc_generate_function_code (n);
1653
    }
1654
}
1655
 
1656
 
1657
/* Initialize an init/cleanup block with existing code.  */
1658
 
1659
void
1660
gfc_start_wrapped_block (gfc_wrapped_block* block, tree code)
1661
{
1662
  gcc_assert (block);
1663
 
1664
  block->init = NULL_TREE;
1665
  block->code = code;
1666
  block->cleanup = NULL_TREE;
1667
}
1668
 
1669
 
1670
/* Add a new pair of initializers/clean-up code.  */
1671
 
1672
void
1673
gfc_add_init_cleanup (gfc_wrapped_block* block, tree init, tree cleanup)
1674
{
1675
  gcc_assert (block);
1676
 
1677
  /* The new pair of init/cleanup should be "wrapped around" the existing
1678
     block of code, thus the initialization is added to the front and the
1679
     cleanup to the back.  */
1680
  add_expr_to_chain (&block->init, init, true);
1681
  add_expr_to_chain (&block->cleanup, cleanup, false);
1682
}
1683
 
1684
 
1685
/* Finish up a wrapped block by building a corresponding try-finally expr.  */
1686
 
1687
tree
1688
gfc_finish_wrapped_block (gfc_wrapped_block* block)
1689
{
1690
  tree result;
1691
 
1692
  gcc_assert (block);
1693
 
1694
  /* Build the final expression.  For this, just add init and body together,
1695
     and put clean-up with that into a TRY_FINALLY_EXPR.  */
1696
  result = block->init;
1697
  add_expr_to_chain (&result, block->code, false);
1698
  if (block->cleanup)
1699
    result = build2_loc (input_location, TRY_FINALLY_EXPR, void_type_node,
1700
                         result, block->cleanup);
1701
 
1702
  /* Clear the block.  */
1703
  block->init = NULL_TREE;
1704
  block->code = NULL_TREE;
1705
  block->cleanup = NULL_TREE;
1706
 
1707
  return result;
1708
}
1709
 
1710
 
1711
/* Helper function for marking a boolean expression tree as unlikely.  */
1712
 
1713
tree
1714
gfc_unlikely (tree cond)
1715
{
1716
  tree tmp;
1717
 
1718
  cond = fold_convert (long_integer_type_node, cond);
1719
  tmp = build_zero_cst (long_integer_type_node);
1720
  cond = build_call_expr_loc (input_location,
1721
                              builtin_decl_explicit (BUILT_IN_EXPECT),
1722
                              2, cond, tmp);
1723
  cond = fold_convert (boolean_type_node, cond);
1724
  return cond;
1725
}
1726
 
1727
 
1728
/* Helper function for marking a boolean expression tree as likely.  */
1729
 
1730
tree
1731
gfc_likely (tree cond)
1732
{
1733
  tree tmp;
1734
 
1735
  cond = fold_convert (long_integer_type_node, cond);
1736
  tmp = build_one_cst (long_integer_type_node);
1737
  cond = build_call_expr_loc (input_location,
1738
                              builtin_decl_explicit (BUILT_IN_EXPECT),
1739
                              2, cond, tmp);
1740
  cond = fold_convert (boolean_type_node, cond);
1741
  return cond;
1742
}

powered by: WebSVN 2.1.0

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