1 /* Implement looping actions for CHILL.
2 Copyright (C) 1992, 1993, 1994, 1998, 1999, 2000
3 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
35 /* if the user codes '-flocal-loop-counter' on the command line,
36 ch-actions.c (lang_decode_option) will set this flag. */
37 int flag_local_loop_counter = 1;
39 /* forward declarations */
40 static int declare_temps PARAMS ((void));
41 static int initialize_iter_var PARAMS ((void));
42 static void maybe_skip_loop PARAMS ((void));
43 static int bottom_loop_end_check PARAMS ((void));
44 static int increment_temps PARAMS ((void));
45 static tree build_temporary_variable PARAMS ((const char *, tree));
46 static tree maybe_make_for_temp PARAMS ((tree, const char *, tree));
48 static tree chill_unsigned_type PARAMS ((tree));
51 /* In terms of the parameters passed to build_loop_iterator,
52 * there are several types of loops. They are encoded by
53 * the ITER_TYPE enumeration.
55 * 1) DO FOR EVER; ... OD
56 * indicated by a NULL_TREE start_exp, step_exp and end_exp,
57 * condition == NULL, in_flag = 0, and ever_flag == 1 in the
60 * 2) DO WHILE cond; ... OD
61 * indicated by NULL_TREE start_exp, step_exp and end_exp,
62 * in_flag = 0, and condition != NULL.
65 * indicated by NULL_TREEs in start_exp, step_exp and end_exp,
66 * condition != NULL, in_flag == 0 and ever_flag == 0. This
67 * is not really a loop, but a compound statement.
69 * 4) DO FOR user_var := start_exp
70 * [DOWN] TO end_exp BY step_exp; ... DO
71 * indicated by non-NULL_TREE start_exp, step_exp and end_exp.
73 * 5) DO FOR user_var [DOWN] IN discrete_mode; ... OD
74 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
75 * discrete mode, with an optional down_flag.
77 * 6) DO FOR user_var [DOWN] IN powerset_expr; ... OD
78 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
79 * powerset mode, with an optional down_flag.
81 * 7) DO FOR user_var [DOWN] IN location; ... OD
82 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
83 * location mode, with an optional down_flag.
96 typedef struct iterator
98 /* These variables only have meaning in the first ITERATOR structure. */
99 ITER_TYPE itype; /* type of this iterator */
100 int error_flag; /* TRUE if no loop was started due to
102 int down_flag; /* TRUE if DOWN was coded */
104 /* These variables have meaning in every ITERATOR structure. */
105 tree user_var; /* user's explicit iteration variable */
106 tree start_exp; /* user's start expression
107 or IN expression of a FOR .. IN*/
108 tree step_exp; /* user's step expression */
109 tree end_exp; /* user's end expression */
110 tree start_temp; /* temp holding evaluated start_exp */
111 tree end_temp; /* temp holding evaluated end_exp */
112 tree step_temp; /* temp holding evaluated step_exp */
113 tree powerset_temp; /* temp holding user's initial powerset expression */
114 tree loc_ptr_temp; /* temp holding count for LOC enumeration ptr */
115 tree iter_var; /* hidden variable for the loop */
116 tree iter_type; /* hidden variable's type */
117 tree stepin_type; /* saved type for a DO FOR IN loop */
118 tree base_type; /* LOC enumeration base type */
119 struct iterator *next; /* ptr to next iterator for this loop */
123 * There's an entry like this for each nested DO loop.
124 * The list is maintained by push_loop_block
125 * and pop_loop_block.
127 typedef struct loop {
128 struct loop *nxt_level; /* pointer to enclosing loop */
129 ITERATOR *iter_list; /* iterators for the current loop */
132 static LOOP *loopstack = (LOOP *)0;
136 Here is a CHILL DO FOR statement:
138 DO FOR user_var := start_exp BY step_exp [DOWN] TO end_exp
141 For this loop to be 'safe', like a Pascal FOR loop, the start,
142 end, and increment expressions are computed once, before the
143 assignment to the iteration variable and saved in temporaries,
144 before the first assignment of the iteration variable, so the
147 FOR i := (i+1) TO (i+10) DO
149 To prevent changes to the start/end/step expressions from
150 effecting the loop's termination, and to make the loop end-check
151 as simple as possible, we evaluate the step expression into
152 a temporary and compute a hidden iteration count before entering
153 the loop's body. User code cannot effect the counter, and the
154 end-loop check simply decrements the counter and checks for zero.
156 The whole phrase FOR iter := ... TO end_exp can be repeated
157 multiple times, with different user-iteration variables. This
160 The loop counter calculations need careful design since a loop
161 from MININT TO MAXINT must work, in the precision of integers.
163 Here's how it works, in C:
165 0) The DO ... OD loop is simply a block with
168 1) The DO FOR EVER is simply implemented:
177 2) The DO WHILE is also simple:
181 if (!condition) goto end_loop
189 3) The DO FOR [while condition] loop (no DOWN)
195 start_temp = start_exp
197 if (end_exp < start_exp) goto end_loop
198 // following line is all unsigned arithmetic
199 iter_var = (end_exp - start_exp) / step_exp
200 user_var = start_temp
202 if (!condition) goto end_loop
206 if (iter_var == 0) goto end_loop
208 user_var += step_temp
213 4) The for [while condition] loop (with DOWN)
218 start_temp = start_exp
220 if (end_exp > start_exp) goto end_loop
221 // following line is all unsigned arithmetic
222 iter_var = (start_exp - end_exp) / step_exp
223 user_var = start_temp
225 if (!condition) goto end_loop
229 if (iter_var == 0) goto end_loop
231 user_var -= step_temp
237 5) The range loop, which iterates over a mode's possible
238 values, works just like the above step loops, but with
239 the start and end values taken from the mode's lower
240 and upper domain values.
243 6) The FOR IN loop, where a location enumeration is
244 specified (see spec on page 81 of Z.200, bottom
248 decl iter_var as an unsigned integer
249 loc_ptr_temp as pointer to a composite base type
252 iter_var = array's length field
254 iter_var = sizeof array / sizeof base_type
255 loc_ptr_temp = &of highest or lowest indexable entry
257 if (!condition) goto end_loop
262 if (iter_var == 0) goto end_loop
263 loc_ptr_temp +/-= sizeof array base_type
268 7) The DO FOR (DOWN) IN powerset_exp
271 decl iterator as basetype of powerset
273 powerset_temp := save_expr (start_exp)
274 iter_var := DOWN ? length : 0
277 iter_var := __ffsetclrpowerset (powerset_temp, length,
280 iter_var := __ffsetclrpowerset (powrset_temp, iter_var, 0);
281 if (iter_var < 0) goto end_loop;
282 user_var = iter_var + min_value;
283 if (!condition) goto end_loop
284 if (!DOWN) iter_var +:= 1;
293 So, here's the general DO FOR schema, as implemented here:
295 expand_start_loop -- start the loop's control scope
296 -- start scope for synthesized loop variables
297 declare_temps -- create, initialize temporary variables
298 maybe_skip_loop -- skip loop if end conditions unsatisfiable
299 initialize_iter_var -- initialize the iteration counter
300 -- initialize user's loop variable
301 expand_start_loop -- generate top-of-loop label
302 top_loop_end_check -- generate while code and/or
303 powerset find-a-bit function call
306 . user's loop body code
309 bottom_loop_end_check -- exit if counter has become zero
310 increment_temps -- update temps for next iteration
311 expand_end_loop -- generate jump back to top of loop
312 expand_end_cond -- generate label for end of conditional
313 -- end of scope for synthesized loop variables
314 free_iterators -- free up iterator space
316 When there are two or more iterator phrases, each of the
317 above loop steps must act upon all iterators. For example,
318 the 'increment_temps' step must increment all temporaries
319 (associated with all iterators).
321 NOTE: Z.200, section 10.1 says that a block is ...
322 "the actions statement list in a do action, including any
323 loop counter and while control". This means that an exp-
324 ression in a WHILE control can include references to the
325 loop counters created for the loop's exclusive use.
330 DO FOR j IN a WHILE j > 0;
333 The 'j' referenced in the while is the loc-identity 'j'
334 created inside the loop's scope, and NOT the 'j' declared
339 * The following routines are called directly by the
345 LOOP *temp = (LOOP *)xmalloc (sizeof (LOOP));
347 /* push a new loop onto the stack */
348 temp->nxt_level = loopstack;
349 temp->iter_list = (ITERATOR *)0;
356 LOOP *do_temp = loopstack;
359 /* pop loop block off the list */
360 loopstack = do_temp->nxt_level;
362 /* free the loop's iterator blocks */
363 ip = do_temp->iter_list;
366 ITERATOR *temp = ip->next;
384 expand_start_bindings (0);
393 end_loop_scope (opt_label)
397 possibly_define_exit_label (opt_label);
401 expand_end_bindings (getdecls (), kept_level_p (), 0);
404 poplevel (kept_level_p (), 1, 0);
408 /* we need the above 2 functions somehow modified for initialising
409 of non-value arrays */
412 nonvalue_begin_loop_scope ()
414 pushlevel (0); /* this happens only in pass 2 */
420 expand_start_bindings (0);
424 nonvalue_end_loop_scope ()
426 expand_end_bindings (getdecls (), kept_level_p (), 0);
428 poplevel (kept_level_p (), 1, 0);
431 /* The iterator structure records all aspects of a
432 * 'FOR i := start [DOWN] TO end' clause or
433 * 'FOR i IN modename' or 'FOR i IN powerset' clause.
434 * It's saved on the iter_list of the current LOOP.
437 build_loop_iterator (user_var, start_exp, step_exp, end_exp,
438 down_flag, in_flag, ever_flag)
439 tree user_var, start_exp, step_exp, end_exp;
440 int down_flag, in_flag, ever_flag;
442 ITERATOR *ip = (ITERATOR *)xmalloc (sizeof (ITERATOR));
444 /* chain this iterator onto the current loop */
445 if (loopstack->iter_list == NULL)
446 loopstack->iter_list = ip;
449 ITERATOR *temp = loopstack->iter_list;
450 while (temp->next != NULL)
455 ip->user_var = user_var;
456 ip->start_exp = start_exp;
457 ip->step_exp = step_exp;
458 ip->end_exp = end_exp;
459 ip->start_temp = NULL_TREE;
460 ip->end_temp = NULL_TREE;
461 ip->step_temp = NULL_TREE;
462 ip->down_flag = down_flag;
463 ip->powerset_temp = NULL_TREE;
464 ip->iter_var = NULL_TREE;
465 ip->iter_type = NULL_TREE;
466 ip->stepin_type = NULL_TREE;
467 ip->loc_ptr_temp = NULL_TREE;
468 ip->error_flag = 1; /* assume error will be found */
469 ip->next = (ITERATOR *)0;
472 ip->itype = DO_FOREVER;
473 else if (in_flag && start_exp != NULL_TREE)
475 if (TREE_CODE (start_exp) == ERROR_MARK)
477 if (TREE_TYPE (start_exp) == NULL_TREE)
479 if (TREE_CODE (start_exp) == CONSTRUCTOR)
480 error ("modeless tuple not allowed in this context");
482 error ("IN expression does not have a mode");
485 if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE)
487 if (CH_BOOLS_TYPE_P (TREE_TYPE (start_exp)))
489 sorry ("location enumeration for BOOLS");
492 ip->itype = DO_POWERSET;
494 else if (discrete_type_p (TREE_TYPE (ip->start_exp)))
496 /* range enumeration */
497 tree type = TREE_TYPE (ip->start_exp);
498 /* save the original type for later use in determine to do a
500 ip->stepin_type = type;
504 ip->start_exp = build_chill_upper (type);
505 ip->end_exp = build_chill_lower (type);
509 ip->start_exp = build_chill_lower (type);
510 ip->end_exp = build_chill_upper (type);
513 else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE)
515 if (TYPE_PACKED (TREE_TYPE (ip->start_exp)))
517 sorry ("location enumeration for bit-packed arrays");
522 else if (chill_varying_type_p (TREE_TYPE (ip->start_exp)))
523 ip->itype = DO_LOC_VARYING;
526 error ("loop's IN expression is not a composite object");
532 if (ip->itype == DO_STEP)
534 struct ch_class class;
536 if (ip->step_exp == NULL_TREE)
537 ip->step_exp = integer_one_node;
539 if (! discrete_type_p (TREE_TYPE (ip->start_exp)))
541 error ("start expr must have discrete mode");
544 if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ENUMERAL_TYPE
545 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->start_exp)))
547 error ("DO FOR start expression is a numbered SET");
550 if (TREE_CODE (ip->end_exp) == ERROR_MARK)
552 if (TREE_CODE (TREE_TYPE (ip->end_exp)) == ENUMERAL_TYPE
553 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->end_exp)))
555 error ("TO expression is a numbered SET");
558 if (! discrete_type_p (TREE_TYPE (ip->end_exp)))
560 error ("TO expr must have discrete mode");
563 if (! CH_COMPATIBLE_CLASSES (ip->start_exp, ip->end_exp))
565 error ("start expr and TO expr must be compatible");
568 if (step_exp != NULL_TREE)
570 if (TREE_CODE (step_exp) == ERROR_MARK)
572 if (! discrete_type_p (TREE_TYPE (step_exp)))
574 error ("BY expr must have discrete mode");
577 if (! CH_COMPATIBLE_CLASSES (ip->start_exp, step_exp))
579 error ("start expr and BY expr must be compatible");
584 if (! flag_local_loop_counter)
586 /* In this case, it's a previously-declared VAR_DECL node. */
587 tree id_node = ip->user_var;
588 if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
589 ip->user_var = lookup_name (ip->user_var);
591 /* Chill 1984 allows the name to be a defining occurrence,
592 but does not require it. */
593 if (ip->user_var == NULL_TREE)
595 warning ("loop identifier undeclared");
596 ip->user_var = id_node;
597 /* We declare a local name below. */
601 if (TREE_CODE (TREE_TYPE (ip->user_var)) == REFERENCE_TYPE)
602 ip->user_var = convert_from_reference (ip->user_var);
604 if (! CH_COMPATIBLE_CLASSES (ip->start_exp, ip->user_var))
606 error ("loop variable incompatible with start expression");
609 class = chill_expr_class (ip->user_var);
612 /* Otherwise, declare a new name. */
613 if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
615 class = CH_RESULTING_CLASS (chill_expr_class (ip->start_exp),
616 chill_expr_class (ip->end_exp));
618 class = CH_RESULTING_CLASS (class, chill_expr_class (step_exp));
620 /* Integer literals noramally have type 'long long'
621 (see convert_integer in lex.c). That is usually overkill. */
622 if (class.kind == CH_DERIVED_CLASS
623 && class.mode == long_long_integer_type_node
624 && int_fits_type_p (ip->start_exp, integer_type_node)
625 && int_fits_type_p (ip->end_exp, integer_type_node))
626 class.mode = integer_type_node;
629 if (TREE_CODE (ip->start_exp) == INTEGER_CST
630 && TREE_CODE (ip->end_exp) == INTEGER_CST
631 && compare_int_csts (ip->down_flag ? LT_EXPR : GT_EXPR,
632 ip->start_exp, ip->end_exp))
633 warning ("body of DO FOR will never execute");
635 ip->start_exp = convert_to_class (class, ip->start_exp);
636 ip->end_exp = convert_to_class (class, ip->end_exp);
637 ip->step_exp = convert_to_class (class, ip->step_exp);
639 if (TREE_CODE (ip->step_exp) != INTEGER_CST)
641 /* generate runtime check for negative BY expr */
643 check_range (ip->step_exp, ip->step_exp,
644 integer_zero_node, NULL_TREE);
646 else if (compare_int_csts (LE_EXPR, ip->step_exp, integer_zero_node))
648 error ("BY expression is negative or zero");
653 ip->error_flag = 0; /* no errors! */
657 build_loop_start (start_label)
660 ITERATOR *firstp = loopstack->iter_list;
662 if (firstp->error_flag)
667 if (initialize_iter_var ())
670 /* use the label as an 'exit' label,
671 'goto' needs another sort of label */
672 expand_start_loop (start_label != NULL_TREE);
676 * Called after the last action of the loop body
682 ITERATOR *ip = loopstack->iter_list;
684 emit_line_note (input_filename, lineno);
689 if (bottom_loop_end_check ())
692 if (increment_temps ())
697 for (; ip != NULL; ip = ip->next)
712 * Reserve space for any loop-control temporaries, initialize them
717 ITERATOR *firstp = loopstack->iter_list, *ip;
720 for (ip = firstp; ip != NULL; ip = ip->next)
728 = type_for_size (TYPE_PRECISION (TREE_TYPE (ip->start_exp)), 1);
730 /* create, initialize temporaries if expressions aren't constant */
731 ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start",
732 TREE_TYPE (ip->start_exp));
733 ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end",
734 TREE_TYPE (ip->end_exp));
735 /* this is just the step-expression */
736 ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step",
737 TREE_TYPE (ip->step_exp));
738 if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
740 /* (re-)declare the user's iteration variable in the
742 tree id_node = ip->user_var;
744 decl_temp1 (id_node, TREE_TYPE (ip->start_exp), 0, NULL_TREE,
746 CH_DERIVED_FLAG (ip->user_var) = CH_DERIVED_FLAG (ip->start_exp);
747 pushdecl (ip->user_var);
750 decl_temp1 (get_unique_identifier ("iter_var"),
751 ip->iter_type, 0, NULL_TREE, 0, 0);
755 /* the user's powerset-expression */
756 ip->powerset_temp = save_expr (ip->start_exp);
757 mark_addressable (ip->powerset_temp);
759 ip->iter_type = integer_type_node;
760 ip->iter_var = decl_temp1 (get_unique_identifier ("iter_var"),
762 !ip->down_flag ? integer_zero_node
763 : powersetlen (ip->powerset_temp),
766 if (flag_local_loop_counter)
768 /* declare the user's iteration variable in the loop's scope. */
769 /* in this case, it's just an IDENTIFIER_NODE */
771 decl_temp1 (ip->user_var,
772 TYPE_DOMAIN (TREE_TYPE (ip->start_exp)),
774 pushdecl (ip->user_var);
778 /* in this case, it's a previously-declared VAR_DECL node */
779 ip->user_var = lookup_name (ip->user_var);
785 ip->iter_type = chill_unsigned_type_node;
786 /* create the counter temp */
788 build_temporary_variable ("iter_var", ip->iter_type);
790 if (!CH_LOCATION_P (ip->start_exp))
792 = decl_temp1 (get_unique_identifier ("iter_loc"),
793 TREE_TYPE (ip->start_exp), 0,
794 ip->start_exp, 0, 0);
796 if (ip->itype == DO_LOC)
798 tree array_type = TREE_TYPE (ip->start_exp);
802 /* FIXME: check for array type in ip->start_exp */
804 /* create pointer temporary */
805 ip->base_type = TREE_TYPE (array_type);
806 ptr_type = build_pointer_type (ip->base_type);
808 build_temporary_variable ("loc_ptr_tmp", ptr_type);
810 /* declare the user's iteration variable in
811 the loop's scope, as an expression, to be
812 passed to build_component_ref later */
813 save_expr_under_name (ip->user_var,
814 build1 (INDIRECT_REF, ip->base_type,
817 /* FIXME: see stor_layout */
818 ip->step_temp = size_in_bytes (ip->base_type);
820 temp = TYPE_DOMAIN (array_type);
822 /* pointer to first array entry to look at */
823 start_ptr = build1 (ADDR_EXPR, ptr_type, ip->start_exp);
824 mark_addressable (ip->start_exp);
825 ip->start_temp = ip->down_flag ?
826 fold (build (PLUS_EXPR, ptr_type,
828 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
829 fold (build (MINUS_EXPR, integer_type_node,
830 TYPE_MAX_VALUE (temp),
831 TYPE_MIN_VALUE (temp)))))))
837 convert (integer_type_node,
838 build_component_ref (ip->start_exp, var_length_id));
839 tree array_type = TREE_TYPE (TREE_CHAIN (
840 TYPE_FIELDS (TREE_TYPE (ip->start_exp))));
841 tree array_data_ptr =
842 build_component_ref (ip->start_exp, var_data_id);
845 if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
847 error ("can't iterate through array of BOOL");
848 firstp->error_flag = 1;
849 return firstp->error_flag;
852 /* create pointer temporary */
853 ip->base_type = TREE_TYPE (array_type);
854 ptr_type = build_pointer_type (ip->base_type);
856 build_temporary_variable ("loc_ptr_temp", ptr_type);
859 /* declare the user's iteration variable in
860 the loop's scope, as an expression, to be
861 passed to build_component_ref later */
862 save_expr_under_name (ip->user_var,
863 build1 (INDIRECT_REF, ip->base_type,
866 /* FIXME: see stor_layout */
867 ip->step_temp = size_in_bytes (ip->base_type);
869 /* pointer to first array entry to look at */
870 start_ptr = build1 (ADDR_EXPR, ptr_type, array_data_ptr);
871 mark_addressable (array_data_ptr);
872 ip->start_temp = ip->down_flag ?
873 fold (build (PLUS_EXPR, ptr_type,
875 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
876 fold (build (MINUS_EXPR, integer_type_node,
878 integer_one_node))))))
885 return firstp->error_flag;
889 * Initialize the hidden iteration-control variables,
890 * and the user's explicit loop variable.
893 initialize_iter_var ()
895 ITERATOR *firstp = loopstack->iter_list, *ip;
897 for (ip = firstp; ip != NULL; ip = ip->next)
901 tree array_type, array_length;
907 count = build (MINUS_EXPR, ip->iter_type,
908 convert (ip->iter_type,
909 ip->down_flag ? ip->start_temp : ip->end_temp),
910 convert (ip->iter_type,
911 ip->down_flag ? ip->end_temp : ip->start_temp));
912 count = fold (build (TRUNC_DIV_EXPR, ip->iter_type,
915 /* The count in this case is actually one less than the
916 number of iterations, to avoid overflow problems
917 if we iterate *all* the values of iter_type. */
918 /* initialize the loop's hidden counter variable */
920 build_chill_modify_expr (ip->iter_var, count));
922 /* initialize user's variable */
924 build_chill_modify_expr (ip->user_var, ip->start_temp));
930 array_type = TREE_TYPE (ip->start_exp);
931 array_length = fold (build (TRUNC_DIV_EXPR, integer_type_node,
932 size_in_bytes (array_type),
933 size_in_bytes (TREE_TYPE (array_type))));
938 = convert (integer_type_node,
939 build_component_ref (ip->start_exp, var_length_id));
942 expand_expr_stmt (build_chill_modify_expr (ip->iter_var,
945 build_chill_modify_expr (ip->loc_ptr_temp,
953 return firstp->error_flag;
956 /* Generate code to skip the whole loop, if start expression not
957 * <= end expression (or >= for DOWN loops). This comparison must
958 * *NOT* be done in unsigned mode, or it will fail.
959 * Also, skip processing an empty VARYING array.
964 ITERATOR *firstp = loopstack->iter_list, *ip;
966 for (ip = firstp; ip != NULL; ip = ip->next)
972 build_compare_discrete_expr (ip->down_flag ? GE_EXPR : LE_EXPR,
973 ip->start_temp, ip->end_temp), 0);
977 { tree array_length =
978 convert (integer_type_node,
979 build_component_ref (ip->start_exp, var_length_id));
981 build (NE_EXPR, TREE_TYPE (array_length),
982 array_length, integer_zero_node), 0);
992 * Check at the top of the loop for a termination
995 top_loop_end_check (condition)
1000 for (ip = loopstack->iter_list; ip != NULL; ip = ip->next)
1010 const char *func_name;
1011 tree user_type = TREE_TYPE (ip->user_var);
1014 func_name = "__flsetclrpowerset";
1016 func_name = "__ffsetclrpowerset";
1018 temp1 = lookup_name (get_identifier (func_name));
1020 temp1 = build_chill_function_call (temp1,
1021 tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp),
1022 tree_cons (NULL_TREE, ip->iter_var,
1023 tree_cons (NULL_TREE, integer_zero_node, NULL_TREE))));
1025 temp1 = build_chill_function_call (temp1,
1026 tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp),
1027 tree_cons (NULL_TREE, powersetlen (ip->powerset_temp),
1028 tree_cons (NULL_TREE, ip->iter_var, NULL_TREE))));
1029 expand_assignment (ip->iter_var, temp1, 0, 0);
1030 expand_exit_loop_if_false (0, build (GE_EXPR, boolean_type_node,
1032 integer_zero_node));
1033 temp1 = TYPE_MIN_VALUE
1034 (TYPE_DOMAIN (TREE_TYPE (ip->powerset_temp)));
1035 expand_assignment (ip->user_var,
1036 build (PLUS_EXPR, user_type,
1037 convert (user_type, ip->iter_var),
1038 convert (user_type, temp1)),
1043 case DO_LOC_VARYING:
1049 emit_line_note (input_filename, lineno);
1051 /* now, exit the loop if the condition isn't TRUE. */
1053 expand_exit_loop_if_false (0, truthvalue_conversion (condition));
1057 * Check generated temporaries for loop's end
1060 bottom_loop_end_check ()
1062 ITERATOR *firstp = loopstack->iter_list, *ip;
1064 emit_line_note (input_filename, lineno);
1066 /* now, generate code to check each loop counter for termination */
1067 for (ip = firstp; ip != NULL; ip = ip->next)
1074 /* exit if it's zero */
1075 expand_exit_loop_if_false (0,
1076 build (NE_EXPR, boolean_type_node,
1078 integer_zero_node));
1079 /* decrement iteration counter by one */
1080 chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
1083 case DO_LOC_VARYING:
1084 /* decrement iteration counter by one */
1085 chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
1086 /* exit if it's zero */
1087 expand_exit_loop_if_false (0,
1088 build (NE_EXPR, boolean_type_node,
1090 integer_zero_node));
1099 return firstp->error_flag;
1103 * increment the loop-control variables.
1108 ITERATOR *firstp = loopstack->iter_list, *ip;
1110 for (ip = firstp; ip != NULL; ip = ip->next)
1119 fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1120 TREE_TYPE (ip->user_var), ip->user_var,
1123 build_chill_modify_expr (ip->user_var, delta));
1127 case DO_LOC_VARYING:
1128 /* This statement uses the C semantics, so that
1129 the pointer is actually incremented by the
1130 length of the object pointed to. */
1132 enum tree_code op = ip->down_flag ? MINUS_EXPR : PLUS_EXPR;
1133 tree el_type = TREE_TYPE (TREE_TYPE (ip->loc_ptr_temp));
1134 chill_expand_assignment (ip->loc_ptr_temp, NOP_EXPR,
1136 TREE_TYPE (ip->loc_ptr_temp),
1138 size_in_bytes (el_type)));
1143 expand_assignment (ip->iter_var,
1144 build (PLUS_EXPR, ip->iter_type,
1153 return firstp->error_flag;
1157 * Generate a (temporary) unique identifier_node of
1158 * the form "__tmp_%s_%d"
1161 get_unique_identifier (lead)
1165 static int idcount = 0;
1167 sprintf (idbuf, "__tmp_%s_%d", lead ? lead : "", idcount++);
1168 return get_identifier (idbuf);
1172 * build a temporary variable, given its NAME and TYPE.
1173 * The name will have a number appended to assure uniqueness.
1174 * return its DECL node.
1177 build_temporary_variable (name, type)
1181 return decl_temp1 (get_unique_identifier (name), type, 0, NULL_TREE, 0, 0);
1186 * If the given expression isn't a constant, build a temp for it
1187 * and evaluate the expression into the temp. Return the tree
1188 * representing either the original constant expression or the
1189 * temp which now contains the expression's value.
1192 maybe_make_for_temp (exp, temp_name, exp_type)
1194 const char *temp_name;
1199 if (exp != NULL_TREE)
1201 /* if exp isn't constant, create a temporary for its value */
1202 if (TREE_CONSTANT (exp))
1204 /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */
1205 result = convert (exp_type, exp);
1208 /* build temp, assign the value */
1209 result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0,
1218 * Adapt the C unsigned_type function to CHILL - we need to
1219 * account for any CHILL-specific integer types here. So far,
1220 * the 16-bit integer type is the only one.
1223 chill_unsigned_type (type)
1226 extern tree chill_unsigned_type_node;
1227 tree type1 = TYPE_MAIN_VARIANT (type);
1229 if (type1 == chill_integer_type_node)
1230 return chill_unsigned_type_node;
1232 return unsigned_type (type);