* class.c (check_bitfield_decl): New function, split out from
[official-gcc.git] / gcc / ch / loop.c
blob5a1385e916e5b65098014115ec9c6033b3854bed
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)
9 any later version.
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. */
21 #include "config.h"
22 #include "system.h"
23 #include "tree.h"
24 #include "ch-tree.h"
25 #include "lex.h"
26 #include "flags.h"
27 #include "actions.h"
28 #include "input.h"
29 #include "obstack.h"
30 #include "assert.h"
31 #include "rtl.h"
32 #include "toplev.h"
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));
46 #if 0
47 static tree chill_unsigned_type PROTO((tree));
48 #endif
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
57 * first ITERATOR.
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.
63 * 3) DO; ... OD
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.
84 typedef enum
86 DO_FOREVER,
87 DO_OD,
88 DO_STEP,
89 DO_POWERSET,
90 DO_LOC,
91 DO_LOC_VARYING
92 } ITER_TYPE;
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
100 user error */
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 */
119 } ITERATOR;
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 */
129 } LOOP;
131 static LOOP *loopstack = (LOOP *)0;
133 #if 0
135 Here is a CHILL DO FOR statement:
137 DO FOR user_var := start_exp BY step_exp [DOWN] TO end_exp
138 WHILE condition;
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
144 following works:
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
157 is discussed later.
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
165 its own scope.
167 1) The DO FOR EVER is simply implemented:
169 loop_top:
171 . body of loop
173 goto loop_top
174 end_loop:
176 2) The DO WHILE is also simple:
179 loop_top:
180 if (!condition) goto end_loop
182 . body of loop
184 goto loop_top
185 end_loop:
188 3) The DO FOR [while condition] loop (no DOWN)
190 push a new scope,
191 decl iter_var
193 step_temp = step_exp
194 start_temp = start_exp
195 end_temp = end_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
200 loop_top:
201 if (!condition) goto end_loop
203 . body of loop
205 if (iter_var == 0) goto end_loop
206 iter_var--
207 user_var += step_temp
208 goto loop_top
209 end_loop:
210 pop scope
212 4) The for [while condition] loop (with DOWN)
214 push a new scope,
215 decl iter
216 step_temp = step_exp
217 start_temp = start_exp
218 end_temp = end_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
223 loop_top:
224 if (!condition) goto end_loop
226 . body of loop
228 if (iter_var == 0) goto end_loop
229 iter_var--
230 user_var -= step_temp
231 goto loop_top
232 end_loop:
233 pop scope
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
244 of page 186):
246 push a new scope,
247 decl iter_var as an unsigned integer
248 loc_ptr_temp as pointer to a composite base type
250 if array is varying
251 iter_var = array''s length field
252 else
253 iter_var = sizeof array / sizeof base_type
254 loc_ptr_temp = &of highest or lowest indexable entry
255 loop_top:
256 if (!condition) goto end_loop
258 . body of loop
260 iter_var--
261 if (iter_var == 0) goto end_loop
262 loc_ptr_temp +/-= sizeof array base_type
263 goto loop_top
264 end_loop:
265 pop scope
267 7) The DO FOR (DOWN) IN powerset_exp
269 push a new scope,
270 decl iterator as basetype of powerset
272 powerset_temp := save_expr (start_exp)
273 iter_var := DOWN ? length : 0
274 loop_top:
275 if (DOWN)
276 iter_var := __ffsetclrpowerset (powerset_temp, length,
277 iter_var);
278 else
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;
285 . body of loop
287 goto loop_top
288 end_loop:
289 pop scope
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.
325 Example:
327 DCL a (1:10) INT;
328 DCL j INT;
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
334 before the loop.
335 #endif
338 * The following routines are called directly by the
339 * CHILL parser.
341 void
342 push_loop_block ()
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;
349 loopstack = temp;
352 void
353 pop_loop_block ()
355 LOOP *do_temp = loopstack;
356 ITERATOR *ip;
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;
363 while (ip != NULL)
365 ITERATOR *temp = ip->next;
366 free (ip);
367 ip = temp;
369 free (do_temp);
372 void
373 begin_loop_scope ()
375 pushlevel (1);
377 if (pass >= 2)
379 declare_temps ();
381 clear_last_expr ();
382 push_momentary ();
383 expand_start_bindings (0);
386 push_handler ();
391 void
392 end_loop_scope (opt_label)
393 tree opt_label;
395 if (opt_label)
396 possibly_define_exit_label (opt_label);
398 if (pass == 2)
400 expand_end_bindings (getdecls (), kept_level_p (), 0);
401 pop_momentary ();
403 poplevel (kept_level_p (), 1, 0);
407 /* we need the above 2 functions somehow modified for initialising
408 of non-value arrays */
410 void
411 nonvalue_begin_loop_scope ()
413 pushlevel (0); /* this happens only in pass 2 */
415 declare_temps ();
417 clear_last_expr ();
418 push_momentary ();
419 expand_start_bindings (0);
422 void
423 nonvalue_end_loop_scope ()
425 expand_end_bindings (getdecls (), kept_level_p (), 0);
426 pop_momentary ();
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.
435 void
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;
446 else
448 ITERATOR *temp = loopstack->iter_list;
449 while (temp->next != NULL)
450 temp = temp->next;
451 temp->next = ip;
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;
470 if (ever_flag)
471 ip->itype = DO_FOREVER;
472 else if (in_flag && start_exp != NULL_TREE)
474 if (TREE_CODE (start_exp) == ERROR_MARK)
475 return;
476 if (TREE_TYPE (start_exp) == NULL_TREE)
478 if (TREE_CODE (start_exp) == CONSTRUCTOR)
479 error ("modeless tuple not allowed in this context");
480 else
481 error ("IN expression does not have a mode");
482 return;
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");
489 return;
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
498 rangecheck or not */
499 ip->stepin_type = type;
500 ip->itype = DO_STEP;
501 if (ip->down_flag)
503 ip->start_exp = build_chill_upper (type);
504 ip->end_exp = build_chill_lower (type);
506 else
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");
517 return;
519 ip->itype = DO_LOC;
521 else if (chill_varying_type_p (TREE_TYPE (ip->start_exp)))
522 ip->itype = DO_LOC_VARYING;
523 else
525 error ("Loop's IN expression is not a composite object");
526 return;
529 else
530 ip->itype = DO_STEP;
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");
541 return;
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");
547 return;
549 if (TREE_CODE (ip->end_exp) == ERROR_MARK)
550 return;
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");
555 return;
557 if (! discrete_type_p (TREE_TYPE (ip->end_exp)))
559 error ("TO expr must have discrete mode");
560 return;
562 if (! CH_COMPATIBLE_CLASSES (ip->start_exp, ip->end_exp))
564 error ("start expr and TO expr must be compatible");
565 return;
567 if (step_exp != NULL_TREE)
569 if (TREE_CODE (step_exp) == ERROR_MARK)
570 return;
571 if (! discrete_type_p (TREE_TYPE (step_exp)))
573 error ("BY expr must have discrete mode");
574 return;
576 if (! CH_COMPATIBLE_CLASSES (ip->start_exp, step_exp))
578 error ("start expr and BY expr must be compatible");
579 return;
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. */
598 else
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");
606 return;
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));
616 if (step_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 */
641 ip->step_exp =
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");
648 return;
652 ip->error_flag = 0; /* no errors! */
655 void
656 build_loop_start (start_label)
657 tree start_label;
659 ITERATOR *firstp = loopstack->iter_list;
661 if (firstp->error_flag)
662 return;
664 maybe_skip_loop ();
666 if (initialize_iter_var ())
667 return;
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
676 * has been parsed.
678 void
679 build_loop_end ()
681 ITERATOR *ip = loopstack->iter_list;
683 emit_line_note (input_filename, lineno);
685 if (ip->error_flag)
686 return;
688 if (bottom_loop_end_check ())
689 return;
691 if (increment_temps ())
692 return;
694 expand_end_loop ();
696 for (; ip != NULL; ip = ip->next)
698 switch (ip->itype)
700 case DO_LOC_VARYING:
701 case DO_STEP:
702 expand_end_cond ();
703 break;
704 default:
705 break;
711 * Reserve space for any loop-control temporaries, initialize them
713 static int
714 declare_temps ()
716 ITERATOR *firstp = loopstack->iter_list, *ip;
717 tree start_ptr;
719 for (ip = firstp; ip != NULL; ip = ip->next)
721 switch (ip->itype)
723 case DO_FOREVER:
724 break;
725 case DO_STEP:
726 ip->iter_type
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
740 loop's scope. */
741 tree id_node = ip->user_var;
742 ip->user_var =
743 decl_temp1 (id_node, TREE_TYPE (ip->start_exp), 0, NULL_TREE,
744 0, 0);
745 CH_DERIVED_FLAG (ip->user_var) = CH_DERIVED_FLAG (ip->start_exp);
746 pushdecl (ip->user_var);
748 ip->iter_var =
749 decl_temp1 (get_unique_identifier ("iter_var"),
750 ip->iter_type, 0, NULL_TREE, 0, 0);
751 break;
753 case DO_POWERSET:
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"),
760 ip->iter_type, 0,
761 !ip->down_flag ? integer_zero_node
762 : powersetlen (ip->powerset_temp),
763 0, 0);
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 */
769 ip->user_var =
770 decl_temp1 (ip->user_var,
771 TYPE_DOMAIN (TREE_TYPE (ip->start_exp)),
772 0, NULL_TREE, 0, 0);
773 pushdecl (ip->user_var);
775 else
777 /* in this case, it's a previously-declared VAR_DECL node */
778 ip->user_var = lookup_name (ip->user_var);
780 break;
782 case DO_LOC:
783 case DO_LOC_VARYING:
784 ip->iter_type = chill_unsigned_type_node;
785 /* create the counter temp */
786 ip->iter_var =
787 build_temporary_variable ("iter_var", ip->iter_type);
789 if (!CH_LOCATION_P (ip->start_exp))
790 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);
798 tree ptr_type;
799 tree temp;
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);
806 ip->loc_ptr_temp =
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,
814 ip->loc_ptr_temp));
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,
826 start_ptr,
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)))))))
831 : start_ptr;
833 else
835 tree array_length =
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);
842 tree ptr_type;
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);
854 ip->loc_ptr_temp =
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,
863 ip->loc_ptr_temp));
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,
873 start_ptr,
874 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
875 fold (build (MINUS_EXPR, integer_type_node,
876 array_length,
877 integer_one_node))))))
878 : start_ptr;
880 default:
884 return firstp->error_flag;
888 * Initialize the hidden iteration-control variables,
889 * and the user's explicit loop variable.
891 static int
892 initialize_iter_var ()
894 ITERATOR *firstp = loopstack->iter_list, *ip;
896 for (ip = firstp; ip != NULL; ip = ip->next)
898 switch (ip->itype)
900 tree array_type, array_length;
901 case DO_FOREVER:
902 break;
903 case DO_STEP:
905 tree count;
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,
912 fold (count),
913 ip->step_temp));
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 */
918 expand_expr_stmt (
919 build_chill_modify_expr (ip->iter_var, count));
921 /* initialize user's variable */
922 expand_expr_stmt (
923 build_chill_modify_expr (ip->user_var, ip->start_temp));
925 break;
926 case DO_POWERSET:
927 break;
928 case DO_LOC:
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))));
933 goto do_loc_common;
935 case DO_LOC_VARYING:
936 array_length
937 = convert (integer_type_node,
938 build_component_ref (ip->start_exp, var_length_id));
940 do_loc_common:
941 expand_expr_stmt (build_chill_modify_expr (ip->iter_var,
942 array_length));
943 expand_expr_stmt (
944 build_chill_modify_expr (ip->loc_ptr_temp,
945 ip->start_temp));
946 break;
948 default:
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.
960 static void
961 maybe_skip_loop ()
963 ITERATOR *firstp = loopstack->iter_list, *ip;
965 for (ip = firstp; ip != NULL; ip = ip->next)
967 switch (ip->itype)
969 case DO_STEP:
970 expand_start_cond (
971 build_compare_discrete_expr (ip->down_flag ? GE_EXPR : LE_EXPR,
972 ip->start_temp, ip->end_temp), 0);
973 break;
975 case DO_LOC_VARYING:
976 { tree array_length =
977 convert (integer_type_node,
978 build_component_ref (ip->start_exp, var_length_id));
979 expand_start_cond (
980 build (NE_EXPR, TREE_TYPE (array_length),
981 array_length, integer_zero_node), 0);
982 break;
984 default:
985 break;
991 * Check at the top of the loop for a termination
993 void
994 top_loop_end_check (condition)
995 tree condition;
997 ITERATOR *ip;
999 for (ip = loopstack->iter_list; ip != NULL; ip = ip->next)
1001 switch (ip->itype)
1003 case DO_FOREVER:
1004 case DO_STEP:
1005 break;
1006 case DO_POWERSET:
1008 tree temp1;
1009 const char *func_name;
1010 tree user_type = TREE_TYPE (ip->user_var);
1012 if (ip->down_flag)
1013 func_name = "__flsetclrpowerset";
1014 else
1015 func_name = "__ffsetclrpowerset";
1017 temp1 = lookup_name (get_identifier (func_name));
1018 if (ip->down_flag)
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))));
1023 else
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,
1030 ip->iter_var,
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)),
1038 0, 0);
1040 break;
1041 case DO_LOC:
1042 case DO_LOC_VARYING:
1043 break;
1044 default:
1048 emit_line_note (input_filename, lineno);
1050 /* now, exit the loop if the condition isn't TRUE. */
1051 if (condition)
1052 expand_exit_loop_if_false (0, truthvalue_conversion (condition));
1056 * Check generated temporaries for loop's end
1058 static int
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)
1068 switch (ip->itype)
1070 case DO_FOREVER:
1071 break;
1072 case DO_STEP:
1073 /* exit if it's zero */
1074 expand_exit_loop_if_false (0,
1075 build (NE_EXPR, boolean_type_node,
1076 ip->iter_var,
1077 integer_zero_node));
1078 /* decrement iteration counter by one */
1079 chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
1080 break;
1081 case DO_LOC:
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,
1088 ip->iter_var,
1089 integer_zero_node));
1090 break;
1091 case DO_POWERSET:
1092 break;
1093 default:
1098 return firstp->error_flag;
1102 * increment the loop-control variables.
1104 static int
1105 increment_temps ()
1107 ITERATOR *firstp = loopstack->iter_list, *ip;
1109 for (ip = firstp; ip != NULL; ip = ip->next)
1111 switch (ip->itype)
1113 case DO_FOREVER:
1114 break;
1115 case DO_STEP:
1117 tree delta =
1118 fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1119 TREE_TYPE (ip->user_var), ip->user_var,
1120 ip->step_temp));
1121 expand_expr_stmt (
1122 build_chill_modify_expr (ip->user_var, delta));
1124 break;
1125 case DO_LOC:
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,
1134 build (op,
1135 TREE_TYPE (ip->loc_ptr_temp),
1136 ip->loc_ptr_temp,
1137 size_in_bytes (el_type)));
1139 break;
1140 case DO_POWERSET:
1141 if (!ip->down_flag)
1142 expand_assignment (ip->iter_var,
1143 build (PLUS_EXPR, ip->iter_type,
1144 ip->iter_var,
1145 integer_one_node),
1146 0, 0);
1147 break;
1148 default:
1152 return firstp->error_flag;
1156 * Generate a (temporary) unique identifier_node of
1157 * the form "__tmp_%s_%d"
1159 tree
1160 get_unique_identifier (lead)
1161 const char *lead;
1163 char idbuf [256];
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.
1175 static tree
1176 build_temporary_variable (name, type)
1177 const char *name;
1178 tree 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.
1190 static tree
1191 maybe_make_for_temp (exp, temp_name, exp_type)
1192 tree exp;
1193 const char *temp_name;
1194 tree exp_type;
1196 tree result = exp;
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);
1206 else {
1207 /* build temp, assign the value */
1208 result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0,
1209 exp, 0, 0);
1212 return result;
1215 #if 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.
1221 static tree
1222 chill_unsigned_type (type)
1223 tree 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;
1230 else
1231 return unsigned_type (type);
1233 #endif