1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003, 2004 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 GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
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
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
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 gfc_saved_var *saved_vars;
2125 iter_info *this_forall, *iter_tmp;
2126 forall_info *info, *forall_tmp;
2127 temporary_list *temp;
2129 gfc_start_block (&block);
2132 /* Count the FORALL index number. */
2133 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2137 /* Allocate the space for var, start, end, step, varexpr. */
2138 var = (tree *) gfc_getmem (nvar * sizeof (tree));
2139 start = (tree *) gfc_getmem (nvar * sizeof (tree));
2140 end = (tree *) gfc_getmem (nvar * sizeof (tree));
2141 step = (tree *) gfc_getmem (nvar * sizeof (tree));
2142 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
2143 saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
2145 /* Allocate the space for info. */
2146 info = (forall_info *) gfc_getmem (sizeof (forall_info));
2148 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2150 gfc_symbol *sym = fa->var->symtree->n.sym;
2152 /* allocate space for this_forall. */
2153 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2155 /* Create a temporary variable for the FORALL index. */
2156 tmp = gfc_typenode_for_spec (&sym->ts);
2157 var[n] = gfc_create_var (tmp, sym->name);
2158 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
2160 /* Record it in this_forall. */
2161 this_forall->var = var[n];
2163 /* Replace the index symbol's backend_decl with the temporary decl. */
2164 sym->backend_decl = var[n];
2166 /* Work out the start, end and stride for the loop. */
2167 gfc_init_se (&se, NULL);
2168 gfc_conv_expr_val (&se, fa->start);
2169 /* Record it in this_forall. */
2170 this_forall->start = se.expr;
2171 gfc_add_block_to_block (&block, &se.pre);
2174 gfc_init_se (&se, NULL);
2175 gfc_conv_expr_val (&se, fa->end);
2176 /* Record it in this_forall. */
2177 this_forall->end = se.expr;
2178 gfc_make_safe_expr (&se);
2179 gfc_add_block_to_block (&block, &se.pre);
2182 gfc_init_se (&se, NULL);
2183 gfc_conv_expr_val (&se, fa->stride);
2184 /* Record it in this_forall. */
2185 this_forall->step = se.expr;
2186 gfc_make_safe_expr (&se);
2187 gfc_add_block_to_block (&block, &se.pre);
2190 /* Set the NEXT field of this_forall to NULL. */
2191 this_forall->next = NULL;
2192 /* Link this_forall to the info construct. */
2193 if (info->this_loop == NULL)
2194 info->this_loop = this_forall;
2197 iter_tmp = info->this_loop;
2198 while (iter_tmp->next != NULL)
2199 iter_tmp = iter_tmp->next;
2200 iter_tmp->next = this_forall;
2207 /* Work out the number of elements in the mask array. */
2210 size = integer_one_node;
2211 sizevar = NULL_TREE;
2213 for (n = 0; n < nvar; n++)
2215 if (lenvar && TREE_TYPE (lenvar) != TREE_TYPE (start[n]))
2218 /* size = (end + step - start) / step. */
2219 tmp = fold (build (MINUS_EXPR, TREE_TYPE (start[n]), step[n], start[n]));
2220 tmp = fold (build (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp));
2222 tmp = fold (build (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]));
2223 tmp = convert (gfc_array_index_type, tmp);
2225 size = fold (build (MULT_EXPR, gfc_array_index_type, size, tmp));
2228 /* Record the nvar and size of current forall level. */
2232 /* Link the current forall level to nested_forall_info. */
2233 forall_tmp = nested_forall_info;
2234 if (forall_tmp == NULL)
2235 nested_forall_info = info;
2238 while (forall_tmp->next_nest != NULL)
2239 forall_tmp = forall_tmp->next_nest;
2240 info->outer = forall_tmp;
2241 forall_tmp->next_nest = info;
2244 /* Copy the mask into a temporary variable if required.
2245 For now we assume a mask temporary is needed. */
2248 /* Allocate the mask temporary. */
2249 bytesize = fold (build (MULT_EXPR, gfc_array_index_type, size,
2250 TYPE_SIZE_UNIT (boolean_type_node)));
2252 mask = gfc_do_allocate (bytesize, size, &pmask, &block, boolean_type_node);
2254 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2255 /* Record them in the info structure. */
2256 info->pmask = pmask;
2258 info->maskindex = maskindex;
2260 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2262 /* Start of mask assignment loop body. */
2263 gfc_start_block (&body);
2265 /* Evaluate the mask expression. */
2266 gfc_init_se (&se, NULL);
2267 gfc_conv_expr_val (&se, code->expr);
2268 gfc_add_block_to_block (&body, &se.pre);
2270 /* Store the mask. */
2271 se.expr = convert (boolean_type_node, se.expr);
2274 tmp = gfc_build_indirect_ref (mask);
2277 tmp = gfc_build_array_ref (tmp, maskindex);
2278 gfc_add_modify_expr (&body, tmp, se.expr);
2280 /* Advance to the next mask element. */
2281 tmp = build (PLUS_EXPR, gfc_array_index_type, maskindex,
2283 gfc_add_modify_expr (&body, maskindex, tmp);
2285 /* Generate the loops. */
2286 tmp = gfc_finish_block (&body);
2287 tmp = gfc_trans_nested_forall_loop (info, tmp, 0, 0);
2288 gfc_add_expr_to_block (&block, tmp);
2292 /* No mask was specified. */
2293 maskindex = NULL_TREE;
2294 mask = pmask = NULL_TREE;
2297 c = code->block->next;
2299 /* TODO: loop merging in FORALL statements. */
2300 /* Now that we've got a copy of the mask, generate the assignment loops. */
2306 /* A scalar or array assingment. */
2307 need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2308 /* Teporaries due to array assignment data dependencies introduce
2309 no end of problems. */
2311 gfc_trans_assign_need_temp (c->expr, c->expr2, NULL,
2312 nested_forall_info, &block);
2315 /* Use the normal assignment copying routines. */
2316 assign = gfc_trans_assignment (c->expr, c->expr2);
2318 /* Reset the mask index. */
2320 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2322 /* Generate body and loops. */
2323 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2324 gfc_add_expr_to_block (&block, tmp);
2331 /* Translate WHERE or WHERE construct nested in FORALL. */
2333 gfc_trans_where_2 (c, NULL, NULL, nested_forall_info, &block, &temp);
2340 /* Free the temporary. */
2341 args = gfc_chainon_list (NULL_TREE, temp->temporary);
2342 tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
2343 gfc_add_expr_to_block (&block, tmp);
2352 /* Pointer assignment inside FORALL. */
2353 case EXEC_POINTER_ASSIGN:
2354 need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2356 gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
2357 nested_forall_info, &block);
2360 /* Use the normal assignment copying routines. */
2361 assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
2363 /* Reset the mask index. */
2365 gfc_add_modify_expr (&block, maskindex, integer_zero_node);
2367 /* Generate body and loops. */
2368 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign,
2370 gfc_add_expr_to_block (&block, tmp);
2375 tmp = gfc_trans_forall_1 (c, nested_forall_info);
2376 gfc_add_expr_to_block (&block, tmp);
2387 /* Restore the original index variables. */
2388 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
2389 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
2391 /* Free the space for var, start, end, step, varexpr. */
2397 gfc_free (saved_vars);
2401 /* Free the temporary for the mask. */
2402 tmp = gfc_chainon_list (NULL_TREE, pmask);
2403 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2404 gfc_add_expr_to_block (&block, tmp);
2407 pushdecl (maskindex);
2409 return gfc_finish_block (&block);
2413 /* Translate the FORALL statement or construct. */
2415 tree gfc_trans_forall (gfc_code * code)
2417 return gfc_trans_forall_1 (code, NULL);
2421 /* Evaluate the WHERE mask expression, copy its value to a temporary.
2422 If the WHERE construct is nested in FORALL, compute the overall temporary
2423 needed by the WHERE mask expression multiplied by the iterator number of
2425 ME is the WHERE mask expression.
2426 MASK is the temporary which value is mask's value.
2427 NMASK is another temporary which value is !mask.
2428 TEMP records the temporary's address allocated in this function in order to
2429 free them outside this function.
2430 MASK, NMASK and TEMP are all OUT arguments. */
2433 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
2434 tree * mask, tree * nmask, temporary_list ** temp,
2435 stmtblock_t * block)
2440 tree ptemp1, ntmp, ptemp2;
2442 stmtblock_t body, body1;
2447 gfc_init_loopinfo (&loop);
2449 /* Calculate the size of temporary needed by the mask-expr. */
2450 inner_size = compute_inner_temp_size (me, me, block, &lss, &rss);
2452 /* Allocate temporary for where mask. */
2453 tmp = allocate_temp_for_forall_nest (nested_forall_info, boolean_type_node,
2454 inner_size, block, &ptemp1);
2455 /* Record the temporary address in order to free it later. */
2458 temporary_list *tempo;
2459 tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2460 tempo->temporary = ptemp1;
2461 tempo->next = *temp;
2465 /* Allocate temporary for !mask. */
2466 ntmp = allocate_temp_for_forall_nest (nested_forall_info, boolean_type_node,
2467 inner_size, block, &ptemp2);
2468 /* Record the temporary in order to free it later. */
2471 temporary_list *tempo;
2472 tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2473 tempo->temporary = ptemp2;
2474 tempo->next = *temp;
2478 /* Variable to index the temporary. */
2479 count = gfc_create_var (gfc_array_index_type, "count");
2480 /* Initilize count. */
2481 gfc_add_modify_expr (block, count, integer_zero_node);
2483 gfc_start_block (&body);
2485 gfc_init_se (&rse, NULL);
2486 gfc_init_se (&lse, NULL);
2488 if (lss == gfc_ss_terminator)
2490 gfc_init_block (&body1);
2494 /* Initiliaze the loop. */
2495 gfc_init_loopinfo (&loop);
2497 /* We may need LSS to determine the shape of the expression. */
2498 gfc_add_ss_to_loop (&loop, lss);
2499 gfc_add_ss_to_loop (&loop, rss);
2501 gfc_conv_ss_startstride (&loop);
2502 gfc_conv_loop_setup (&loop);
2504 gfc_mark_ss_chain_used (rss, 1);
2505 /* Start the loop body. */
2506 gfc_start_scalarized_body (&loop, &body1);
2508 /* Translate the expression. */
2509 gfc_copy_loopinfo_to_se (&rse, &loop);
2511 gfc_conv_expr (&rse, me);
2513 /* Form the expression of the temporary. */
2514 lse.expr = gfc_build_array_ref (tmp, count);
2515 tmpexpr = gfc_build_array_ref (ntmp, count);
2517 /* Use the scalar assignment to fill temporary TMP. */
2518 tmp1 = gfc_trans_scalar_assign (&lse, &rse, me->ts.type);
2519 gfc_add_expr_to_block (&body1, tmp1);
2521 /* Fill temporary NTMP. */
2522 tmp1 = build1 (TRUTH_NOT_EXPR, TREE_TYPE (lse.expr), lse.expr);
2523 gfc_add_modify_expr (&body1, tmpexpr, tmp1);
2525 if (lss == gfc_ss_terminator)
2527 gfc_add_block_to_block (&body, &body1);
2531 /* Increment count. */
2532 tmp1 = fold (build (PLUS_EXPR, gfc_array_index_type, count,
2534 gfc_add_modify_expr (&body1, count, tmp1);
2536 /* Generate the copying loops. */
2537 gfc_trans_scalarizing_loops (&loop, &body1);
2539 gfc_add_block_to_block (&body, &loop.pre);
2540 gfc_add_block_to_block (&body, &loop.post);
2542 gfc_cleanup_loop (&loop);
2543 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
2544 as tree nodes in SS may not be valid in different scope. */
2547 tmp1 = gfc_finish_block (&body);
2548 /* If the WHERE construct is inside FORALL, fill the full temporary. */
2549 if (nested_forall_info != NULL)
2550 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1);
2553 gfc_add_expr_to_block (block, tmp1);
2562 /* Translate an assignment statement in a WHERE statement or construct
2563 statement. The MASK expression is used to control which elements
2564 of EXPR1 shall be assigned. */
2567 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2, tree mask,
2568 tree count1, tree count2)
2573 gfc_ss *lss_section;
2580 tree index, maskexpr, tmp1;
2583 /* TODO: handle this special case.
2584 Special case a single function returning an array. */
2585 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
2587 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
2593 /* Assignment of the form lhs = rhs. */
2594 gfc_start_block (&block);
2596 gfc_init_se (&lse, NULL);
2597 gfc_init_se (&rse, NULL);
2600 lss = gfc_walk_expr (expr1);
2603 /* In each where-assign-stmt, the mask-expr and the variable being
2604 defined shall be arrays of the same shape. */
2605 assert (lss != gfc_ss_terminator);
2607 /* The assignment needs scalarization. */
2610 /* Find a non-scalar SS from the lhs. */
2611 while (lss_section != gfc_ss_terminator
2612 && lss_section->type != GFC_SS_SECTION)
2613 lss_section = lss_section->next;
2615 assert (lss_section != gfc_ss_terminator);
2617 /* Initialize the scalarizer. */
2618 gfc_init_loopinfo (&loop);
2621 rss = gfc_walk_expr (expr2);
2622 if (rss == gfc_ss_terminator)
2624 /* The rhs is scalar. Add a ss for the expression. */
2625 rss = gfc_get_ss ();
2626 rss->next = gfc_ss_terminator;
2627 rss->type = GFC_SS_SCALAR;
2631 /* Associate the SS with the loop. */
2632 gfc_add_ss_to_loop (&loop, lss);
2633 gfc_add_ss_to_loop (&loop, rss);
2635 /* Calculate the bounds of the scalarization. */
2636 gfc_conv_ss_startstride (&loop);
2638 /* Resolve any data dependencies in the statement. */
2639 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
2641 /* Setup the scalarizing loops. */
2642 gfc_conv_loop_setup (&loop);
2644 /* Setup the gfc_se structures. */
2645 gfc_copy_loopinfo_to_se (&lse, &loop);
2646 gfc_copy_loopinfo_to_se (&rse, &loop);
2649 gfc_mark_ss_chain_used (rss, 1);
2650 if (loop.temp_ss == NULL)
2653 gfc_mark_ss_chain_used (lss, 1);
2657 lse.ss = loop.temp_ss;
2658 gfc_mark_ss_chain_used (lss, 3);
2659 gfc_mark_ss_chain_used (loop.temp_ss, 3);
2662 /* Start the scalarized loop body. */
2663 gfc_start_scalarized_body (&loop, &body);
2665 /* Translate the expression. */
2666 gfc_conv_expr (&rse, expr2);
2667 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
2669 gfc_conv_tmp_array_ref (&lse);
2670 gfc_advance_se_ss_chain (&lse);
2673 gfc_conv_expr (&lse, expr1);
2675 /* Form the mask expression according to the mask tree list. */
2679 maskexpr = gfc_build_array_ref (tmp, index);
2683 tmp = TREE_CHAIN (tmp);
2686 tmp1 = gfc_build_array_ref (tmp, index);
2687 maskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1), maskexpr, tmp1);
2688 tmp = TREE_CHAIN (tmp);
2690 /* Use the scalar assignment as is. */
2691 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2692 tmp = build_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2694 gfc_add_expr_to_block (&body, tmp);
2696 if (lss == gfc_ss_terminator)
2698 /* Increment count1. */
2699 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2701 gfc_add_modify_expr (&body, count1, tmp);
2703 /* Use the scalar assignment as is. */
2704 gfc_add_block_to_block (&block, &body);
2708 if (lse.ss != gfc_ss_terminator)
2710 if (rse.ss != gfc_ss_terminator)
2713 if (loop.temp_ss != NULL)
2715 /* Increment count1 before finish the main body of a scalarized
2717 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2719 gfc_add_modify_expr (&body, count1, tmp);
2720 gfc_trans_scalarized_loop_boundary (&loop, &body);
2722 /* We need to copy the temporary to the actual lhs. */
2723 gfc_init_se (&lse, NULL);
2724 gfc_init_se (&rse, NULL);
2725 gfc_copy_loopinfo_to_se (&lse, &loop);
2726 gfc_copy_loopinfo_to_se (&rse, &loop);
2728 rse.ss = loop.temp_ss;
2731 gfc_conv_tmp_array_ref (&rse);
2732 gfc_advance_se_ss_chain (&rse);
2733 gfc_conv_expr (&lse, expr1);
2735 if (lse.ss != gfc_ss_terminator)
2738 if (rse.ss != gfc_ss_terminator)
2741 /* Form the mask expression according to the mask tree list. */
2745 maskexpr = gfc_build_array_ref (tmp, index);
2749 tmp = TREE_CHAIN (tmp);
2752 tmp1 = gfc_build_array_ref (tmp, index);
2753 maskexpr = build (TRUTH_AND_EXPR, TREE_TYPE (tmp1), maskexpr,
2755 tmp = TREE_CHAIN (tmp);
2757 /* Use the scalar assignment as is. */
2758 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2759 tmp = build_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2760 gfc_add_expr_to_block (&body, tmp);
2761 /* Increment count2. */
2762 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count2), count2,
2764 gfc_add_modify_expr (&body, count2, tmp);
2768 /* Increment count1. */
2769 tmp = fold (build (PLUS_EXPR, TREE_TYPE (count1), count1,
2771 gfc_add_modify_expr (&body, count1, tmp);
2774 /* Generate the copying loops. */
2775 gfc_trans_scalarizing_loops (&loop, &body);
2777 /* Wrap the whole thing up. */
2778 gfc_add_block_to_block (&block, &loop.pre);
2779 gfc_add_block_to_block (&block, &loop.post);
2780 gfc_cleanup_loop (&loop);
2783 return gfc_finish_block (&block);
2787 /* Translate the WHERE construct or statement.
2788 This fuction can be called iteratelly to translate the nested WHERE
2789 construct or statement.
2790 MASK is the control mask, and PMASK is the pending control mask.
2791 TEMP records the temporary address which must be freed later. */
2794 gfc_trans_where_2 (gfc_code * code, tree mask, tree pmask,
2795 forall_info * nested_forall_info, stmtblock_t * block,
2796 temporary_list ** temp)
2802 tree tmp, tmp1, tmp2;
2803 tree count1, count2;
2807 /* the WHERE statement or the WHERE construct statement. */
2808 cblock = code->block;
2811 /* Has mask-expr. */
2814 /* Ensure that the WHERE mask be evaluated only once. */
2815 tmp2 = gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
2816 &tmp, &tmp1, temp, block);
2818 /* Set the control mask and the pending control mask. */
2819 /* It's a where-stmt. */
2825 /* It's a nested where-stmt. */
2826 else if (mask && pmask == NULL)
2829 /* Use the TREE_CHAIN to list the masks. */
2830 tmp2 = copy_list (mask);
2831 pmask = chainon (mask, tmp1);
2832 mask = chainon (tmp2, tmp);
2834 /* It's a masked-elsewhere-stmt. */
2835 else if (mask && cblock->expr)
2838 tmp2 = copy_list (pmask);
2841 tmp2 = chainon (tmp2, tmp);
2842 pmask = chainon (mask, tmp1);
2846 /* It's a elsewhere-stmt. No mask-expr is present. */
2850 /* Get the assignment statement of a WHERE statement, or the first
2851 statement in where-body-construct of a WHERE construct. */
2852 cnext = cblock->next;
2857 /* WHERE assignment statement. */
2859 expr1 = cnext->expr;
2860 expr2 = cnext->expr2;
2861 if (nested_forall_info != NULL)
2866 nvar = nested_forall_info->nvar;
2867 varexpr = (gfc_expr **)
2868 gfc_getmem (nvar * sizeof (gfc_expr *));
2869 need_temp = gfc_check_dependency (expr1, expr2, varexpr,
2872 gfc_trans_assign_need_temp (expr1, expr2, mask,
2873 nested_forall_info, block);
2876 /* Variables to control maskexpr. */
2877 count1 = gfc_create_var (gfc_array_index_type, "count1");
2878 count2 = gfc_create_var (gfc_array_index_type, "count2");
2879 gfc_add_modify_expr (block, count1, integer_zero_node);
2880 gfc_add_modify_expr (block, count2, integer_zero_node);
2882 tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
2884 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
2886 gfc_add_expr_to_block (block, tmp);
2891 /* Variables to control maskexpr. */
2892 count1 = gfc_create_var (gfc_array_index_type, "count1");
2893 count2 = gfc_create_var (gfc_array_index_type, "count2");
2894 gfc_add_modify_expr (block, count1, integer_zero_node);
2895 gfc_add_modify_expr (block, count2, integer_zero_node);
2897 tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
2899 gfc_add_expr_to_block (block, tmp);
2904 /* WHERE or WHERE construct is part of a where-body-construct. */
2906 /* Ensure that MASK is not modified by next gfc_trans_where_2. */
2907 mask_copy = copy_list (mask);
2908 gfc_trans_where_2 (cnext, mask_copy, NULL, nested_forall_info,
2916 /* The next statement within the same where-body-construct. */
2917 cnext = cnext->next;
2919 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
2920 cblock = cblock->block;
2925 /* As the WHERE or WHERE construct statement can be nested, we call
2926 gfc_trans_where_2 to do the translation, and pass the initial
2927 NULL values for both the control mask and the pending control mask. */
2930 gfc_trans_where (gfc_code * code)
2933 temporary_list *temp, *p;
2937 gfc_start_block (&block);
2940 gfc_trans_where_2 (code, NULL, NULL, NULL, &block, &temp);
2942 /* Add calls to free temporaries which were dynamically allocated. */
2945 args = gfc_chainon_list (NULL_TREE, temp->temporary);
2946 tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
2947 gfc_add_expr_to_block (&block, tmp);
2953 return gfc_finish_block (&block);
2957 /* CYCLE a DO loop. The label decl has already been created by
2958 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
2959 node at the head of the loop. We must mark the label as used. */
2962 gfc_trans_cycle (gfc_code * code)
2966 cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
2967 TREE_USED (cycle_label) = 1;
2968 return build1_v (GOTO_EXPR, cycle_label);
2972 /* EXIT a DO loop. Similair to CYCLE, but now the label is in
2973 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
2977 gfc_trans_exit (gfc_code * code)
2981 exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
2982 TREE_USED (exit_label) = 1;
2983 return build1_v (GOTO_EXPR, exit_label);
2987 /* Translate the ALLOCATE statement. */
2990 gfc_trans_allocate (gfc_code * code)
3003 if (!code->ext.alloc_list)
3006 gfc_start_block (&block);
3010 stat = gfc_create_var (gfc_int4_type_node, "stat");
3011 pstat = gfc_build_addr_expr (NULL, stat);
3013 error_label = gfc_build_label_decl (NULL_TREE);
3014 TREE_USED (error_label) = 1;
3018 pstat = integer_zero_node;
3019 stat = error_label = NULL_TREE;
3023 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3027 gfc_init_se (&se, NULL);
3028 gfc_start_block (&se.pre);
3030 se.want_pointer = 1;
3031 se.descriptor_only = 1;
3032 gfc_conv_expr (&se, expr);
3036 /* Find the last reference in the chain. */
3037 while (ref && ref->next != NULL)
3039 assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3043 if (ref != NULL && ref->type == REF_ARRAY)
3046 gfc_array_allocate (&se, ref, pstat);
3050 /* A scalar or derived type. */
3053 val = gfc_create_var (ppvoid_type_node, "ptr");
3054 tmp = gfc_build_addr_expr (ppvoid_type_node, se.expr);
3055 gfc_add_modify_expr (&se.pre, val, tmp);
3057 tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
3058 parm = gfc_chainon_list (NULL_TREE, val);
3059 parm = gfc_chainon_list (parm, tmp);
3060 parm = gfc_chainon_list (parm, pstat);
3061 tmp = gfc_build_function_call (gfor_fndecl_allocate, parm);
3062 gfc_add_expr_to_block (&se.pre, tmp);
3066 tmp = build1_v (GOTO_EXPR, error_label);
3068 build (NE_EXPR, boolean_type_node, stat, integer_zero_node);
3069 tmp = build_v (COND_EXPR, parm, tmp, build_empty_stmt ());
3070 gfc_add_expr_to_block (&se.pre, tmp);
3074 tmp = gfc_finish_block (&se.pre);
3075 gfc_add_expr_to_block (&block, tmp);
3078 /* Assign the value to the status variable. */
3081 tmp = build1_v (LABEL_EXPR, error_label);
3082 gfc_add_expr_to_block (&block, tmp);
3084 gfc_init_se (&se, NULL);
3085 gfc_conv_expr_lhs (&se, code->expr);
3086 tmp = convert (TREE_TYPE (se.expr), stat);
3087 gfc_add_modify_expr (&block, se.expr, tmp);
3090 return gfc_finish_block (&block);
3095 gfc_trans_deallocate (gfc_code * code)
3105 gfc_start_block (&block);
3107 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3110 assert (expr->expr_type == EXPR_VARIABLE);
3112 gfc_init_se (&se, NULL);
3113 gfc_start_block (&se.pre);
3115 se.want_pointer = 1;
3116 se.descriptor_only = 1;
3117 gfc_conv_expr (&se, expr);
3119 if (expr->symtree->n.sym->attr.dimension)
3121 tmp = gfc_array_deallocate (se.expr);
3122 gfc_add_expr_to_block (&se.pre, tmp);
3126 type = build_pointer_type (TREE_TYPE (se.expr));
3127 var = gfc_create_var (type, "ptr");
3128 tmp = gfc_build_addr_expr (type, se.expr);
3129 gfc_add_modify_expr (&se.pre, var, tmp);
3131 tmp = gfc_chainon_list (NULL_TREE, var);
3132 tmp = gfc_chainon_list (tmp, integer_zero_node);
3133 tmp = gfc_build_function_call (gfor_fndecl_deallocate, tmp);
3134 gfc_add_expr_to_block (&se.pre, tmp);
3136 tmp = gfc_finish_block (&se.pre);
3137 gfc_add_expr_to_block (&block, tmp);
3140 return gfc_finish_block (&block);