1 /* Implement looping actions for CHILL.
2 Copyright (C) 1992, 93, 1994, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
34 /* if the user codes '-flocal-loop-counter' on the command line,
35 ch-actions.c (lang_decode_option) will set this flag. */
36 int flag_local_loop_counter
= 1;
38 /* forward declarations */
39 static int declare_temps
PROTO((void));
40 static int initialize_iter_var
PROTO((void));
41 static void maybe_skip_loop
PROTO((void));
42 static int bottom_loop_end_check
PROTO((void));
43 static int increment_temps
PROTO((void));
44 static tree build_temporary_variable
PROTO((const char *, tree
));
45 static tree maybe_make_for_temp
PROTO((tree
, const char *, tree
));
47 static tree chill_unsigned_type
PROTO((tree
));
50 /* In terms of the parameters passed to build_loop_iterator,
51 * there are several types of loops. They are encoded by
52 * the ITER_TYPE enumeration.
54 * 1) DO FOR EVER; ... OD
55 * indicated by a NULL_TREE start_exp, step_exp and end_exp,
56 * condition == NULL, in_flag = 0, and ever_flag == 1 in the
59 * 2) DO WHILE cond; ... OD
60 * indicated by NULL_TREE start_exp, step_exp and end_exp,
61 * in_flag = 0, and condition != NULL.
64 * indicated by NULL_TREEs in start_exp, step_exp and end_exp,
65 * condition != NULL, in_flag == 0 and ever_flag == 0. This
66 * is not really a loop, but a compound statement.
68 * 4) DO FOR user_var := start_exp
69 * [DOWN] TO end_exp BY step_exp; ... DO
70 * indicated by non-NULL_TREE start_exp, step_exp and end_exp.
72 * 5) DO FOR user_var [DOWN] IN discrete_mode; ... OD
73 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
74 * discrete mode, with an optional down_flag.
76 * 6) DO FOR user_var [DOWN] IN powerset_expr; ... OD
77 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
78 * powerset mode, with an optional down_flag.
80 * 7) DO FOR user_var [DOWN] IN location; ... OD
81 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
82 * location mode, with an optional down_flag.
95 typedef struct iterator
97 /* These variables only have meaning in the first ITERATOR structure. */
98 ITER_TYPE itype
; /* type of this iterator */
99 int error_flag
; /* TRUE if no loop was started due to
101 int down_flag
; /* TRUE if DOWN was coded */
103 /* These variables have meaning in every ITERATOR structure. */
104 tree user_var
; /* user's explicit iteration variable */
105 tree start_exp
; /* user's start expression
106 or IN expression of a FOR .. IN*/
107 tree step_exp
; /* user's step expression */
108 tree end_exp
; /* user's end expression */
109 tree start_temp
; /* temp holding evaluated start_exp */
110 tree end_temp
; /* temp holding evaluated end_exp */
111 tree step_temp
; /* temp holding evaluated step_exp */
112 tree powerset_temp
; /* temp holding user's initial powerset expression */
113 tree loc_ptr_temp
; /* temp holding count for LOC enumeration ptr */
114 tree iter_var
; /* hidden variable for the loop */
115 tree iter_type
; /* hidden variable's type */
116 tree stepin_type
; /* saved type for a DO FOR IN loop */
117 tree base_type
; /* LOC enumeration base type */
118 struct iterator
*next
; /* ptr to next iterator for this loop */
122 * There's an entry like this for each nested DO loop.
123 * The list is maintained by push_loop_block
124 * and pop_loop_block.
126 typedef struct loop
{
127 struct loop
*nxt_level
; /* pointer to enclosing loop */
128 ITERATOR
*iter_list
; /* iterators for the current loop */
131 static LOOP
*loopstack
= (LOOP
*)0;
135 Here is a CHILL DO FOR statement
:
137 DO FOR user_var
:= start_exp BY step_exp
[DOWN
] TO end_exp
140 For
this loop to be
'safe', like a Pascal FOR loop
, the start
,
141 end
, and increment expressions are computed once
, before the
142 assignment to the iteration variable
and saved in temporaries
,
143 before the first assignment of the iteration variable
, so the
146 FOR i
:= (i
+1) TO (i
+10) DO
148 To prevent changes to the start
/end
/step expressions from
149 effecting the loop
''s termination
, and to make the loop end
-check
150 as simple as possible
, we evaluate the step expression into
151 a temporary
and compute a hidden iteration count before entering
152 the loop
''s body
. User code cannot effect the counter
, and the
153 end
-loop check simply decrements the counter
and checks
for zero
.
155 The whole phrase FOR iter
:= ... TO end_exp can be repeated
156 multiple times
, with different user
-iteration variables
. This
159 The loop counter calculations need careful design since a loop
160 from MININT TO MAXINT must work
, in the precision of integers
.
162 Here
''s how it works
, in C
:
164 0) The DO
... OD loop is simply a block with
167 1) The DO FOR EVER is simply implemented
:
176 2) The DO WHILE is also simple
:
180 if (!condition
) goto end_loop
188 3) The DO FOR
[while condition
] loop (no DOWN
)
194 start_temp
= start_exp
196 if (end_exp
< start_exp
) goto end_loop
197 /* following line is all unsigned arithmetic */
198 iter_var
= (end_exp
- start_exp
) / step_exp
199 user_var
= start_temp
201 if (!condition
) goto end_loop
205 if (iter_var
== 0) goto end_loop
207 user_var
+= step_temp
212 4) The
for [while condition
] loop (with DOWN
)
217 start_temp
= start_exp
219 if (end_exp
> start_exp
) goto end_loop
220 /* following line is all unsigned arithmetic */
221 iter_var
= (start_exp
- end_exp
) / step_exp
222 user_var
= start_temp
224 if (!condition
) goto end_loop
228 if (iter_var
== 0) goto end_loop
230 user_var
-= step_temp
236 5) The range loop
, which iterates over a mode
''s possible
237 values
, works just like the above step loops
, but with
238 the start
and end values taken from the mode
''s lower
239 and upper domain values
.
242 6) The FOR IN loop
, where a location enumeration is
243 specified (see spec on page
81 of Z
.200, bottom
247 decl iter_var as an
unsigned integer
248 loc_ptr_temp as pointer to a composite base type
251 iter_var
= array
''s length field
253 iter_var
= sizeof array
/ sizeof base_type
254 loc_ptr_temp
= &of highest
or lowest indexable entry
256 if (!condition
) goto end_loop
261 if (iter_var
== 0) goto end_loop
262 loc_ptr_temp
+/-= sizeof array base_type
267 7) The DO
FOR (DOWN
) IN powerset_exp
270 decl iterator as basetype of powerset
272 powerset_temp
:= save_expr (start_exp
)
273 iter_var
:= DOWN
? length
: 0
276 iter_var
:= __ffsetclrpowerset (powerset_temp
, length
,
279 iter_var
:= __ffsetclrpowerset (powrset_temp
, iter_var
, 0);
280 if (iter_var
< 0) goto end_loop
;
281 user_var
= iter_var
+ min_value
;
282 if (!condition
) goto end_loop
283 if (!DOWN
) iter_var
+:= 1;
292 So
, here
''s the general DO FOR schema
, as implemented here
:
294 expand_start_loop
-- start the loop
''s control scope
295 -- start scope
for synthesized loop variables
296 declare_temps
-- create
, initialize temporary variables
297 maybe_skip_loop
-- skip loop
if end conditions unsatisfiable
298 initialize_iter_var
-- initialize the iteration counter
299 -- initialize user
''s loop variable
300 expand_start_loop
-- generate top
-of
-loop label
301 top_loop_end_check
-- generate
while code
and/or
302 powerset find
-a
-bit function call
305 . user
''s loop body code
308 bottom_loop_end_check
-- exit
if counter has become zero
309 increment_temps
-- update temps
for next iteration
310 expand_end_loop
-- generate jump back to top of loop
311 expand_end_cond
-- generate label
for end of conditional
312 -- end of scope
for synthesized loop variables
313 free_iterators
-- free up iterator space
315 When there are two
or more iterator phrases
, each of the
316 above loop steps must act upon all iterators
. For example
,
317 the
'increment_temps' step must increment all temporaries
318 (associated with all iterators
).
320 NOTE
: Z
.200, section
10.1 says that a block is
...
321 "the actions statement list in a do action, including any
322 loop counter and while control". This means that an exp
-
323 ression in a WHILE control can include references to the
324 loop counters created
for the loop
''s exclusive use
.
329 DO FOR j IN a WHILE j
> 0;
332 The
'j' referenced in the
while is the loc
-identity
'j'
333 created inside the loop
''s scope
, and NOT the
'j' declared
338 * The following routines are called directly by the
344 LOOP
*temp
= (LOOP
*)xmalloc (sizeof (LOOP
));
346 /* push a new loop onto the stack */
347 temp
->nxt_level
= loopstack
;
348 temp
->iter_list
= (ITERATOR
*)0;
355 LOOP
*do_temp
= loopstack
;
358 /* pop loop block off the list */
359 loopstack
= do_temp
->nxt_level
;
361 /* free the loop's iterator blocks */
362 ip
= do_temp
->iter_list
;
365 ITERATOR
*temp
= ip
->next
;
383 expand_start_bindings (0);
392 end_loop_scope (opt_label
)
396 possibly_define_exit_label (opt_label
);
400 expand_end_bindings (getdecls (), kept_level_p (), 0);
403 poplevel (kept_level_p (), 1, 0);
407 /* we need the above 2 functions somehow modified for initialising
408 of non-value arrays */
411 nonvalue_begin_loop_scope ()
413 pushlevel (0); /* this happens only in pass 2 */
419 expand_start_bindings (0);
423 nonvalue_end_loop_scope ()
425 expand_end_bindings (getdecls (), kept_level_p (), 0);
427 poplevel (kept_level_p (), 1, 0);
430 /* The iterator structure records all aspects of a
431 * 'FOR i := start [DOWN] TO end' clause or
432 * 'FOR i IN modename' or 'FOR i IN powerset' clause.
433 * It's saved on the iter_list of the current LOOP.
436 build_loop_iterator (user_var
, start_exp
, step_exp
, end_exp
,
437 down_flag
, in_flag
, ever_flag
)
438 tree user_var
, start_exp
, step_exp
, end_exp
;
439 int down_flag
, in_flag
, ever_flag
;
441 ITERATOR
*ip
= (ITERATOR
*)xmalloc (sizeof (ITERATOR
));
443 /* chain this iterator onto the current loop */
444 if (loopstack
->iter_list
== NULL
)
445 loopstack
->iter_list
= ip
;
448 ITERATOR
*temp
= loopstack
->iter_list
;
449 while (temp
->next
!= NULL
)
454 ip
->user_var
= user_var
;
455 ip
->start_exp
= start_exp
;
456 ip
->step_exp
= step_exp
;
457 ip
->end_exp
= end_exp
;
458 ip
->start_temp
= NULL_TREE
;
459 ip
->end_temp
= NULL_TREE
;
460 ip
->step_temp
= NULL_TREE
;
461 ip
->down_flag
= down_flag
;
462 ip
->powerset_temp
= NULL_TREE
;
463 ip
->iter_var
= NULL_TREE
;
464 ip
->iter_type
= NULL_TREE
;
465 ip
->stepin_type
= NULL_TREE
;
466 ip
->loc_ptr_temp
= NULL_TREE
;
467 ip
->error_flag
= 1; /* assume error will be found */
468 ip
->next
= (ITERATOR
*)0;
471 ip
->itype
= DO_FOREVER
;
472 else if (in_flag
&& start_exp
!= NULL_TREE
)
474 if (TREE_CODE (start_exp
) == ERROR_MARK
)
476 if (TREE_TYPE (start_exp
) == NULL_TREE
)
478 if (TREE_CODE (start_exp
) == CONSTRUCTOR
)
479 error ("modeless tuple not allowed in this context");
481 error ("IN expression does not have a mode");
484 if (TREE_CODE (TREE_TYPE (start_exp
)) == SET_TYPE
)
486 if (CH_BOOLS_TYPE_P (TREE_TYPE (start_exp
)))
488 sorry ("location enumeration for BOOLS");
491 ip
->itype
= DO_POWERSET
;
493 else if (discrete_type_p (TREE_TYPE (ip
->start_exp
)))
495 /* range enumeration */
496 tree type
= TREE_TYPE (ip
->start_exp
);
497 /* save the original type for later use in determine to do a
499 ip
->stepin_type
= type
;
503 ip
->start_exp
= build_chill_upper (type
);
504 ip
->end_exp
= build_chill_lower (type
);
508 ip
->start_exp
= build_chill_lower (type
);
509 ip
->end_exp
= build_chill_upper (type
);
512 else if (TREE_CODE (TREE_TYPE (ip
->start_exp
)) == ARRAY_TYPE
)
514 if (TYPE_PACKED (TREE_TYPE (ip
->start_exp
)))
516 sorry ("location enumeration for bit-packed arrays");
521 else if (chill_varying_type_p (TREE_TYPE (ip
->start_exp
)))
522 ip
->itype
= DO_LOC_VARYING
;
525 error ("Loop's IN expression is not a composite object");
531 if (ip
->itype
== DO_STEP
)
533 struct ch_class
class;
535 if (ip
->step_exp
== NULL_TREE
)
536 ip
->step_exp
= integer_one_node
;
538 if (! discrete_type_p (TREE_TYPE (ip
->start_exp
)))
540 error ("start expr must have discrete mode");
543 if (TREE_CODE (TREE_TYPE (ip
->start_exp
)) == ENUMERAL_TYPE
544 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip
->start_exp
)))
546 error ("DO FOR start expression is a numbered SET");
549 if (TREE_CODE (ip
->end_exp
) == ERROR_MARK
)
551 if (TREE_CODE (TREE_TYPE (ip
->end_exp
)) == ENUMERAL_TYPE
552 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip
->end_exp
)))
554 error ("TO expression is a numbered SET");
557 if (! discrete_type_p (TREE_TYPE (ip
->end_exp
)))
559 error ("TO expr must have discrete mode");
562 if (! CH_COMPATIBLE_CLASSES (ip
->start_exp
, ip
->end_exp
))
564 error ("start expr and TO expr must be compatible");
567 if (step_exp
!= NULL_TREE
)
569 if (TREE_CODE (step_exp
) == ERROR_MARK
)
571 if (! discrete_type_p (TREE_TYPE (step_exp
)))
573 error ("BY expr must have discrete mode");
576 if (! CH_COMPATIBLE_CLASSES (ip
->start_exp
, step_exp
))
578 error ("start expr and BY expr must be compatible");
583 if (! flag_local_loop_counter
)
585 /* In this case, it's a previously-declared VAR_DECL node. */
586 tree id_node
= ip
->user_var
;
587 if (TREE_CODE (ip
->user_var
) == IDENTIFIER_NODE
)
588 ip
->user_var
= lookup_name (ip
->user_var
);
590 /* Chill 1984 allows the name to be a defining occurrence,
591 but does not require it. */
592 if (ip
->user_var
== NULL_TREE
)
594 warning ("loop identifier undeclared");
595 ip
->user_var
= id_node
;
596 /* We declare a local name below. */
600 if (TREE_CODE (TREE_TYPE (ip
->user_var
)) == REFERENCE_TYPE
)
601 ip
->user_var
= convert_from_reference (ip
->user_var
);
603 if (! CH_COMPATIBLE_CLASSES (ip
->start_exp
, ip
->user_var
))
605 error ("loop variable incompatible with start expression");
608 class = chill_expr_class (ip
->user_var
);
611 /* Otherwise, declare a new name. */
612 if (TREE_CODE (ip
->user_var
) == IDENTIFIER_NODE
)
614 class = CH_RESULTING_CLASS (chill_expr_class (ip
->start_exp
),
615 chill_expr_class (ip
->end_exp
));
617 class = CH_RESULTING_CLASS (class, chill_expr_class (step_exp
));
619 /* Integer literals noramally have type 'long long'
620 (see convert_integer in lex.c). That is usually overkill. */
621 if (class.kind
== CH_DERIVED_CLASS
622 && class.mode
== long_long_integer_type_node
623 && int_fits_type_p (ip
->start_exp
, integer_type_node
)
624 && int_fits_type_p (ip
->end_exp
, integer_type_node
))
625 class.mode
= integer_type_node
;
628 if (TREE_CODE (ip
->start_exp
) == INTEGER_CST
629 && TREE_CODE (ip
->end_exp
) == INTEGER_CST
630 && compare_int_csts (ip
->down_flag
? LT_EXPR
: GT_EXPR
,
631 ip
->start_exp
, ip
->end_exp
))
632 warning ("body of DO FOR will never execute");
634 ip
->start_exp
= convert_to_class (class, ip
->start_exp
);
635 ip
->end_exp
= convert_to_class (class, ip
->end_exp
);
636 ip
->step_exp
= convert_to_class (class, ip
->step_exp
);
638 if (TREE_CODE (ip
->step_exp
) != INTEGER_CST
)
640 /* generate runtime check for negative BY expr */
642 check_range (ip
->step_exp
, ip
->step_exp
,
643 integer_zero_node
, NULL_TREE
);
645 else if (compare_int_csts (LE_EXPR
, ip
->step_exp
, integer_zero_node
))
647 error ("BY expression is negative or zero");
652 ip
->error_flag
= 0; /* no errors! */
656 build_loop_start (start_label
)
659 ITERATOR
*firstp
= loopstack
->iter_list
;
661 if (firstp
->error_flag
)
666 if (initialize_iter_var ())
669 /* use the label as an 'exit' label,
670 'goto' needs another sort of label */
671 expand_start_loop (start_label
!= NULL_TREE
);
675 * Called after the last action of the loop body
681 ITERATOR
*ip
= loopstack
->iter_list
;
683 emit_line_note (input_filename
, lineno
);
688 if (bottom_loop_end_check ())
691 if (increment_temps ())
696 for (; ip
!= NULL
; ip
= ip
->next
)
711 * Reserve space for any loop-control temporaries, initialize them
716 ITERATOR
*firstp
= loopstack
->iter_list
, *ip
;
719 for (ip
= firstp
; ip
!= NULL
; ip
= ip
->next
)
727 = type_for_size (TYPE_PRECISION (TREE_TYPE (ip
->start_exp
)), 1);
729 /* create, initialize temporaries if expressions aren't constant */
730 ip
->start_temp
= maybe_make_for_temp (ip
->start_exp
, "for_start",
731 TREE_TYPE (ip
->start_exp
));
732 ip
->end_temp
= maybe_make_for_temp (ip
->end_exp
, "for_end",
733 TREE_TYPE (ip
->end_exp
));
734 /* this is just the step-expression */
735 ip
->step_temp
= maybe_make_for_temp (ip
->step_exp
, "for_step",
736 TREE_TYPE (ip
->step_exp
));
737 if (TREE_CODE (ip
->user_var
) == IDENTIFIER_NODE
)
739 /* (re-)declare the user's iteration variable in the
741 tree id_node
= ip
->user_var
;
743 decl_temp1 (id_node
, TREE_TYPE (ip
->start_exp
), 0, NULL_TREE
,
745 CH_DERIVED_FLAG (ip
->user_var
) = CH_DERIVED_FLAG (ip
->start_exp
);
746 pushdecl (ip
->user_var
);
749 decl_temp1 (get_unique_identifier ("iter_var"),
750 ip
->iter_type
, 0, NULL_TREE
, 0, 0);
754 /* the user's powerset-expression */
755 ip
->powerset_temp
= save_expr (ip
->start_exp
);
756 mark_addressable (ip
->powerset_temp
);
758 ip
->iter_type
= integer_type_node
;
759 ip
->iter_var
= decl_temp1 (get_unique_identifier ("iter_var"),
761 !ip
->down_flag
? integer_zero_node
762 : powersetlen (ip
->powerset_temp
),
765 if (flag_local_loop_counter
)
767 /* declare the user's iteration variable in the loop's scope. */
768 /* in this case, it's just an IDENTIFIER_NODE */
770 decl_temp1 (ip
->user_var
,
771 TYPE_DOMAIN (TREE_TYPE (ip
->start_exp
)),
773 pushdecl (ip
->user_var
);
777 /* in this case, it's a previously-declared VAR_DECL node */
778 ip
->user_var
= lookup_name (ip
->user_var
);
784 ip
->iter_type
= chill_unsigned_type_node
;
785 /* create the counter temp */
787 build_temporary_variable ("iter_var", ip
->iter_type
);
789 if (!CH_LOCATION_P (ip
->start_exp
))
791 = decl_temp1 (get_unique_identifier ("iter_loc"),
792 TREE_TYPE (ip
->start_exp
), 0,
793 ip
->start_exp
, 0, 0);
795 if (ip
->itype
== DO_LOC
)
797 tree array_type
= TREE_TYPE (ip
->start_exp
);
801 /* FIXME: check for array type in ip->start_exp */
803 /* create pointer temporary */
804 ip
->base_type
= TREE_TYPE (array_type
);
805 ptr_type
= build_pointer_type (ip
->base_type
);
807 build_temporary_variable ("loc_ptr_tmp", ptr_type
);
809 /* declare the user's iteration variable in
810 the loop's scope, as an expression, to be
811 passed to build_component_ref later */
812 save_expr_under_name (ip
->user_var
,
813 build1 (INDIRECT_REF
, ip
->base_type
,
816 /* FIXME: see stor_layout */
817 ip
->step_temp
= size_in_bytes (ip
->base_type
);
819 temp
= TYPE_DOMAIN (array_type
);
821 /* pointer to first array entry to look at */
822 start_ptr
= build1 (ADDR_EXPR
, ptr_type
, ip
->start_exp
);
823 mark_addressable (ip
->start_exp
);
824 ip
->start_temp
= ip
->down_flag
?
825 fold (build (PLUS_EXPR
, ptr_type
,
827 fold (build (MULT_EXPR
, integer_type_node
, ip
->step_temp
,
828 fold (build (MINUS_EXPR
, integer_type_node
,
829 TYPE_MAX_VALUE (temp
),
830 TYPE_MIN_VALUE (temp
)))))))
836 convert (integer_type_node
,
837 build_component_ref (ip
->start_exp
, var_length_id
));
838 tree array_type
= TREE_TYPE (TREE_CHAIN (
839 TYPE_FIELDS (TREE_TYPE (ip
->start_exp
))));
840 tree array_data_ptr
=
841 build_component_ref (ip
->start_exp
, var_data_id
);
844 if (TREE_CODE (TREE_TYPE (array_type
)) == BOOLEAN_TYPE
)
846 error ("Can't iterate through array of BOOL");
847 firstp
->error_flag
= 1;
848 return firstp
->error_flag
;
851 /* create pointer temporary */
852 ip
->base_type
= TREE_TYPE (array_type
);
853 ptr_type
= build_pointer_type (ip
->base_type
);
855 build_temporary_variable ("loc_ptr_temp", ptr_type
);
858 /* declare the user's iteration variable in
859 the loop's scope, as an expression, to be
860 passed to build_component_ref later */
861 save_expr_under_name (ip
->user_var
,
862 build1 (INDIRECT_REF
, ip
->base_type
,
865 /* FIXME: see stor_layout */
866 ip
->step_temp
= size_in_bytes (ip
->base_type
);
868 /* pointer to first array entry to look at */
869 start_ptr
= build1 (ADDR_EXPR
, ptr_type
, array_data_ptr
);
870 mark_addressable (array_data_ptr
);
871 ip
->start_temp
= ip
->down_flag
?
872 fold (build (PLUS_EXPR
, ptr_type
,
874 fold (build (MULT_EXPR
, integer_type_node
, ip
->step_temp
,
875 fold (build (MINUS_EXPR
, integer_type_node
,
877 integer_one_node
))))))
884 return firstp
->error_flag
;
888 * Initialize the hidden iteration-control variables,
889 * and the user's explicit loop variable.
892 initialize_iter_var ()
894 ITERATOR
*firstp
= loopstack
->iter_list
, *ip
;
896 for (ip
= firstp
; ip
!= NULL
; ip
= ip
->next
)
900 tree array_type
, array_length
;
906 count
= build (MINUS_EXPR
, ip
->iter_type
,
907 convert (ip
->iter_type
,
908 ip
->down_flag
? ip
->start_temp
: ip
->end_temp
),
909 convert (ip
->iter_type
,
910 ip
->down_flag
? ip
->end_temp
: ip
->start_temp
));
911 count
= fold (build (TRUNC_DIV_EXPR
, ip
->iter_type
,
914 /* The count in this case is actually one less than the
915 number of iterations, to avoid overflow problems
916 if we iterate *all* the values of iter_type. */
917 /* initialize the loop's hidden counter variable */
919 build_chill_modify_expr (ip
->iter_var
, count
));
921 /* initialize user's variable */
923 build_chill_modify_expr (ip
->user_var
, ip
->start_temp
));
929 array_type
= TREE_TYPE (ip
->start_exp
);
930 array_length
= fold (build (TRUNC_DIV_EXPR
, integer_type_node
,
931 size_in_bytes (array_type
),
932 size_in_bytes (TREE_TYPE (array_type
))));
937 = convert (integer_type_node
,
938 build_component_ref (ip
->start_exp
, var_length_id
));
941 expand_expr_stmt (build_chill_modify_expr (ip
->iter_var
,
944 build_chill_modify_expr (ip
->loc_ptr_temp
,
952 return firstp
->error_flag
;
955 /* Generate code to skip the whole loop, if start expression not
956 * <= end expression (or >= for DOWN loops). This comparison must
957 * *NOT* be done in unsigned mode, or it will fail.
958 * Also, skip processing an empty VARYING array.
963 ITERATOR
*firstp
= loopstack
->iter_list
, *ip
;
965 for (ip
= firstp
; ip
!= NULL
; ip
= ip
->next
)
971 build_compare_discrete_expr (ip
->down_flag
? GE_EXPR
: LE_EXPR
,
972 ip
->start_temp
, ip
->end_temp
), 0);
976 { tree array_length
=
977 convert (integer_type_node
,
978 build_component_ref (ip
->start_exp
, var_length_id
));
980 build (NE_EXPR
, TREE_TYPE (array_length
),
981 array_length
, integer_zero_node
), 0);
991 * Check at the top of the loop for a termination
994 top_loop_end_check (condition
)
999 for (ip
= loopstack
->iter_list
; ip
!= NULL
; ip
= ip
->next
)
1009 const char *func_name
;
1010 tree user_type
= TREE_TYPE (ip
->user_var
);
1013 func_name
= "__flsetclrpowerset";
1015 func_name
= "__ffsetclrpowerset";
1017 temp1
= lookup_name (get_identifier (func_name
));
1019 temp1
= build_chill_function_call (temp1
,
1020 tree_cons (NULL_TREE
, force_addr_of (ip
->powerset_temp
),
1021 tree_cons (NULL_TREE
, ip
->iter_var
,
1022 tree_cons (NULL_TREE
, integer_zero_node
, NULL_TREE
))));
1024 temp1
= build_chill_function_call (temp1
,
1025 tree_cons (NULL_TREE
, force_addr_of (ip
->powerset_temp
),
1026 tree_cons (NULL_TREE
, powersetlen (ip
->powerset_temp
),
1027 tree_cons (NULL_TREE
, ip
->iter_var
, NULL_TREE
))));
1028 expand_assignment (ip
->iter_var
, temp1
, 0, 0);
1029 expand_exit_loop_if_false (0, build (GE_EXPR
, boolean_type_node
,
1031 integer_zero_node
));
1032 temp1
= TYPE_MIN_VALUE
1033 (TYPE_DOMAIN (TREE_TYPE (ip
->powerset_temp
)));
1034 expand_assignment (ip
->user_var
,
1035 build (PLUS_EXPR
, user_type
,
1036 convert (user_type
, ip
->iter_var
),
1037 convert (user_type
, temp1
)),
1042 case DO_LOC_VARYING
:
1048 emit_line_note (input_filename
, lineno
);
1050 /* now, exit the loop if the condition isn't TRUE. */
1052 expand_exit_loop_if_false (0, truthvalue_conversion (condition
));
1056 * Check generated temporaries for loop's end
1059 bottom_loop_end_check ()
1061 ITERATOR
*firstp
= loopstack
->iter_list
, *ip
;
1063 emit_line_note (input_filename
, lineno
);
1065 /* now, generate code to check each loop counter for termination */
1066 for (ip
= firstp
; ip
!= NULL
; ip
= ip
->next
)
1073 /* exit if it's zero */
1074 expand_exit_loop_if_false (0,
1075 build (NE_EXPR
, boolean_type_node
,
1077 integer_zero_node
));
1078 /* decrement iteration counter by one */
1079 chill_expand_assignment (ip
->iter_var
, MINUS_EXPR
, integer_one_node
);
1082 case DO_LOC_VARYING
:
1083 /* decrement iteration counter by one */
1084 chill_expand_assignment (ip
->iter_var
, MINUS_EXPR
, integer_one_node
);
1085 /* exit if it's zero */
1086 expand_exit_loop_if_false (0,
1087 build (NE_EXPR
, boolean_type_node
,
1089 integer_zero_node
));
1098 return firstp
->error_flag
;
1102 * increment the loop-control variables.
1107 ITERATOR
*firstp
= loopstack
->iter_list
, *ip
;
1109 for (ip
= firstp
; ip
!= NULL
; ip
= ip
->next
)
1118 fold (build (ip
->down_flag
? MINUS_EXPR
: PLUS_EXPR
,
1119 TREE_TYPE (ip
->user_var
), ip
->user_var
,
1122 build_chill_modify_expr (ip
->user_var
, delta
));
1126 case DO_LOC_VARYING
:
1127 /* This statement uses the C semantics, so that
1128 the pointer is actually incremented by the
1129 length of the object pointed to. */
1131 enum tree_code op
= ip
->down_flag
? MINUS_EXPR
: PLUS_EXPR
;
1132 tree el_type
= TREE_TYPE (TREE_TYPE (ip
->loc_ptr_temp
));
1133 chill_expand_assignment (ip
->loc_ptr_temp
, NOP_EXPR
,
1135 TREE_TYPE (ip
->loc_ptr_temp
),
1137 size_in_bytes (el_type
)));
1142 expand_assignment (ip
->iter_var
,
1143 build (PLUS_EXPR
, ip
->iter_type
,
1152 return firstp
->error_flag
;
1156 * Generate a (temporary) unique identifier_node of
1157 * the form "__tmp_%s_%d"
1160 get_unique_identifier (lead
)
1164 static int idcount
= 0;
1166 sprintf (idbuf
, "__tmp_%s_%d", lead
? lead
: "", idcount
++);
1167 return get_identifier (idbuf
);
1171 * build a temporary variable, given its NAME and TYPE.
1172 * The name will have a number appended to assure uniqueness.
1173 * return its DECL node.
1176 build_temporary_variable (name
, type
)
1180 return decl_temp1 (get_unique_identifier (name
), type
, 0, NULL_TREE
, 0, 0);
1185 * If the given expression isn't a constant, build a temp for it
1186 * and evaluate the expression into the temp. Return the tree
1187 * representing either the original constant expression or the
1188 * temp which now contains the expression's value.
1191 maybe_make_for_temp (exp
, temp_name
, exp_type
)
1193 const char *temp_name
;
1198 if (exp
!= NULL_TREE
)
1200 /* if exp isn't constant, create a temporary for its value */
1201 if (TREE_CONSTANT (exp
))
1203 /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */
1204 result
= convert (exp_type
, exp
);
1207 /* build temp, assign the value */
1208 result
= decl_temp1 (get_unique_identifier (temp_name
), exp_type
, 0,
1217 * Adapt the C unsigned_type function to CHILL - we need to
1218 * account for any CHILL-specific integer types here. So far,
1219 * the 16-bit integer type is the only one.
1222 chill_unsigned_type (type
)
1225 extern tree chill_unsigned_type_node
;
1226 tree type1
= TYPE_MAIN_VARIANT (type
);
1228 if (type1
== chill_integer_type_node
)
1229 return chill_unsigned_type_node
;
1231 return unsigned_type (type
);