1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GNU G95.
8 GNU G95 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU G95 is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU G95; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
26 #include "coretypes.h"
28 #include "tree-gimple.h"
37 #include "trans-stmt.h"
38 #include "trans-types.h"
39 #include "trans-array.h"
40 #include "trans-const.h"
43 int has_alternate_specifier;
45 typedef struct iter_info
51 struct iter_info *next;
55 typedef struct temporary_list
58 struct temporary_list *next;
62 typedef struct forall_info
70 struct forall_info *outer;
71 struct forall_info *next_nest;
75 static void gfc_trans_where_2 (gfc_code *, tree, tree, forall_info *,
76 stmtblock_t *, temporary_list **temp);
78 /* Translate a F95 label number to a LABEL_EXPR. */
81 gfc_trans_label_here (gfc_code * code)
83 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
86 /* Translate a label assignment statement. */
88 gfc_trans_label_assign (gfc_code * code)
98 /* Start a new block. */
99 gfc_init_se (&se, NULL);
100 gfc_start_block (&se.pre);
101 gfc_conv_expr (&se, code->expr);
102 len = GFC_DECL_STRING_LEN (se.expr);
103 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
105 label_tree = gfc_get_label_decl (code->label);
107 if (code->label->defined == ST_LABEL_TARGET)
109 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
110 len_tree = integer_minus_one_node;
114 label_str = code->label->format->value.character.string;
115 label_len = code->label->format->value.character.length;
116 len_tree = build_int_2 (label_len, 0);
117 label_tree = gfc_build_string_const (label_len + 1, label_str);
118 label_tree = gfc_build_addr_expr (pchar_type_node, label_tree);
121 gfc_add_modify_expr (&se.pre, len, len_tree);
122 gfc_add_modify_expr (&se.pre, addr, label_tree);
124 return gfc_finish_block (&se.pre);
127 /* Translate a GOTO statement. */
130 gfc_trans_goto (gfc_code * code)
140 if (code->label != NULL)
141 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
144 gfc_init_se (&se, NULL);
145 gfc_start_block (&se.pre);
146 gfc_conv_expr (&se, code->expr);
148 gfc_build_string_const (37, "Assigned label is not a target label");
149 tmp = GFC_DECL_STRING_LEN (se.expr);
150 tmp = build (NE_EXPR, boolean_type_node, tmp, integer_minus_one_node);
151 gfc_trans_runtime_check (tmp, assign_error, &se.pre);
153 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
154 target = build1 (GOTO_EXPR, void_type_node, assigned_goto);
159 gfc_add_expr_to_block (&se.pre, target);
160 return gfc_finish_block (&se.pre);
163 /* Check the label list. */
165 gfc_build_string_const (34, "Assigned label is not in the list");
169 tmp = gfc_get_label_decl (code->label);
170 tmp = gfc_build_addr_expr (pvoid_type_node, tmp);
171 tmp = build (EQ_EXPR, boolean_type_node, tmp, assigned_goto);
172 tmp = build_v (COND_EXPR, tmp, target, build_empty_stmt ());
173 gfc_add_expr_to_block (&se.pre, tmp);
176 while (code != NULL);
177 gfc_trans_runtime_check (boolean_true_node, range_error, &se.pre);
178 return gfc_finish_block (&se.pre);
182 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
185 gfc_trans_call (gfc_code * code)
189 /* A CALL starts a new block because the actual arguments may have to
190 be evaluated first. */
191 gfc_init_se (&se, NULL);
192 gfc_start_block (&se.pre);
194 assert (code->resolved_sym);
195 has_alternate_specifier = 0;
197 /* Translate the call. */
198 gfc_conv_function_call (&se, code->resolved_sym, code->ext.actual);
200 /* A subroutine without side-effect, by definition, does nothing! */
201 TREE_SIDE_EFFECTS (se.expr) = 1;
203 /* Chain the pieces together and return the block. */
204 if (has_alternate_specifier)
206 gfc_code *select_code;
208 select_code = code->next;
209 assert(select_code->op == EXEC_SELECT);
210 sym = select_code->expr->symtree->n.sym;
211 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
212 gfc_add_modify_expr (&se.pre, sym->backend_decl, se.expr);
215 gfc_add_expr_to_block (&se.pre, se.expr);
217 gfc_add_block_to_block (&se.pre, &se.post);
218 return gfc_finish_block (&se.pre);
222 /* Translate the RETURN statement. */
225 gfc_trans_return (gfc_code * code ATTRIBUTE_UNUSED)
233 /* if code->expr is not NULL, this return statement must appear
234 in a subroutine and current_fake_result_decl has already
237 result = gfc_get_fake_result_decl (NULL);
240 gfc_warning ("An alternate return at %L without a * dummy argument",
242 return build1_v (GOTO_EXPR, gfc_get_return_label ());
245 /* Start a new block for this statement. */
246 gfc_init_se (&se, NULL);
247 gfc_start_block (&se.pre);
249 gfc_conv_expr (&se, code->expr);
251 tmp = build (MODIFY_EXPR, TREE_TYPE (result), result, se.expr);
252 gfc_add_expr_to_block (&se.pre, tmp);
254 tmp = build1_v (GOTO_EXPR, gfc_get_return_label ());
255 gfc_add_expr_to_block (&se.pre, tmp);
256 gfc_add_block_to_block (&se.pre, &se.post);
257 return gfc_finish_block (&se.pre);
260 return build1_v (GOTO_EXPR, gfc_get_return_label ());
264 /* Translate the PAUSE statement. We have to translate this statement
265 to a runtime library call. */
268 gfc_trans_pause (gfc_code * code)
275 /* Start a new block for this statement. */
276 gfc_init_se (&se, NULL);
277 gfc_start_block (&se.pre);
280 if (code->expr == NULL)
282 tmp = build_int_2 (code->ext.stop_code, 0);
283 TREE_TYPE (tmp) = gfc_int4_type_node;
284 args = gfc_chainon_list (NULL_TREE, tmp);
285 fndecl = gfor_fndecl_pause_numeric;
289 gfc_conv_expr_reference (&se, code->expr);
290 args = gfc_chainon_list (NULL_TREE, se.expr);
291 args = gfc_chainon_list (args, se.string_length);
292 fndecl = gfor_fndecl_pause_string;
295 tmp = gfc_build_function_call (fndecl, args);
296 gfc_add_expr_to_block (&se.pre, tmp);
298 gfc_add_block_to_block (&se.pre, &se.post);
300 return gfc_finish_block (&se.pre);
304 /* Translate the STOP statement. We have to translate this statement
305 to a runtime library call. */
308 gfc_trans_stop (gfc_code * code)
315 /* Start a new block for this statement. */
316 gfc_init_se (&se, NULL);
317 gfc_start_block (&se.pre);
320 if (code->expr == NULL)
322 tmp = build_int_2 (code->ext.stop_code, 0);
323 TREE_TYPE (tmp) = gfc_int4_type_node;
324 args = gfc_chainon_list (NULL_TREE, tmp);
325 fndecl = gfor_fndecl_stop_numeric;
329 gfc_conv_expr_reference (&se, code->expr);
330 args = gfc_chainon_list (NULL_TREE, se.expr);
331 args = gfc_chainon_list (args, se.string_length);
332 fndecl = gfor_fndecl_stop_string;
335 tmp = gfc_build_function_call (fndecl, args);
336 gfc_add_expr_to_block (&se.pre, tmp);
338 gfc_add_block_to_block (&se.pre, &se.post);
340 return gfc_finish_block (&se.pre);
344 /* Generate GENERIC for the IF construct. This function also deals with
345 the simple IF statement, because the front end translates the IF
346 statement into an IF construct.
378 where COND_S is the simplified version of the predicate. PRE_COND_S
379 are the pre side-effects produced by the translation of the
381 We need to build the chain recursively otherwise we run into
382 problems with folding incomplete statements. */
385 gfc_trans_if_1 (gfc_code * code)
390 /* Check for an unconditional ELSE clause. */
392 return gfc_trans_code (code->next);
394 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
395 gfc_init_se (&if_se, NULL);
396 gfc_start_block (&if_se.pre);
398 /* Calculate the IF condition expression. */
399 gfc_conv_expr_val (&if_se, code->expr);
401 /* Translate the THEN clause. */
402 stmt = gfc_trans_code (code->next);
404 /* Translate the ELSE clause. */
406 elsestmt = gfc_trans_if_1 (code->block);
408 elsestmt = build_empty_stmt ();
410 /* Build the condition expression and add it to the condition block. */
411 stmt = build_v (COND_EXPR, if_se.expr, stmt, elsestmt);
413 gfc_add_expr_to_block (&if_se.pre, stmt);
415 /* Finish off this statement. */
416 return gfc_finish_block (&if_se.pre);
420 gfc_trans_if (gfc_code * code)
422 /* Ignore the top EXEC_IF, it only announces an IF construct. The
423 actual code we must translate is in code->block. */
425 return gfc_trans_if_1 (code->block);
429 /* Translage an arithmetic IF expression.
431 IF (cond) label1, label2, label3 translates to
445 gfc_trans_arithmetic_if (gfc_code * code)
453 /* Start a new block. */
454 gfc_init_se (&se, NULL);
455 gfc_start_block (&se.pre);
457 /* Pre-evaluate COND. */
458 gfc_conv_expr_val (&se, code->expr);
460 /* Build something to compare with. */
461 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
463 /* If (cond < 0) take branch1 else take branch2.
464 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
465 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
466 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
468 tmp = build (LT_EXPR, boolean_type_node, se.expr, zero);
469 branch1 = build_v (COND_EXPR, tmp, branch1, branch2);
471 /* if (cond <= 0) take branch1 else take branch2. */
472 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
473 tmp = build (LE_EXPR, boolean_type_node, se.expr, zero);
474 branch1 = build_v (COND_EXPR, tmp, branch1, branch2);
476 /* Append the COND_EXPR to the evaluation of COND, and return. */
477 gfc_add_expr_to_block (&se.pre, branch1);
478 return gfc_finish_block (&se.pre);
482 /* Translate the DO construct. This obviously is one of the most
483 important ones to get right with any compiler, but especially
486 Currently we calculate the loop count before entering the loop, but
487 it may be possible to optimize if step is a constant. The main
488 advantage is that the loop test is a single GENERIC node
490 We translate a do loop from:
492 DO dovar = from, to, step
502 temp1=to_expr-from_expr;
504 range_temp=step_tmp/range_temp;
505 for ( ; range_temp > 0 ; range_temp = range_temp - 1)
510 dovar=dovar_temp + step_temp;
514 Some optimization is done for empty do loops. We can't just let
515 dovar=to because it's possible for from+range*loopcount!=to. Anyone
516 who writes empty DO deserves sub-optimal (but correct) code anyway.
518 TODO: Large loop counts
519 Does not work loop counts which do not fit into a signed integer kind,
520 ie. Does not work for loop counts > 2^31 for integer(kind=4) variables
521 We must support the full range. */
524 gfc_trans_do (gfc_code * code)
540 gfc_start_block (&block);
542 /* Create GIMPLE versions of all expressions in the iterator. */
544 gfc_init_se (&se, NULL);
545 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
546 gfc_add_block_to_block (&block, &se.pre);
548 type = TREE_TYPE (dovar);
550 gfc_init_se (&se, NULL);
551 gfc_conv_expr_type (&se, code->ext.iterator->start, type);
552 gfc_add_block_to_block (&block, &se.pre);
555 gfc_init_se (&se, NULL);
556 gfc_conv_expr_type (&se, code->ext.iterator->end, type);
557 gfc_add_block_to_block (&block, &se.pre);
560 gfc_init_se (&se, NULL);
561 gfc_conv_expr_type (&se, code->ext.iterator->step, type);
563 /* We don't want this changing part way through. */
564 gfc_make_safe_expr (&se);
565 gfc_add_block_to_block (&block, &se.pre);
568 /* Initialise loop count. This code is executed before we enter the
569 loop body. We generate: count = (to + step - from) / step. */
571 tmp = fold (build (MINUS_EXPR, type, step, from));
572 tmp = fold (build (PLUS_EXPR, type, to, tmp));
573 tmp = fold (build (TRUNC_DIV_EXPR, type, tmp, step));
575 count = gfc_create_var (type, "count");
576 gfc_add_modify_expr (&block, count, tmp);
578 /* Initialise the DO variable: dovar = from. */
579 gfc_add_modify_expr (&block, dovar, from);
582 gfc_start_block (&body);
584 /* Cycle and exit statements are implemented with gotos. */
585 cycle_label = gfc_build_label_decl (NULL_TREE);
586 exit_label = gfc_build_label_decl (NULL_TREE);
588 /* Start with the loop condition. Loop until count <= 0. */
589 cond = build (LE_EXPR, boolean_type_node, count, integer_zero_node);
590 tmp = build1_v (GOTO_EXPR, exit_label);
591 TREE_USED (exit_label) = 1;
592 tmp = build_v (COND_EXPR, cond, tmp, build_empty_stmt ());
593 gfc_add_expr_to_block (&body, tmp);
595 /* Put these labels where they can be found later. We put the
596 labels in a TREE_LIST node (because TREE_CHAIN is already
597 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
598 label in TREE_VALUE (backend_decl). */
600 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
602 /* Main loop body. */
603 tmp = gfc_trans_code (code->block->next);
604 gfc_add_expr_to_block (&body, tmp);
606 /* Label for cycle statements (if needed). */
607 if (TREE_USED (cycle_label))
609 tmp = build1_v (LABEL_EXPR, cycle_label);
610 gfc_add_expr_to_block (&body, tmp);
613 /* Increment the loop variable. */
614 tmp = build (PLUS_EXPR, type, dovar, step);
615 gfc_add_modify_expr (&body, dovar, tmp);
617 /* Decrement the loop count. */
618 tmp = build (MINUS_EXPR, type, count, integer_one_node);
619 gfc_add_modify_expr (&body, count, tmp);
621 /* End of loop body. */
622 tmp = gfc_finish_block (&body);
624 /* The for loop itself. */
625 tmp = build_v (LOOP_EXPR, tmp);
626 gfc_add_expr_to_block (&block, tmp);
628 /* Add the exit label. */
629 tmp = build1_v (LABEL_EXPR, exit_label);
630 gfc_add_expr_to_block (&block, tmp);
632 return gfc_finish_block (&block);
636 /* Translate the DO WHILE construct.
649 if (! cond) goto exit_label;
655 Because the evaluation of the exit condition `cond' may have side
656 effects, we can't do much for empty loop bodies. The backend optimizers
657 should be smart enough to eliminate any dead loops. */
660 gfc_trans_do_while (gfc_code * code)
668 /* Everything we build here is part of the loop body. */
669 gfc_start_block (&block);
671 /* Cycle and exit statements are implemented with gotos. */
672 cycle_label = gfc_build_label_decl (NULL_TREE);
673 exit_label = gfc_build_label_decl (NULL_TREE);
675 /* Put the labels where they can be found later. See gfc_trans_do(). */
676 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
678 /* Create a GIMPLE version of the exit condition. */
679 gfc_init_se (&cond, NULL);
680 gfc_conv_expr_val (&cond, code->expr);
681 gfc_add_block_to_block (&block, &cond.pre);
682 cond.expr = fold (build1 (TRUTH_NOT_EXPR, boolean_type_node, cond.expr));
684 /* Build "IF (! cond) GOTO exit_label". */
685 tmp = build1_v (GOTO_EXPR, exit_label);
686 TREE_USED (exit_label) = 1;
687 tmp = build_v (COND_EXPR, cond.expr, tmp, build_empty_stmt ());
688 gfc_add_expr_to_block (&block, tmp);
690 /* The main body of the loop. */
691 tmp = gfc_trans_code (code->block->next);
692 gfc_add_expr_to_block (&block, tmp);
694 /* Label for cycle statements (if needed). */
695 if (TREE_USED (cycle_label))
697 tmp = build1_v (LABEL_EXPR, cycle_label);
698 gfc_add_expr_to_block (&block, tmp);
701 /* End of loop body. */
702 tmp = gfc_finish_block (&block);
704 gfc_init_block (&block);
705 /* Build the loop. */
706 tmp = build_v (LOOP_EXPR, tmp);
707 gfc_add_expr_to_block (&block, tmp);
709 /* Add the exit label. */
710 tmp = build1_v (LABEL_EXPR, exit_label);
711 gfc_add_expr_to_block (&block, tmp);
713 return gfc_finish_block (&block);
717 /* Translate the SELECT CASE construct for INTEGER case expressions,
718 without killing all potential optimizations. The problem is that
719 Fortran allows unbounded cases, but the back-end does not, so we
720 need to intercept those before we enter the equivalent SWITCH_EXPR
723 For example, we translate this,
726 CASE (:100,101,105:115)
736 to the GENERIC equivalent,
740 case (minimum value for typeof(expr) ... 100:
746 case 200 ... (maximum value for typeof(expr):
763 gfc_trans_integer_select (gfc_code * code)
773 gfc_start_block (&block);
775 /* Calculate the switch expression. */
776 gfc_init_se (&se, NULL);
777 gfc_conv_expr_val (&se, code->expr);
778 gfc_add_block_to_block (&block, &se.pre);
780 end_label = gfc_build_label_decl (NULL_TREE);
782 gfc_init_block (&body);
784 for (c = code->block; c; c = c->block)
786 for (cp = c->ext.case_list; cp; cp = cp->next)
791 /* Assume it's the default case. */
792 low = high = NULL_TREE;
796 low = gfc_conv_constant_to_tree (cp->low);
798 /* If there's only a lower bound, set the high bound to the
799 maximum value of the case expression. */
801 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
806 /* Three cases are possible here:
808 1) There is no lower bound, e.g. CASE (:N).
809 2) There is a lower bound .NE. high bound, that is
810 a case range, e.g. CASE (N:M) where M>N (we make
811 sure that M>N during type resolution).
812 3) There is a lower bound, and it has the same value
813 as the high bound, e.g. CASE (N:N). This is our
814 internal representation of CASE(N).
816 In the first and second case, we need to set a value for
817 high. In the thirth case, we don't because the GCC middle
818 end represents a single case value by just letting high be
819 a NULL_TREE. We can't do that because we need to be able
820 to represent unbounded cases. */
824 && mpz_cmp (cp->low->value.integer,
825 cp->high->value.integer) != 0))
826 high = gfc_conv_constant_to_tree (cp->high);
828 /* Unbounded case. */
830 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
834 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
835 DECL_CONTEXT (label) = current_function_decl;
837 /* Add this case label.
838 Add parameter 'label', make it match GCC backend. */
839 tmp = build (CASE_LABEL_EXPR, void_type_node, low, high, label);
840 gfc_add_expr_to_block (&body, tmp);
843 /* Add the statements for this case. */
844 tmp = gfc_trans_code (c->next);
845 gfc_add_expr_to_block (&body, tmp);
847 /* Break to the end of the construct. */
848 tmp = build1_v (GOTO_EXPR, end_label);
849 gfc_add_expr_to_block (&body, tmp);
852 tmp = gfc_finish_block (&body);
853 tmp = build_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
854 gfc_add_expr_to_block (&block, tmp);
856 tmp = build1_v (LABEL_EXPR, end_label);
857 gfc_add_expr_to_block (&block, tmp);
859 return gfc_finish_block (&block);
863 /* Translate the SELECT CASE construct for LOGICAL case expressions.
865 There are only two cases possible here, even though the standard
866 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
867 .FALSE., and DEFAULT.
869 We never generate more than two blocks here. Instead, we always
870 try to eliminate the DEFAULT case. This way, we can translate this
871 kind of SELECT construct to a simple
875 expression in GENERIC. */
878 gfc_trans_logical_select (gfc_code * code)
886 /* Assume we don't have any cases at all. */
889 /* Now see which ones we actually do have. We can have at most two
890 cases in a single case list: one for .TRUE. and one for .FALSE.
891 The default case is always separate. If the cases for .TRUE. and
892 .FALSE. are in the same case list, the block for that case list
893 always executed, and we don't generate code a COND_EXPR. */
894 for (c = code->block; c; c = c->block)
896 for (cp = c->ext.case_list; cp; cp = cp->next)
900 if (cp->low->value.logical == 0) /* .FALSE. */
902 else /* if (cp->value.logical != 0), thus .TRUE. */
910 /* Start a new block. */
911 gfc_start_block (&block);
913 /* Calculate the switch expression. We always need to do this
914 because it may have side effects. */
915 gfc_init_se (&se, NULL);
916 gfc_conv_expr_val (&se, code->expr);
917 gfc_add_block_to_block (&block, &se.pre);
919 if (t == f && t != NULL)
921 /* Cases for .TRUE. and .FALSE. are in the same block. Just
922 translate the code for these cases, append it to the current
924 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
928 tree true_tree, false_tree;
930 true_tree = build_empty_stmt ();
931 false_tree = build_empty_stmt ();
933 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
934 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
935 make the missing case the default case. */
936 if (t != NULL && f != NULL)
946 /* Translate the code for each of these blocks, and append it to
947 the current block. */
949 true_tree = gfc_trans_code (t->next);
952 false_tree = gfc_trans_code (f->next);
954 gfc_add_expr_to_block (&block, build_v (COND_EXPR, se.expr,
955 true_tree, false_tree));
958 return gfc_finish_block (&block);
962 /* Translate the SELECT CASE construct for CHARACTER case expressions.
963 Instead of generating compares and jumps, it is far simpler to
964 generate a data structure describing the cases in order and call a
965 library subroutine that locates the right case.
966 This is particularly true because this is the only case where we
967 might have to dispose of a temporary.
968 The library subroutine returns a pointer to jump to or NULL if no
969 branches are to be taken. */
972 gfc_trans_character_select (gfc_code *code)
974 tree init, node, end_label, tmp, type, args, *labels;
975 stmtblock_t block, body;
981 static tree select_struct;
982 static tree ss_string1, ss_string1_len;
983 static tree ss_string2, ss_string2_len;
984 static tree ss_target;
986 if (select_struct == NULL)
988 select_struct = make_node (RECORD_TYPE);
989 TYPE_NAME (select_struct) = get_identifier ("_jump_struct");
992 #define ADD_FIELD(NAME, TYPE) \
993 ss_##NAME = gfc_add_field_to_struct \
994 (&(TYPE_FIELDS (select_struct)), select_struct, \
995 get_identifier (stringize(NAME)), TYPE)
997 ADD_FIELD (string1, pchar_type_node);
998 ADD_FIELD (string1_len, gfc_int4_type_node);
1000 ADD_FIELD (string2, pchar_type_node);
1001 ADD_FIELD (string2_len, gfc_int4_type_node);
1003 ADD_FIELD (target, pvoid_type_node);
1006 gfc_finish_type (select_struct);
1009 cp = code->block->ext.case_list;
1010 while (cp->left != NULL)
1014 for (d = cp; d; d = d->right)
1018 labels = gfc_getmem (n * sizeof (tree));
1022 for(i = 0; i < n; i++)
1024 labels[i] = gfc_build_label_decl (NULL_TREE);
1025 TREE_USED (labels[i]) = 1;
1026 /* TODO: The gimplifier should do this for us, but it has
1027 inadequacies when dealing with static initializers. */
1028 FORCED_LABEL (labels[i]) = 1;
1031 end_label = gfc_build_label_decl (NULL_TREE);
1033 /* Generate the body */
1034 gfc_start_block (&block);
1035 gfc_init_block (&body);
1037 for (c = code->block; c; c = c->block)
1039 for (d = c->ext.case_list; d; d = d->next)
1041 tmp = build_v (LABEL_EXPR, labels[d->n]);
1042 gfc_add_expr_to_block (&body, tmp);
1045 tmp = gfc_trans_code (c->next);
1046 gfc_add_expr_to_block (&body, tmp);
1048 tmp = build_v (GOTO_EXPR, end_label);
1049 gfc_add_expr_to_block (&body, tmp);
1052 /* Generate the structure describing the branches */
1056 for(d = cp; d; d = d->right, i++)
1060 gfc_init_se (&se, NULL);
1064 node = tree_cons (ss_string1, null_pointer_node, node);
1065 node = tree_cons (ss_string1_len, integer_zero_node, node);
1069 gfc_conv_expr_reference (&se, d->low);
1071 node = tree_cons (ss_string1, se.expr, node);
1072 node = tree_cons (ss_string1_len, se.string_length, node);
1075 if (d->high == NULL)
1077 node = tree_cons (ss_string2, null_pointer_node, node);
1078 node = tree_cons (ss_string2_len, integer_zero_node, node);
1082 gfc_init_se (&se, NULL);
1083 gfc_conv_expr_reference (&se, d->high);
1085 node = tree_cons (ss_string2, se.expr, node);
1086 node = tree_cons (ss_string2_len, se.string_length, node);
1089 tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]);
1090 node = tree_cons (ss_target, tmp, node);
1092 tmp = build1 (CONSTRUCTOR, select_struct, nreverse (node));
1093 init = tree_cons (NULL_TREE, tmp, init);
1096 type = build_array_type (select_struct,
1097 build_index_type (build_int_2(n - 1, 0)));
1099 init = build1 (CONSTRUCTOR, type, nreverse(init));
1100 TREE_CONSTANT (init) = 1;
1101 TREE_INVARIANT (init) = 1;
1102 TREE_STATIC (init) = 1;
1103 /* Create a static variable to hold the jump table. */
1104 tmp = gfc_create_var (type, "jumptable");
1105 TREE_CONSTANT (tmp) = 1;
1106 TREE_INVARIANT (tmp) = 1;
1107 TREE_STATIC (tmp) = 1;
1108 DECL_INITIAL (tmp) = init;
1111 /* Build an argument list for the library call */
1112 init = gfc_build_addr_expr (pvoid_type_node, init);
1113 args = gfc_chainon_list (NULL_TREE, init);
1115 tmp = build_int_2 (n, 0);
1116 args = gfc_chainon_list (args, tmp);
1118 tmp = gfc_build_addr_expr (pvoid_type_node, end_label);
1119 args = gfc_chainon_list (args, tmp);
1121 gfc_init_se (&se, NULL);
1122 gfc_conv_expr_reference (&se, code->expr);
1124 args = gfc_chainon_list (args, se.expr);
1125 args = gfc_chainon_list (args, se.string_length);
1127 gfc_add_block_to_block (&block, &se.pre);
1129 tmp = gfc_build_function_call (gfor_fndecl_select_string, args);
1130 tmp = build1 (GOTO_EXPR, void_type_node, tmp);
1131 gfc_add_expr_to_block (&block, tmp);
1133 tmp = gfc_finish_block (&body);
1134 gfc_add_expr_to_block (&block, tmp);
1135 tmp = build_v (LABEL_EXPR, end_label);
1136 gfc_add_expr_to_block (&block, tmp);
1141 return gfc_finish_block (&block);
1145 /* Translate the three variants of the SELECT CASE construct.
1147 SELECT CASEs with INTEGER case expressions can be translated to an
1148 equivalent GENERIC switch statement, and for LOGICAL case
1149 expressions we build one or two if-else compares.
1151 SELECT CASEs with CHARACTER case expressions are a whole different
1152 story, because they don't exist in GENERIC. So we sort them and
1153 do a binary search at runtime.
1155 Fortran has no BREAK statement, and it does not allow jumps from
1156 one case block to another. That makes things a lot easier for
1160 gfc_trans_select (gfc_code * code)
1162 assert (code && code->expr);
1164 /* Empty SELECT constructs are legal. */
1165 if (code->block == NULL)
1166 return build_empty_stmt ();
1168 /* Select the correct translation function. */
1169 switch (code->expr->ts.type)
1171 case BT_LOGICAL: return gfc_trans_logical_select (code);
1172 case BT_INTEGER: return gfc_trans_integer_select (code);
1173 case BT_CHARACTER: return gfc_trans_character_select (code);
1175 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
1181 /* Generate the loops for a FORALL block. The normal loop format:
1182 count = (end - start + step) / step
1195 gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_flag)
1203 tree var, start, end, step, mask, maskindex;
1206 iter = forall_tmp->this_loop;
1207 for (n = 0; n < nvar; n++)
1210 start = iter->start;
1214 exit_label = gfc_build_label_decl (NULL_TREE);
1215 TREE_USED (exit_label) = 1;
1217 /* The loop counter. */
1218 count = gfc_create_var (TREE_TYPE (var), "count");
1220 /* The body of the loop. */
1221 gfc_init_block (&block);
1223 /* The exit condition. */
1224 cond = build (LE_EXPR, boolean_type_node, count, integer_zero_node);
1225 tmp = build1_v (GOTO_EXPR, exit_label);
1226 tmp = build_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1227 gfc_add_expr_to_block (&block, tmp);
1229 /* The main loop body. */
1230 gfc_add_expr_to_block (&block, body);
1232 /* Increment the loop variable. */
1233 tmp = build (PLUS_EXPR, TREE_TYPE (var), var, step);
1234 gfc_add_modify_expr (&block, var, tmp);
1236 /* Advance to the next mask element. */
1239 mask = forall_tmp->mask;
1240 maskindex = forall_tmp->maskindex;
1243 tmp = build (PLUS_EXPR, gfc_array_index_type, maskindex,
1245 gfc_add_modify_expr (&block, maskindex, tmp);
1248 /* Decrement the loop counter. */
1249 tmp = build (MINUS_EXPR, TREE_TYPE (var), count, integer_one_node);
1250 gfc_add_modify_expr (&block, count, tmp);
1252 body = gfc_finish_block (&block);
1254 /* Loop var initialization. */
1255 gfc_init_block (&block);
1256 gfc_add_modify_expr (&block, var, start);
1258 /* Initialize the loop counter. */
1259 tmp = fold (build (MINUS_EXPR, TREE_TYPE (var), step, start));
1260 tmp = fold (build (PLUS_EXPR, TREE_TYPE (var), end, tmp));
1261 tmp = fold (build (TRUNC_DIV_EXPR, TREE_TYPE (var), tmp, step));
1262 gfc_add_modify_expr (&block, count, tmp);
1264 /* The loop expression. */
1265 tmp = build_v (LOOP_EXPR, body);
1266 gfc_add_expr_to_block (&block, tmp);
1268 /* The exit label. */
1269 tmp = build1_v (LABEL_EXPR, exit_label);
1270 gfc_add_expr_to_block (&block, tmp);
1272 body = gfc_finish_block (&block);
1279 /* Generate the body and loops according to MASK_FLAG and NEST_FLAG.
1280 if MASK_FLAG is non-zero, the body is controlled by maskes in forall
1281 nest, otherwise, the body is not controlled by maskes.
1282 if NEST_FLAG is non-zero, generate loops for nested forall, otherwise,
1283 only generate loops for the current forall level. */
1286 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
1287 int mask_flag, int nest_flag)
1291 forall_info *forall_tmp;
1292 tree pmask, mask, maskindex;
1294 forall_tmp = nested_forall_info;
1295 /* Generate loops for nested forall. */
1298 while (forall_tmp->next_nest != NULL)
1299 forall_tmp = forall_tmp->next_nest;
1300 while (forall_tmp != NULL)
1302 /* Generate body with masks' control. */
1305 pmask = forall_tmp->pmask;
1306 mask = forall_tmp->mask;
1307 maskindex = forall_tmp->maskindex;
1311 /* If a mask was specified make the assignment contitional. */
1313 tmp = gfc_build_indirect_ref (mask);
1316 tmp = gfc_build_array_ref (tmp, maskindex);
1318 body = build_v (COND_EXPR, tmp, body, build_empty_stmt ());
1321 nvar = forall_tmp->nvar;
1322 body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1323 forall_tmp = forall_tmp->outer;
1328 nvar = forall_tmp->nvar;
1329 body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1336 /* Allocate data for holding a temporary array. Returns either a local
1337 temporary array or a pointer variable. */
1340 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
1348 if (INTEGER_CST_P (size))
1350 tmp = fold (build (MINUS_EXPR, gfc_array_index_type, size,
1356 type = build_range_type (gfc_array_index_type, integer_zero_node, tmp);
1357 type = build_array_type (elem_type, type);
1358 if (gfc_can_put_var_on_stack (bytesize))
1360 assert (INTEGER_CST_P (size));
1361 tmpvar = gfc_create_var (type, "temp");
1366 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
1367 *pdata = convert (pvoid_type_node, tmpvar);
1369 args = gfc_chainon_list (NULL_TREE, bytesize);
1370 if (gfc_index_integer_kind == 4)
1371 tmp = gfor_fndecl_internal_malloc;
1372 else if (gfc_index_integer_kind == 8)
1373 tmp = gfor_fndecl_internal_malloc64;
1376 tmp = gfc_build_function_call (tmp, args);
1377 tmp = convert (TREE_TYPE (tmpvar), tmp);
1378 gfc_add_modify_expr (pblock, tmpvar, tmp);
1384 /* Generate codes to copy the temporary to the actual lhs. */
1387 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree size,
1388 tree count3, tree count1, tree count2, tree wheremask)
1392 stmtblock_t block, body;
1399 lss = gfc_walk_expr (expr);
1401 if (lss == gfc_ss_terminator)
1403 gfc_start_block (&block);
1405 gfc_init_se (&lse, NULL);
1407 /* Translate the expression. */
1408 gfc_conv_expr (&lse, expr);
1410 /* Form the expression for the temporary. */
1411 tmp = gfc_build_array_ref (tmp1, count1);
1413 /* Use the scalar assignment as is. */
1414 gfc_add_block_to_block (&block, &lse.pre);
1415 gfc_add_modify_expr (&block, lse.expr, tmp);
1416 gfc_add_block_to_block (&block, &lse.post);
1418 /* Increment the count1. */
1419 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1, size));
1420 gfc_add_modify_expr (&block, count1, tmp);
1421 tmp = gfc_finish_block (&block);
1425 gfc_start_block (&block);
1427 gfc_init_loopinfo (&loop1);
1428 gfc_init_se (&rse, NULL);
1429 gfc_init_se (&lse, NULL);
1431 /* Associate the lss with the loop. */
1432 gfc_add_ss_to_loop (&loop1, lss);
1434 /* Calculate the bounds of the scalarization. */
1435 gfc_conv_ss_startstride (&loop1);
1436 /* Setup the scalarizing loops. */
1437 gfc_conv_loop_setup (&loop1);
1439 gfc_mark_ss_chain_used (lss, 1);
1440 /* Initialize count2. */
1441 gfc_add_modify_expr (&block, count2, integer_zero_node);
1443 /* Start the scalarized loop body. */
1444 gfc_start_scalarized_body (&loop1, &body);
1446 /* Setup the gfc_se structures. */
1447 gfc_copy_loopinfo_to_se (&lse, &loop1);
1450 /* Form the expression of the temporary. */
1451 if (lss != gfc_ss_terminator)
1453 index = fold (build (PLUS_EXPR, gfc_array_index_type,
1455 rse.expr = gfc_build_array_ref (tmp1, index);
1457 /* Translate expr. */
1458 gfc_conv_expr (&lse, expr);
1460 /* Use the scalar assignment. */
1461 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
1463 /* Form the mask expression according to the mask tree list. */
1468 wheremaskexpr = gfc_build_array_ref (tmp2, count3);
1469 tmp2 = TREE_CHAIN (tmp2);
1472 tmp1 = gfc_build_array_ref (tmp2, count3);
1473 wheremaskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1),
1474 wheremaskexpr, tmp1);
1475 tmp2 = TREE_CHAIN (tmp2);
1477 tmp = build_v (COND_EXPR, wheremaskexpr, tmp, build_empty_stmt ());
1480 gfc_add_expr_to_block (&body, tmp);
1482 /* Increment count2. */
1483 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count2), count2,
1485 gfc_add_modify_expr (&body, count2, tmp);
1487 /* Increment count3. */
1490 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count3), count3,
1492 gfc_add_modify_expr (&body, count3, tmp);
1495 /* Generate the copying loops. */
1496 gfc_trans_scalarizing_loops (&loop1, &body);
1497 gfc_add_block_to_block (&block, &loop1.pre);
1498 gfc_add_block_to_block (&block, &loop1.post);
1499 gfc_cleanup_loop (&loop1);
1501 /* Increment count1. */
1502 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1, size));
1503 gfc_add_modify_expr (&block, count1, tmp);
1504 tmp = gfc_finish_block (&block);
1510 /* Generate codes to copy rhs to the temporary. TMP1 is the address of temporary
1511 LSS and RSS are formed in function compute_inner_temp_size(), and should
1515 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree size,
1516 tree count3, tree count1, tree count2,
1517 gfc_ss *lss, gfc_ss *rss, tree wheremask)
1519 stmtblock_t block, body1;
1523 tree tmp, tmp2, index;
1526 gfc_start_block (&block);
1528 gfc_init_se (&rse, NULL);
1529 gfc_init_se (&lse, NULL);
1531 if (lss == gfc_ss_terminator)
1533 gfc_init_block (&body1);
1534 gfc_conv_expr (&rse, expr2);
1535 lse.expr = gfc_build_array_ref (tmp1, count1);
1539 /* Initilize count2. */
1540 gfc_add_modify_expr (&block, count2, integer_zero_node);
1542 /* Initiliaze the loop. */
1543 gfc_init_loopinfo (&loop);
1545 /* We may need LSS to determine the shape of the expression. */
1546 gfc_add_ss_to_loop (&loop, lss);
1547 gfc_add_ss_to_loop (&loop, rss);
1549 gfc_conv_ss_startstride (&loop);
1550 gfc_conv_loop_setup (&loop);
1552 gfc_mark_ss_chain_used (rss, 1);
1553 /* Start the loop body. */
1554 gfc_start_scalarized_body (&loop, &body1);
1556 /* Translate the expression. */
1557 gfc_copy_loopinfo_to_se (&rse, &loop);
1559 gfc_conv_expr (&rse, expr2);
1561 /* Form the expression of the temporary. */
1562 index = fold (build (PLUS_EXPR, gfc_array_index_type, count1, count2));
1563 lse.expr = gfc_build_array_ref (tmp1, index);
1566 /* Use the scalar assignment. */
1567 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts.type);
1569 /* Form the mask expression according to the mask tree list. */
1574 wheremaskexpr = gfc_build_array_ref (tmp2, count3);
1575 tmp2 = TREE_CHAIN (tmp2);
1578 tmp1 = gfc_build_array_ref (tmp2, count3);
1579 wheremaskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1),
1580 wheremaskexpr, tmp1);
1581 tmp2 = TREE_CHAIN (tmp2);
1583 tmp = build_v (COND_EXPR, wheremaskexpr, tmp, build_empty_stmt ());
1586 gfc_add_expr_to_block (&body1, tmp);
1588 if (lss == gfc_ss_terminator)
1590 gfc_add_block_to_block (&block, &body1);
1594 /* Increment count2. */
1595 tmp = fold (build (PLUS_EXPR, gfc_array_index_type, count2,
1597 gfc_add_modify_expr (&body1, count2, tmp);
1599 /* Increment count3. */
1602 tmp = fold (build (PLUS_EXPR, gfc_array_index_type, count3,
1604 gfc_add_modify_expr (&body1, count3, tmp);
1607 /* Generate the copying loops. */
1608 gfc_trans_scalarizing_loops (&loop, &body1);
1610 gfc_add_block_to_block (&block, &loop.pre);
1611 gfc_add_block_to_block (&block, &loop.post);
1613 gfc_cleanup_loop (&loop);
1614 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
1615 as tree nodes in SS may not be valid in different scope. */
1617 /* Increment count1. */
1618 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1, size));
1619 gfc_add_modify_expr (&block, count1, tmp);
1621 tmp = gfc_finish_block (&block);
1626 /* Calculate the size of temporary needed in the assignment inside forall.
1627 LSS and RSS are filled in this function. */
1630 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
1631 stmtblock_t * pblock,
1632 gfc_ss **lss, gfc_ss **rss)
1639 *lss = gfc_walk_expr (expr1);
1642 size = integer_one_node;
1643 if (*lss != gfc_ss_terminator)
1645 gfc_init_loopinfo (&loop);
1647 /* Walk the RHS of the expression. */
1648 *rss = gfc_walk_expr (expr2);
1649 if (*rss == gfc_ss_terminator)
1651 /* The rhs is scalar. Add a ss for the expression. */
1652 *rss = gfc_get_ss ();
1653 (*rss)->next = gfc_ss_terminator;
1654 (*rss)->type = GFC_SS_SCALAR;
1655 (*rss)->expr = expr2;
1658 /* Associate the SS with the loop. */
1659 gfc_add_ss_to_loop (&loop, *lss);
1660 /* We don't actually need to add the rhs at this point, but it might
1661 make guessing the loop bounds a bit easier. */
1662 gfc_add_ss_to_loop (&loop, *rss);
1664 /* We only want the shape of the expression, not rest of the junk
1665 generated by the scalarizer. */
1666 loop.array_parameter = 1;
1668 /* Calculate the bounds of the scalarization. */
1669 gfc_conv_ss_startstride (&loop);
1670 gfc_conv_loop_setup (&loop);
1672 /* Figure out how many elements we need. */
1673 for (i = 0; i < loop.dimen; i++)
1675 tmp = fold (build (MINUS_EXPR, TREE_TYPE (loop.from[i]),
1676 integer_one_node, loop.from[i]));
1677 tmp = fold (build (PLUS_EXPR, TREE_TYPE (tmp), tmp, loop.to[i]));
1678 size = fold (build (MULT_EXPR, TREE_TYPE (size), size, tmp));
1680 gfc_add_block_to_block (pblock, &loop.pre);
1681 size = gfc_evaluate_now (size, pblock);
1682 gfc_add_block_to_block (pblock, &loop.post);
1684 /* TODO: write a function that cleans up a loopinfo without freeing
1685 the SS chains. Currently a NOP. */
1692 /* Calculate the overall iterator number of the nested forall construct. */
1695 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
1701 /* TODO: optimizing the computing process. */
1702 number = gfc_create_var (gfc_array_index_type, "num");
1703 gfc_add_modify_expr (block, number, integer_zero_node);
1705 gfc_start_block (&body);
1706 if (nested_forall_info)
1707 tmp = build (PLUS_EXPR, gfc_array_index_type, number,
1711 gfc_add_modify_expr (&body, number, tmp);
1712 tmp = gfc_finish_block (&body);
1714 /* Generate loops. */
1715 if (nested_forall_info != NULL)
1716 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 0, 1);
1718 gfc_add_expr_to_block (block, tmp);
1724 /* Allocate temporary for forall construct according to the information in
1725 nested_forall_info. INNER_SIZE is the size of temporary needed in the
1726 assignment inside forall. PTEMP1 is returned for space free. */
1729 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
1730 tree inner_size, stmtblock_t * block,
1736 tree bytesize, size;
1738 /* Calculate the total size of temporary needed in forall construct. */
1739 size = compute_overall_iter_number (nested_forall_info, inner_size, block);
1741 unit = TYPE_SIZE_UNIT (type);
1742 bytesize = fold (build (MULT_EXPR, gfc_array_index_type, size, unit));
1745 temp1 = gfc_do_allocate (bytesize, size, ptemp1, block, type);
1748 tmp = gfc_build_indirect_ref (temp1);
1756 /* Handle assignments inside forall which need temporary. */
1758 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, tree wheremask,
1759 forall_info * nested_forall_info,
1760 stmtblock_t * block)
1765 tree count, count1, count2;
1768 tree mask, maskindex;
1769 forall_info *forall_tmp;
1771 /* Create vars. count1 is the current iterator number of the nested forall.
1772 count2 is the current iterator number of the inner loops needed in the
1774 count1 = gfc_create_var (gfc_array_index_type, "count1");
1775 count2 = gfc_create_var (gfc_array_index_type, "count2");
1777 /* Count is the wheremask index. */
1780 count = gfc_create_var (gfc_array_index_type, "count");
1781 gfc_add_modify_expr (block, count, integer_zero_node);
1786 /* Initialize count1. */
1787 gfc_add_modify_expr (block, count1, integer_zero_node);
1789 /* Calculate the size of temporary needed in the assignment. Return loop, lss
1790 and rss which are used in function generate_loop_for_rhs_to_temp(). */
1791 inner_size = compute_inner_temp_size (expr1, expr2, block, &lss, &rss);
1793 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
1794 type = gfc_typenode_for_spec (&expr1->ts);
1796 /* Allocate temporary for nested forall construct according to the
1797 information in nested_forall_info and inner_size. */
1798 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
1799 inner_size, block, &ptemp1);
1801 /* Initialize the maskindexes. */
1802 forall_tmp = nested_forall_info;
1803 while (forall_tmp != NULL)
1805 mask = forall_tmp->mask;
1806 maskindex = forall_tmp->maskindex;
1808 gfc_add_modify_expr (block, maskindex, integer_zero_node);
1809 forall_tmp = forall_tmp->next_nest;
1812 /* Generate codes to copy rhs to the temporary . */
1813 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, inner_size, count,
1814 count1, count2, lss, rss, wheremask);
1816 /* Generate body and loops according to the inforamtion in
1817 nested_forall_info. */
1818 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
1819 gfc_add_expr_to_block (block, tmp);
1822 gfc_add_modify_expr (block, count1, integer_zero_node);
1824 /* Reset maskindexed. */
1825 forall_tmp = nested_forall_info;
1826 while (forall_tmp != NULL)
1828 mask = forall_tmp->mask;
1829 maskindex = forall_tmp->maskindex;
1831 gfc_add_modify_expr (block, maskindex, integer_zero_node);
1832 forall_tmp = forall_tmp->next_nest;
1837 gfc_add_modify_expr (block, count, integer_zero_node);
1839 /* Generate codes to copy the temporary to lhs. */
1840 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, inner_size, count,
1841 count1, count2, wheremask);
1843 /* Generate body and loops according to the inforamtion in
1844 nested_forall_info. */
1845 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
1846 gfc_add_expr_to_block (block, tmp);
1850 /* Free the temporary. */
1851 tmp = gfc_chainon_list (NULL_TREE, ptemp1);
1852 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
1853 gfc_add_expr_to_block (block, tmp);
1858 /* Translate pointer assignment inside FORALL which need temporary. */
1861 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
1862 forall_info * nested_forall_info,
1863 stmtblock_t * block)
1877 tree tmp, tmp1, ptemp1;
1878 tree mask, maskindex;
1879 forall_info *forall_tmp;
1881 count = gfc_create_var (gfc_array_index_type, "count");
1882 gfc_add_modify_expr (block, count, integer_zero_node);
1884 inner_size = integer_one_node;
1885 lss = gfc_walk_expr (expr1);
1886 rss = gfc_walk_expr (expr2);
1887 if (lss == gfc_ss_terminator)
1889 type = gfc_typenode_for_spec (&expr1->ts);
1890 type = build_pointer_type (type);
1892 /* Allocate temporary for nested forall construct according to the
1893 information in nested_forall_info and inner_size. */
1894 tmp1 = allocate_temp_for_forall_nest (nested_forall_info,
1895 type, inner_size, block, &ptemp1);
1896 gfc_start_block (&body);
1897 gfc_init_se (&lse, NULL);
1898 lse.expr = gfc_build_array_ref (tmp1, count);
1899 gfc_init_se (&rse, NULL);
1900 rse.want_pointer = 1;
1901 gfc_conv_expr (&rse, expr2);
1902 gfc_add_block_to_block (&body, &rse.pre);
1903 gfc_add_modify_expr (&body, lse.expr, rse.expr);
1904 gfc_add_block_to_block (&body, &rse.post);
1906 /* Increment count. */
1907 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count), count,
1909 gfc_add_modify_expr (&body, count, tmp);
1911 tmp = gfc_finish_block (&body);
1913 /* Initialize the maskindexes. */
1914 forall_tmp = nested_forall_info;
1915 while (forall_tmp != NULL)
1917 mask = forall_tmp->mask;
1918 maskindex = forall_tmp->maskindex;
1920 gfc_add_modify_expr (block, maskindex, integer_zero_node);
1921 forall_tmp = forall_tmp->next_nest;
1924 /* Generate body and loops according to the inforamtion in
1925 nested_forall_info. */
1926 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
1927 gfc_add_expr_to_block (block, tmp);
1930 gfc_add_modify_expr (block, count, integer_zero_node);
1932 /* Reset maskindexes. */
1933 forall_tmp = nested_forall_info;
1934 while (forall_tmp != NULL)
1936 mask = forall_tmp->mask;
1937 maskindex = forall_tmp->maskindex;
1939 gfc_add_modify_expr (block, maskindex, integer_zero_node);
1940 forall_tmp = forall_tmp->next_nest;
1942 gfc_start_block (&body);
1943 gfc_init_se (&lse, NULL);
1944 gfc_init_se (&rse, NULL);
1945 rse.expr = gfc_build_array_ref (tmp1, count);
1946 lse.want_pointer = 1;
1947 gfc_conv_expr (&lse, expr1);
1948 gfc_add_block_to_block (&body, &lse.pre);
1949 gfc_add_modify_expr (&body, lse.expr, rse.expr);
1950 gfc_add_block_to_block (&body, &lse.post);
1951 /* Increment count. */
1952 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count), count,
1954 gfc_add_modify_expr (&body, count, tmp);
1955 tmp = gfc_finish_block (&body);
1957 /* Generate body and loops according to the inforamtion in
1958 nested_forall_info. */
1959 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
1960 gfc_add_expr_to_block (block, tmp);
1964 gfc_init_loopinfo (&loop);
1966 /* Associate the SS with the loop. */
1967 gfc_add_ss_to_loop (&loop, rss);
1969 /* Setup the scalarizing loops and bounds. */
1970 gfc_conv_ss_startstride (&loop);
1972 gfc_conv_loop_setup (&loop);
1974 info = &rss->data.info;
1975 desc = info->descriptor;
1977 /* Make a new descriptor. */
1978 parmtype = gfc_get_element_type (TREE_TYPE (desc));
1979 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
1980 loop.from, loop.to, 1);
1982 /* Allocate temporary for nested forall construct. */
1983 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
1984 inner_size, block, &ptemp1);
1985 gfc_start_block (&body);
1986 gfc_init_se (&lse, NULL);
1987 lse.expr = gfc_build_array_ref (tmp1, count);
1988 lse.direct_byref = 1;
1989 rss = gfc_walk_expr (expr2);
1990 gfc_conv_expr_descriptor (&lse, expr2, rss);
1992 gfc_add_block_to_block (&body, &lse.pre);
1993 gfc_add_block_to_block (&body, &lse.post);
1995 /* Increment count. */
1996 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count), count,
1998 gfc_add_modify_expr (&body, count, tmp);
2000 tmp = gfc_finish_block (&body);
2002 /* Initialize the maskindexes. */
2003 forall_tmp = nested_forall_info;
2004 while (forall_tmp != NULL)
2006 mask = forall_tmp->mask;
2007 maskindex = forall_tmp->maskindex;
2009 gfc_add_modify_expr (block, maskindex, integer_zero_node);
2010 forall_tmp = forall_tmp->next_nest;
2013 /* Generate body and loops according to the inforamtion in
2014 nested_forall_info. */
2015 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2016 gfc_add_expr_to_block (block, tmp);
2019 gfc_add_modify_expr (block, count, integer_zero_node);
2021 /* Reset maskindexes. */
2022 forall_tmp = nested_forall_info;
2023 while (forall_tmp != NULL)
2025 mask = forall_tmp->mask;
2026 maskindex = forall_tmp->maskindex;
2028 gfc_add_modify_expr (block, maskindex, integer_zero_node);
2029 forall_tmp = forall_tmp->next_nest;
2031 parm = gfc_build_array_ref (tmp1, count);
2032 lss = gfc_walk_expr (expr1);
2033 gfc_init_se (&lse, NULL);
2034 gfc_conv_expr_descriptor (&lse, expr1, lss);
2035 gfc_add_modify_expr (&lse.pre, lse.expr, parm);
2036 gfc_start_block (&body);
2037 gfc_add_block_to_block (&body, &lse.pre);
2038 gfc_add_block_to_block (&body, &lse.post);
2040 /* Increment count. */
2041 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count), count,
2043 gfc_add_modify_expr (&body, count, tmp);
2045 tmp = gfc_finish_block (&body);
2047 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2048 gfc_add_expr_to_block (block, tmp);
2050 /* Free the temporary. */
2053 tmp = gfc_chainon_list (NULL_TREE, ptemp1);
2054 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2055 gfc_add_expr_to_block (block, tmp);
2060 /* FORALL and WHERE statements are really nasty, especially when you nest
2061 them. All the rhs of a forall assignment must be evaluated before the
2062 actual assignments are performed. Presumably this also applies to all the
2063 assignments in an inner where statement. */
2065 /* Generate code for a FORALL statement. Any temporaries are allocated as a
2066 linear array, relying on the fact that we process in the same order in all
2069 forall (i=start:end:stride; maskexpr)
2073 (where e,f,g,h<i> are arbitary expressions possibly involving i)
2075 count = ((end + 1 - start) / staride)
2076 masktmp(:) = maskexpr(:)
2079 for (i = start; i <= end; i += stride)
2081 if (masktmp[maskindex++])
2085 for (i = start; i <= end; i += stride)
2087 if (masktmp[maskindex++])
2091 Note that this code only works when there are no dependencies.
2092 Forall loop with array assignments and data dependencies are a real pain,
2093 because the size of the temporary cannot always be determined before the
2094 loop is executed. This problem is compouded by the presence of nested
2099 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
2121 gfc_forall_iterator *fa;
2124 tree *saved_var_decl;
2125 symbol_attribute *saved_var_attr;
2126 iter_info *this_forall, *iter_tmp;
2127 forall_info *info, *forall_tmp;
2128 temporary_list *temp;
2130 gfc_start_block (&block);
2133 /* Count the FORALL index number. */
2134 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2138 /* Allocate the space for var, start, end, step, varexpr. */
2139 var = (tree *) gfc_getmem (nvar * sizeof (tree));
2140 start = (tree *) gfc_getmem (nvar * sizeof (tree));
2141 end = (tree *) gfc_getmem (nvar * sizeof (tree));
2142 step = (tree *) gfc_getmem (nvar * sizeof (tree));
2143 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
2144 saved_var_decl = (tree *) gfc_getmem (nvar * sizeof (tree));
2145 saved_var_attr = (symbol_attribute *)
2146 gfc_getmem (nvar * sizeof (symbol_attribute));
2148 /* Allocate the space for info. */
2149 info = (forall_info *) gfc_getmem (sizeof (forall_info));
2151 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2153 gfc_symbol *sym = fa->var->symtree->n.sym;
2155 /* allocate space for this_forall. */
2156 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2158 /* Save the FORALL index's backend_decl. */
2159 saved_var_decl[n] = sym->backend_decl;
2161 /* Save the attribute. */
2162 saved_var_attr[n] = sym->attr;
2164 /* Set the proper attributes. */
2165 gfc_clear_attr (&sym->attr);
2166 sym->attr.referenced = 1;
2167 sym->attr.flavor = FL_VARIABLE;
2169 /* Create a temporary variable for the FORALL index. */
2170 tmp = gfc_typenode_for_spec (&sym->ts);
2171 var[n] = gfc_create_var (tmp, sym->name);
2172 /* Record it in this_forall. */
2173 this_forall->var = var[n];
2175 /* Replace the index symbol's backend_decl with the temporary decl. */
2176 sym->backend_decl = var[n];
2178 /* Work out the start, end and stride for the loop. */
2179 gfc_init_se (&se, NULL);
2180 gfc_conv_expr_val (&se, fa->start);
2181 /* Record it in this_forall. */
2182 this_forall->start = se.expr;
2183 gfc_add_block_to_block (&block, &se.pre);
2186 gfc_init_se (&se, NULL);
2187 gfc_conv_expr_val (&se, fa->end);
2188 /* Record it in this_forall. */
2189 this_forall->end = se.expr;
2190 gfc_make_safe_expr (&se);
2191 gfc_add_block_to_block (&block, &se.pre);
2194 gfc_init_se (&se, NULL);
2195 gfc_conv_expr_val (&se, fa->stride);
2196 /* Record it in this_forall. */
2197 this_forall->step = se.expr;
2198 gfc_make_safe_expr (&se);
2199 gfc_add_block_to_block (&block, &se.pre);
2202 /* Set the NEXT field of this_forall to NULL. */
2203 this_forall->next = NULL;
2204 /* Link this_forall to the info construct. */
2205 if (info->this_loop == NULL)
2206 info->this_loop = this_forall;
2209 iter_tmp = info->this_loop;
2210 while (iter_tmp->next != NULL)
2211 iter_tmp = iter_tmp->next;
2212 iter_tmp->next = this_forall;
2219 /* Work out the number of elements in the mask array. */
2222 size = integer_one_node;
2223 sizevar = NULL_TREE;
2225 for (n = 0; n < nvar; n++)
2227 if (lenvar && TREE_TYPE (lenvar) != TREE_TYPE (start[n]))
2230 /* size = (end + step - start) / step. */
2231 tmp = fold (build (MINUS_EXPR, TREE_TYPE (start[n]), step[n], start[n]));
2232 tmp = fold (build (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp));
2234 tmp = fold (build (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]));
2235 tmp = convert (gfc_array_index_type, tmp);
2237 size = fold (build (MULT_EXPR, gfc_array_index_type, size, tmp));
2240 /* Record the nvar and size of current forall level. */
2244 /* Link the current forall level to nested_forall_info. */
2245 forall_tmp = nested_forall_info;
2246 if (forall_tmp == NULL)
2247 nested_forall_info = info;
2250 while (forall_tmp->next_nest != NULL)
2251 forall_tmp = forall_tmp->next_nest;
2252 info->outer = forall_tmp;
2253 forall_tmp->next_nest = info;
2256 /* Copy the mask into a temporary variable if required.
2257 For now we assume a mask temporary is needed. */
2260 /* Allocate the mask temporary. */
2261 bytesize = fold (build (MULT_EXPR, gfc_array_index_type, size,
2262 TYPE_SIZE_UNIT (boolean_type_node)));
2264 mask = gfc_do_allocate (bytesize, size, &pmask, &block, boolean_type_node);
2266 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2267 /* Record them in the info structure. */
2268 info->pmask = pmask;
2270 info->maskindex = maskindex;
2272 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2274 /* Start of mask assignment loop body. */
2275 gfc_start_block (&body);
2277 /* Evaluate the mask expression. */
2278 gfc_init_se (&se, NULL);
2279 gfc_conv_expr_val (&se, code->expr);
2280 gfc_add_block_to_block (&body, &se.pre);
2282 /* Store the mask. */
2283 se.expr = convert (boolean_type_node, se.expr);
2286 tmp = gfc_build_indirect_ref (mask);
2289 tmp = gfc_build_array_ref (tmp, maskindex);
2290 gfc_add_modify_expr (&body, tmp, se.expr);
2292 /* Advance to the next mask element. */
2293 tmp = build (PLUS_EXPR, gfc_array_index_type, maskindex,
2295 gfc_add_modify_expr (&body, maskindex, tmp);
2297 /* Generate the loops. */
2298 tmp = gfc_finish_block (&body);
2299 tmp = gfc_trans_nested_forall_loop (info, tmp, 0, 0);
2300 gfc_add_expr_to_block (&block, tmp);
2304 /* No mask was specified. */
2305 maskindex = NULL_TREE;
2306 mask = pmask = NULL_TREE;
2309 c = code->block->next;
2311 /* TODO: loop merging in FORALL statements. */
2312 /* Now that we've got a copy of the mask, generate the assignment loops. */
2318 /* A scalar or array assingment. */
2319 need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2320 /* Teporaries due to array assignment data dependencies introduce
2321 no end of problems. */
2323 gfc_trans_assign_need_temp (c->expr, c->expr2, NULL,
2324 nested_forall_info, &block);
2327 /* Use the normal assignment copying routines. */
2328 assign = gfc_trans_assignment (c->expr, c->expr2);
2330 /* Reset the mask index. */
2332 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2334 /* Generate body and loops. */
2335 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2336 gfc_add_expr_to_block (&block, tmp);
2343 /* Translate WHERE or WHERE construct nested in FORALL. */
2345 gfc_trans_where_2 (c, NULL, NULL, nested_forall_info, &block, &temp);
2352 /* Free the temporary. */
2353 args = gfc_chainon_list (NULL_TREE, temp->temporary);
2354 tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
2355 gfc_add_expr_to_block (&block, tmp);
2364 /* Pointer assignment inside FORALL. */
2365 case EXEC_POINTER_ASSIGN:
2366 need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2368 gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
2369 nested_forall_info, &block);
2372 /* Use the normal assignment copying routines. */
2373 assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
2375 /* Reset the mask index. */
2377 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2379 /* Generate body and loops. */
2380 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign,
2382 gfc_add_expr_to_block (&block, tmp);
2387 tmp = gfc_trans_forall_1 (c, nested_forall_info);
2388 gfc_add_expr_to_block (&block, tmp);
2399 /* Restore the index original backend_decl and the attribute. */
2400 for (fa = code->ext.forall_iterator, n=0; fa; fa = fa->next, n++)
2402 gfc_symbol *sym = fa->var->symtree->n.sym;
2403 sym->backend_decl = saved_var_decl[n];
2404 sym->attr = saved_var_attr[n];
2407 /* Free the space for var, start, end, step, varexpr. */
2413 gfc_free (saved_var_decl);
2414 gfc_free (saved_var_attr);
2418 /* Free the temporary for the mask. */
2419 tmp = gfc_chainon_list (NULL_TREE, pmask);
2420 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2421 gfc_add_expr_to_block (&block, tmp);
2424 pushdecl (maskindex);
2426 return gfc_finish_block (&block);
2430 /* Translate the FORALL statement or construct. */
2432 tree gfc_trans_forall (gfc_code * code)
2434 return gfc_trans_forall_1 (code, NULL);
2438 /* Evaluate the WHERE mask expression, copy its value to a temporary.
2439 If the WHERE construct is nested in FORALL, compute the overall temporary
2440 needed by the WHERE mask expression multiplied by the iterator number of
2442 ME is the WHERE mask expression.
2443 MASK is the temporary which value is mask's value.
2444 NMASK is another temporary which value is !mask.
2445 TEMP records the temporary's address allocated in this function in order to
2446 free them outside this function.
2447 MASK, NMASK and TEMP are all OUT arguments. */
2450 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
2451 tree * mask, tree * nmask, temporary_list ** temp,
2452 stmtblock_t * block)
2457 tree ptemp1, ntmp, ptemp2;
2459 stmtblock_t body, body1;
2464 gfc_init_loopinfo (&loop);
2466 /* Calculate the size of temporary needed by the mask-expr. */
2467 inner_size = compute_inner_temp_size (me, me, block, &lss, &rss);
2469 /* Allocate temporary for where mask. */
2470 tmp = allocate_temp_for_forall_nest (nested_forall_info, boolean_type_node,
2471 inner_size, block, &ptemp1);
2472 /* Record the temporary address in order to free it later. */
2475 temporary_list *tempo;
2476 tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2477 tempo->temporary = ptemp1;
2478 tempo->next = *temp;
2482 /* Allocate temporary for !mask. */
2483 ntmp = allocate_temp_for_forall_nest (nested_forall_info, boolean_type_node,
2484 inner_size, block, &ptemp2);
2485 /* Record the temporary in order to free it later. */
2488 temporary_list *tempo;
2489 tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2490 tempo->temporary = ptemp2;
2491 tempo->next = *temp;
2495 /* Variable to index the temporary. */
2496 count = gfc_create_var (gfc_array_index_type, "count");
2497 /* Initilize count. */
2498 gfc_add_modify_expr (block, count, integer_zero_node);
2500 gfc_start_block (&body);
2502 gfc_init_se (&rse, NULL);
2503 gfc_init_se (&lse, NULL);
2505 if (lss == gfc_ss_terminator)
2507 gfc_init_block (&body1);
2511 /* Initiliaze the loop. */
2512 gfc_init_loopinfo (&loop);
2514 /* We may need LSS to determine the shape of the expression. */
2515 gfc_add_ss_to_loop (&loop, lss);
2516 gfc_add_ss_to_loop (&loop, rss);
2518 gfc_conv_ss_startstride (&loop);
2519 gfc_conv_loop_setup (&loop);
2521 gfc_mark_ss_chain_used (rss, 1);
2522 /* Start the loop body. */
2523 gfc_start_scalarized_body (&loop, &body1);
2525 /* Translate the expression. */
2526 gfc_copy_loopinfo_to_se (&rse, &loop);
2528 gfc_conv_expr (&rse, me);
2530 /* Form the expression of the temporary. */
2531 lse.expr = gfc_build_array_ref (tmp, count);
2532 tmpexpr = gfc_build_array_ref (ntmp, count);
2534 /* Use the scalar assignment to fill temporary TMP. */
2535 tmp1 = gfc_trans_scalar_assign (&lse, &rse, me->ts.type);
2536 gfc_add_expr_to_block (&body1, tmp1);
2538 /* Fill temporary NTMP. */
2539 tmp1 = build1 (TRUTH_NOT_EXPR, TREE_TYPE (lse.expr), lse.expr);
2540 gfc_add_modify_expr (&body1, tmpexpr, tmp1);
2542 if (lss == gfc_ss_terminator)
2544 gfc_add_block_to_block (&body, &body1);
2548 /* Increment count. */
2549 tmp1 = fold (build (PLUS_EXPR, gfc_array_index_type, count,
2551 gfc_add_modify_expr (&body1, count, tmp1);
2553 /* Generate the copying loops. */
2554 gfc_trans_scalarizing_loops (&loop, &body1);
2556 gfc_add_block_to_block (&body, &loop.pre);
2557 gfc_add_block_to_block (&body, &loop.post);
2559 gfc_cleanup_loop (&loop);
2560 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
2561 as tree nodes in SS may not be valid in different scope. */
2564 tmp1 = gfc_finish_block (&body);
2565 /* If the WHERE construct is inside FORALL, fill the full temporary. */
2566 if (nested_forall_info != NULL)
2567 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1);
2570 gfc_add_expr_to_block (block, tmp1);
2579 /* Translate an assignment statement in a WHERE statement or construct
2580 statement. The MASK expression is used to control which elements
2581 of EXPR1 shall be assigned. */
2584 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2, tree mask,
2585 tree count1, tree count2)
2590 gfc_ss *lss_section;
2597 tree index, maskexpr, tmp1;
2600 /* TODO: handle this special case.
2601 Special case a single function returning an array. */
2602 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
2604 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
2610 /* Assignment of the form lhs = rhs. */
2611 gfc_start_block (&block);
2613 gfc_init_se (&lse, NULL);
2614 gfc_init_se (&rse, NULL);
2617 lss = gfc_walk_expr (expr1);
2620 /* In each where-assign-stmt, the mask-expr and the variable being
2621 defined shall be arrays of the same shape. */
2622 assert (lss != gfc_ss_terminator);
2624 /* The assignment needs scalarization. */
2627 /* Find a non-scalar SS from the lhs. */
2628 while (lss_section != gfc_ss_terminator
2629 && lss_section->type != GFC_SS_SECTION)
2630 lss_section = lss_section->next;
2632 assert (lss_section != gfc_ss_terminator);
2634 /* Initialize the scalarizer. */
2635 gfc_init_loopinfo (&loop);
2638 rss = gfc_walk_expr (expr2);
2639 if (rss == gfc_ss_terminator)
2641 /* The rhs is scalar. Add a ss for the expression. */
2642 rss = gfc_get_ss ();
2643 rss->next = gfc_ss_terminator;
2644 rss->type = GFC_SS_SCALAR;
2648 /* Associate the SS with the loop. */
2649 gfc_add_ss_to_loop (&loop, lss);
2650 gfc_add_ss_to_loop (&loop, rss);
2652 /* Calculate the bounds of the scalarization. */
2653 gfc_conv_ss_startstride (&loop);
2655 /* Resolve any data dependencies in the statement. */
2656 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
2658 /* Setup the scalarizing loops. */
2659 gfc_conv_loop_setup (&loop);
2661 /* Setup the gfc_se structures. */
2662 gfc_copy_loopinfo_to_se (&lse, &loop);
2663 gfc_copy_loopinfo_to_se (&rse, &loop);
2666 gfc_mark_ss_chain_used (rss, 1);
2667 if (loop.temp_ss == NULL)
2670 gfc_mark_ss_chain_used (lss, 1);
2674 lse.ss = loop.temp_ss;
2675 gfc_mark_ss_chain_used (lss, 3);
2676 gfc_mark_ss_chain_used (loop.temp_ss, 3);
2679 /* Start the scalarized loop body. */
2680 gfc_start_scalarized_body (&loop, &body);
2682 /* Translate the expression. */
2683 gfc_conv_expr (&rse, expr2);
2684 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
2686 gfc_conv_tmp_array_ref (&lse);
2687 gfc_advance_se_ss_chain (&lse);
2690 gfc_conv_expr (&lse, expr1);
2692 /* Form the mask expression according to the mask tree list. */
2696 maskexpr = gfc_build_array_ref (tmp, index);
2700 tmp = TREE_CHAIN (tmp);
2703 tmp1 = gfc_build_array_ref (tmp, index);
2704 maskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1), maskexpr, tmp1);
2705 tmp = TREE_CHAIN (tmp);
2707 /* Use the scalar assignment as is. */
2708 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2709 tmp = build_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2711 gfc_add_expr_to_block (&body, tmp);
2713 if (lss == gfc_ss_terminator)
2715 /* Increment count1. */
2716 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2718 gfc_add_modify_expr (&body, count1, tmp);
2720 /* Use the scalar assignment as is. */
2721 gfc_add_block_to_block (&block, &body);
2725 if (lse.ss != gfc_ss_terminator)
2727 if (rse.ss != gfc_ss_terminator)
2730 if (loop.temp_ss != NULL)
2732 /* Increment count1 before finish the main body of a scalarized
2734 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2736 gfc_add_modify_expr (&body, count1, tmp);
2737 gfc_trans_scalarized_loop_boundary (&loop, &body);
2739 /* We need to copy the temporary to the actual lhs. */
2740 gfc_init_se (&lse, NULL);
2741 gfc_init_se (&rse, NULL);
2742 gfc_copy_loopinfo_to_se (&lse, &loop);
2743 gfc_copy_loopinfo_to_se (&rse, &loop);
2745 rse.ss = loop.temp_ss;
2748 gfc_conv_tmp_array_ref (&rse);
2749 gfc_advance_se_ss_chain (&rse);
2750 gfc_conv_expr (&lse, expr1);
2752 if (lse.ss != gfc_ss_terminator)
2755 if (rse.ss != gfc_ss_terminator)
2758 /* Form the mask expression according to the mask tree list. */
2762 maskexpr = gfc_build_array_ref (tmp, index);
2766 tmp = TREE_CHAIN (tmp);
2769 tmp1 = gfc_build_array_ref (tmp, index);
2770 maskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1), maskexpr,
2772 tmp = TREE_CHAIN (tmp);
2774 /* Use the scalar assignment as is. */
2775 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2776 tmp = build_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2777 gfc_add_expr_to_block (&body, tmp);
2778 /* Increment count2. */
2779 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count2), count2,
2781 gfc_add_modify_expr (&body, count2, tmp);
2785 /* Increment count1. */
2786 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2788 gfc_add_modify_expr (&body, count1, tmp);
2791 /* Generate the copying loops. */
2792 gfc_trans_scalarizing_loops (&loop, &body);
2794 /* Wrap the whole thing up. */
2795 gfc_add_block_to_block (&block, &loop.pre);
2796 gfc_add_block_to_block (&block, &loop.post);
2797 gfc_cleanup_loop (&loop);
2800 return gfc_finish_block (&block);
2804 /* Translate the WHERE construct or statement.
2805 This fuction can be called iteratelly to translate the nested WHERE
2806 construct or statement.
2807 MASK is the control mask, and PMASK is the pending control mask.
2808 TEMP records the temporary address which must be freed later. */
2811 gfc_trans_where_2 (gfc_code * code, tree mask, tree pmask,
2812 forall_info * nested_forall_info, stmtblock_t * block,
2813 temporary_list ** temp)
2819 tree tmp, tmp1, tmp2;
2820 tree count1, count2;
2824 /* the WHERE statement or the WHERE construct statement. */
2825 cblock = code->block;
2828 /* Has mask-expr. */
2831 /* Ensure that the WHERE mask be evaluated only once. */
2832 tmp2 = gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
2833 &tmp, &tmp1, temp, block);
2835 /* Set the control mask and the pending control mask. */
2836 /* It's a where-stmt. */
2842 /* It's a nested where-stmt. */
2843 else if (mask && pmask == NULL)
2846 /* Use the TREE_CHAIN to list the masks. */
2847 tmp2 = copy_list (mask);
2848 pmask = chainon (mask, tmp1);
2849 mask = chainon (tmp2, tmp);
2851 /* It's a masked-elsewhere-stmt. */
2852 else if (mask && cblock->expr)
2855 tmp2 = copy_list (pmask);
2858 tmp2 = chainon (tmp2, tmp);
2859 pmask = chainon (mask, tmp1);
2863 /* It's a elsewhere-stmt. No mask-expr is present. */
2867 /* Get the assignment statement of a WHERE statement, or the first
2868 statement in where-body-construct of a WHERE construct. */
2869 cnext = cblock->next;
2874 /* WHERE assignment statement. */
2876 expr1 = cnext->expr;
2877 expr2 = cnext->expr2;
2878 if (nested_forall_info != NULL)
2883 nvar = nested_forall_info->nvar;
2884 varexpr = (gfc_expr **)
2885 gfc_getmem (nvar * sizeof (gfc_expr *));
2886 need_temp = gfc_check_dependency (expr1, expr2, varexpr,
2889 gfc_trans_assign_need_temp (expr1, expr2, mask,
2890 nested_forall_info, block);
2893 /* Variables to control maskexpr. */
2894 count1 = gfc_create_var (gfc_array_index_type, "count1");
2895 count2 = gfc_create_var (gfc_array_index_type, "count2");
2896 gfc_add_modify_expr (block, count1, integer_zero_node);
2897 gfc_add_modify_expr (block, count2, integer_zero_node);
2899 tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
2901 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
2903 gfc_add_expr_to_block (block, tmp);
2908 /* Variables to control maskexpr. */
2909 count1 = gfc_create_var (gfc_array_index_type, "count1");
2910 count2 = gfc_create_var (gfc_array_index_type, "count2");
2911 gfc_add_modify_expr (block, count1, integer_zero_node);
2912 gfc_add_modify_expr (block, count2, integer_zero_node);
2914 tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
2916 gfc_add_expr_to_block (block, tmp);
2921 /* WHERE or WHERE construct is part of a where-body-construct. */
2923 /* Ensure that MASK is not modified by next gfc_trans_where_2. */
2924 mask_copy = copy_list (mask);
2925 gfc_trans_where_2 (cnext, mask_copy, NULL, nested_forall_info,
2933 /* The next statement within the same where-body-construct. */
2934 cnext = cnext->next;
2936 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
2937 cblock = cblock->block;
2942 /* As the WHERE or WHERE construct statement can be nested, we call
2943 gfc_trans_where_2 to do the translation, and pass the initial
2944 NULL values for both the control mask and the pending control mask. */
2947 gfc_trans_where (gfc_code * code)
2950 temporary_list *temp, *p;
2954 gfc_start_block (&block);
2957 gfc_trans_where_2 (code, NULL, NULL, NULL, &block, &temp);
2959 /* Add calls to free temporaries which were dynamically allocated. */
2962 args = gfc_chainon_list (NULL_TREE, temp->temporary);
2963 tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
2964 gfc_add_expr_to_block (&block, tmp);
2970 return gfc_finish_block (&block);
2974 /* CYCLE a DO loop. The label decl has already been created by
2975 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
2976 node at the head of the loop. We must mark the label as used. */
2979 gfc_trans_cycle (gfc_code * code)
2983 cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
2984 TREE_USED (cycle_label) = 1;
2985 return build1_v (GOTO_EXPR, cycle_label);
2989 /* EXIT a DO loop. Similair to CYCLE, but now the label is in
2990 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
2994 gfc_trans_exit (gfc_code * code)
2998 exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
2999 TREE_USED (exit_label) = 1;
3000 return build1_v (GOTO_EXPR, exit_label);
3004 /* Translate the ALLOCATE statement. */
3007 gfc_trans_allocate (gfc_code * code)
3020 if (!code->ext.alloc_list)
3023 gfc_start_block (&block);
3027 stat = gfc_create_var (gfc_int4_type_node, "stat");
3028 pstat = gfc_build_addr_expr (NULL, stat);
3030 error_label = gfc_build_label_decl (NULL_TREE);
3031 TREE_USED (error_label) = 1;
3035 pstat = integer_zero_node;
3036 stat = error_label = NULL_TREE;
3040 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3044 gfc_init_se (&se, NULL);
3045 gfc_start_block (&se.pre);
3047 se.want_pointer = 1;
3048 se.descriptor_only = 1;
3049 gfc_conv_expr (&se, expr);
3053 /* Find the last reference in the chain. */
3054 while (ref && ref->next != NULL)
3056 assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3060 if (ref != NULL && ref->type == REF_ARRAY)
3063 gfc_array_allocate (&se, ref, pstat);
3067 /* A scalar or derived type. */
3070 val = gfc_create_var (ppvoid_type_node, "ptr");
3071 tmp = gfc_build_addr_expr (ppvoid_type_node, se.expr);
3072 gfc_add_modify_expr (&se.pre, val, tmp);
3074 tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
3075 parm = gfc_chainon_list (NULL_TREE, val);
3076 parm = gfc_chainon_list (parm, tmp);
3077 parm = gfc_chainon_list (parm, pstat);
3078 tmp = gfc_build_function_call (gfor_fndecl_allocate, parm);
3079 gfc_add_expr_to_block (&se.pre, tmp);
3083 tmp = build1_v (GOTO_EXPR, error_label);
3085 build (NE_EXPR, boolean_type_node, stat, integer_zero_node);
3086 tmp = build_v (COND_EXPR, parm, tmp, build_empty_stmt ());
3087 gfc_add_expr_to_block (&se.pre, tmp);
3091 tmp = gfc_finish_block (&se.pre);
3092 gfc_add_expr_to_block (&block, tmp);
3095 /* Assign the value to the status variable. */
3098 tmp = build1_v (LABEL_EXPR, error_label);
3099 gfc_add_expr_to_block (&block, tmp);
3101 gfc_init_se (&se, NULL);
3102 gfc_conv_expr_lhs (&se, code->expr);
3103 tmp = convert (TREE_TYPE (se.expr), stat);
3104 gfc_add_modify_expr (&block, se.expr, tmp);
3107 return gfc_finish_block (&block);
3112 gfc_trans_deallocate (gfc_code * code)
3122 gfc_start_block (&block);
3124 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3127 assert (expr->expr_type == EXPR_VARIABLE);
3129 gfc_init_se (&se, NULL);
3130 gfc_start_block (&se.pre);
3132 se.want_pointer = 1;
3133 se.descriptor_only = 1;
3134 gfc_conv_expr (&se, expr);
3136 if (expr->symtree->n.sym->attr.dimension)
3138 tmp = gfc_array_deallocate (se.expr);
3139 gfc_add_expr_to_block (&se.pre, tmp);
3143 type = build_pointer_type (TREE_TYPE (se.expr));
3144 var = gfc_create_var (type, "ptr");
3145 tmp = gfc_build_addr_expr (type, se.expr);
3146 gfc_add_modify_expr (&se.pre, var, tmp);
3148 tmp = gfc_chainon_list (NULL_TREE, var);
3149 tmp = gfc_chainon_list (tmp, integer_zero_node);
3150 tmp = gfc_build_function_call (gfor_fndecl_deallocate, tmp);
3151 gfc_add_expr_to_block (&se.pre, tmp);
3153 tmp = gfc_finish_block (&se.pre);
3154 gfc_add_expr_to_block (&block, tmp);
3157 return gfc_finish_block (&block);