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
);