1 /* Implement looping actions for CHILL.
2 Copyright (C) 1992, 93, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
33 /* if the user codes '-flocal-loop-counter' on the command line,
34 ch-actions.c (lang_decode_option) will set this flag. */
35 int flag_local_loop_counter = 0;
37 extern tree chill_truthvalue_conversion PROTO((tree));
38 extern rtx emit_line_note PROTO((char *, int));
39 extern void error PROTO((char *, ...));
40 extern rtx expand_assignment PROTO((tree, tree, int, int));
41 extern void save_expr_under_name PROTO((tree, tree));
42 extern void stamp_nesting_label PROTO((tree));
43 extern int int_fits_type_p PROTO((tree, tree));
44 extern void warning PROTO((char *, ...));
46 /* forward declarations */
47 static int classify_loop PROTO((void));
48 static int declare_temps PROTO((void));
49 static int initialize_iter_var PROTO((void));
50 static int maybe_skip_loop PROTO((void));
51 static int top_loop_end_check PROTO((void));
52 static int bottom_loop_end_check PROTO((void));
53 static int increment_temps PROTO((void));
54 static tree build_temporary_variable PROTO((char *, tree));
55 static tree maybe_make_for_temp PROTO((tree, char *, tree));
56 static tree chill_unsigned_type PROTO((tree));
58 /* In terms of the parameters passed to build_loop_iterator,
59 * there are several types of loops. They are encoded by
60 * the ITER_TYPE enumeration.
62 * 1) DO FOR EVER; ... OD
63 * indicated by a NULL_TREE start_exp, step_exp and end_exp,
64 * condition == NULL, in_flag = 0, and ever_flag == 1 in the
67 * 2) DO WHILE cond; ... OD
68 * indicated by NULL_TREE start_exp, step_exp and end_exp,
69 * in_flag = 0, and condition != NULL.
72 * indicated by NULL_TREEs in start_exp, step_exp and end_exp,
73 * condition != NULL, in_flag == 0 and ever_flag == 0. This
74 * is not really a loop, but a compound statement.
76 * 4) DO FOR user_var := start_exp
77 * [DOWN] TO end_exp BY step_exp; ... DO
78 * indicated by non-NULL_TREE start_exp, step_exp and end_exp.
80 * 5) DO FOR user_var [DOWN] IN discrete_mode; ... OD
81 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
82 * discrete mode, with an optional down_flag.
84 * 6) DO FOR user_var [DOWN] IN powerset_expr; ... OD
85 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
86 * powerset mode, with an optional down_flag.
88 * 7) DO FOR user_var [DOWN] IN location; ... OD
89 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
90 * location mode, with an optional down_flag.
106 typedef struct iterator
108 /* These variables only have meaning in the first ITERATOR structure. */
109 ITER_TYPE itype; /* type of this iterator */
110 int error_flag; /* TRUE if no loop was started due to
112 tree condition; /* WHILE condition expression */
113 int down_flag; /* TRUE if DOWN was coded */
115 /* These variables have meaning in every ITERATOR structure. */
116 tree user_var; /* user's explicit iteration variable */
117 tree start_exp; /* user's start expression
118 or IN expression of a FOR .. IN*/
119 tree step_exp; /* user's step expression */
120 tree end_exp; /* user's end expression */
121 tree start_temp; /* temp holding evaluated start_exp */
122 tree end_temp; /* temp holding evaluated end_exp */
123 tree step_temp; /* temp holding evaluated step_exp */
124 tree powerset_temp; /* temp holding user's initial powerset expression */
125 tree loc_ptr_temp; /* temp holding count for LOC enumeration ptr */
126 tree iter_var; /* hidden variable for the loop */
127 tree iter_type; /* hidden variable's type */
128 tree base_type; /* LOC enumeration base type */
129 struct iterator *next; /* ptr to next iterator for this loop */
133 * There's an entry like this for each nested DO loop.
134 * The list is maintained by push_loop_block
135 * and pop_loop_block.
137 typedef struct loop {
138 struct loop *nxt_level; /* pointer to enclosing loop */
139 ITERATOR *iter_list; /* iterators for the current loop */
142 static LOOP *loop_stack = (LOOP *)0;
146 Here is a CHILL DO FOR statement:
148 DO FOR user_var := start_exp BY step_exp [DOWN] TO end_exp
151 For this loop to be 'safe', like a Pascal FOR loop, the start,
152 end, and increment expressions are computed once, before the
153 assignment to the iteration variable and saved in temporaries,
154 before the first assignment of the iteration variable, so the
157 FOR i := (i+1) TO (i+10) DO
159 To prevent changes to the start/end/step expressions from
160 effecting the loop''s termination, and to make the loop end-check
161 as simple as possible, we evaluate the step expression into
162 a temporary and compute a hidden iteration count before entering
163 the loop''s body. User code cannot effect the counter, and the
164 end-loop check simply decrements the counter and checks for zero.
166 The whole phrase FOR iter := ... TO end_exp can be repeated
167 multiple times, with different user-iteration variables. This
170 The loop counter calculations need careful design since a loop
171 from MININT TO MAXINT must work, in the precision of integers.
173 Here''s how it works, in C:
175 0) The DO ... OD loop is simply a block with
178 1) The DO FOR EVER is simply implemented:
187 2) The DO WHILE is also simple:
191 if (!condition) goto end_loop
199 3) The DO FOR [while condition] loop (no DOWN)
205 start_temp = start_exp
207 if (end_exp < start_exp) goto end_loop
208 /* following line is all unsigned arithmetic */
209 iter_var = (end_exp - start_exp + step_exp) / step_exp
210 user_var = start_temp
212 if (!condition) goto end_loop
217 if (iter_var == 0) goto end_loop
218 user_var += step_temp
223 4) The proposed CHILL for [while condition] loop (with DOWN)
228 start_temp = start_exp
230 if (end_exp > start_exp) goto end_loop
231 /* following line is all unsigned arithmetic */
232 iter_var = (start_exp - end_exp + step_exp) / step_exp
233 user_var = start_temp
235 if (!condition) goto end_loop
240 if (iter_var == 0) goto end_loop
241 user_var -= step_temp
247 5) The range loop, which iterates over a mode''s possible
248 values, works just like the above step loops, but with
249 the start and end values taken from the mode''s lower
250 and upper domain values.
253 6) The FOR IN loop, where a location enumeration is
254 specified (see spec on page 81 of Z.200, bottom
258 decl iter_var as an unsigned integer
259 loc_ptr_temp as pointer to a composite base type
262 iter_var = array''s length field
264 iter_var = sizeof array / sizeof base_type
265 loc_ptr_temp = &of highest or lowest indexable entry
267 if (!condition) goto end_loop
272 if (iter_var == 0) goto end_loop
273 loc_ptr_temp +/-= sizeof array base_type
278 7) The DO FOR (DOWN) IN powerset_exp
282 decl iterator as basetype of powerset
284 powerset_temp := start_exp
287 if (__flsetclrpowerset () == 0) goto end_loop;
289 if (__ffsetclrpowerset () == 0) goto end_loop;
290 if (!condition) goto end_loop
299 So, here''s the general DO FOR schema, as implemented here:
301 classify_loop -- what type of loop have we?
302 -- build_iterator does some of this, also
303 expand_start_loop -- start the loop''s control scope
304 -- start scope for synthesized loop variables
305 declare_temps -- create, initialize temporary variables
306 maybe_skip_loop -- skip loop if end conditions unsatisfiable
307 initialize_iter_var -- initialize the iteration counter
308 -- initialize user''s loop variable
309 expand_start_loop -- generate top-of-loop label
310 top_loop_end_check -- generate while code and/or
311 powerset find-a-bit function call
314 . user''s loop body code
317 bottom_loop_end_check -- exit if counter has become zero
318 increment_temps -- update temps for next iteration
319 expand_end_loop -- generate jump back to top of loop
320 expand_end_cond -- generate label for end of conditional
321 -- end of scope for synthesized loop variables
322 free_iterators -- free up iterator space
324 When there are two or more iterator phrases, each of the
325 above loop steps must act upon all iterators. For example,
326 the 'increment_temps' step must increment all temporaries
327 (associated with all iterators).
329 NOTE: Z.200, section 10.1 says that a block is ...
330 "the actions statement list in a do action, including any
331 loop counter and while control". This means that an exp-
332 ression in a WHILE control can include references to the
333 loop counters created for the loop''s exclusive use.
338 DO FOR j IN a WHILE j > 0;
341 The 'j' referenced in the while is the loc-identity 'j'
342 created inside the loop''s scope, and NOT the 'j' declared
347 * The following routines are called directly by the
353 LOOP *temp = (LOOP *)xmalloc (sizeof (LOOP));
355 /* push a new loop onto the stack */
356 temp->nxt_level = loop_stack;
357 temp->iter_list = (ITERATOR *)0;
364 LOOP *do_temp = loop_stack;
367 /* pop loop block off the list */
368 loop_stack = do_temp->nxt_level;
370 /* free the loop's iterator blocks */
371 ip = do_temp->iter_list;
374 ITERATOR *temp = ip->next;
384 ITERATOR *firstp = loop_stack->iter_list;
390 * We need to classify the loop and declare its temporaries
391 * here, so as to define them before the WHILE condition
392 * (if any) is parsed. The WHILE expression may refer to
395 if (classify_loop ())
398 if (firstp->itype != DO_OD)
403 expand_start_bindings (0);
408 end_loop_scope (opt_label)
412 possibly_define_exit_label (opt_label);
418 expand_end_bindings (getdecls (), kept_level_p (), 0);
422 /* The iterator structure records all aspects of a
423 * 'FOR i := start [DOWN] TO end' clause or
424 * 'FOR i IN modename' or 'FOR i IN powerset' clause.
425 * It's saved on the iter_list of the current LOOP.
428 build_loop_iterator (user_var, start_exp, step_exp, end_exp,
429 down_flag, in_flag, ever_flag)
430 tree user_var, start_exp, step_exp, end_exp;
431 int down_flag, in_flag, ever_flag;
433 ITERATOR *ip = (ITERATOR *)xmalloc (sizeof (ITERATOR));
435 /* chain this iterator onto the current loop */
436 if (loop_stack->iter_list == NULL)
437 loop_stack->iter_list = ip;
440 ITERATOR *temp = loop_stack->iter_list;
441 while (temp->next != NULL)
446 ip->itype = DO_UNUSED;
447 ip->user_var = user_var;
448 ip->start_exp = start_exp;
449 ip->step_exp = step_exp;
450 ip->end_exp = end_exp;
451 ip->condition = NULL_TREE;
452 ip->start_temp = NULL_TREE;
453 ip->end_temp = NULL_TREE;
454 ip->step_temp = NULL_TREE;
455 ip->down_flag = down_flag;
456 ip->powerset_temp = NULL_TREE;
457 ip->iter_var = NULL_TREE;
458 ip->iter_type = NULL_TREE;
459 ip->loc_ptr_temp = NULL_TREE;
460 ip->error_flag = 1; /* assume error will be found */
461 ip->next = (ITERATOR *)0;
464 ip->itype = DO_FOREVER;
465 else if (in_flag && start_exp != NULL_TREE)
467 if (TREE_CODE (start_exp) == ERROR_MARK)
469 if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE)
470 ip->itype = DO_POWERSET;
471 else if (discrete_type_p (TREE_TYPE (ip->start_exp)))
472 ip->itype = DO_RANGE;
473 else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE)
475 else if (chill_varying_type_p (TREE_TYPE (ip->start_exp)))
476 ip->itype = DO_LOC_VARYING;
479 error ("Loop's IN expression is not a composite object");
483 else if (start_exp == NULL_TREE && end_exp == NULL_TREE
484 && step_exp == NULL_TREE && !down_flag)
488 /* FIXME: Move this to the lexer? */
489 #define CST_FITS_INT(NODE) (TREE_CODE(NODE) == INTEGER_CST &&\
490 int_fits_type_p (NODE, integer_type_node))
492 tree max_prec_type = integer_type_node;
494 if (! discrete_type_p (TREE_TYPE (ip->start_exp)))
496 error ("start expr must have discrete mode");
499 if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ENUMERAL_TYPE
500 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->start_exp)))
502 error ("DO FOR start expression is a numbered SET");
505 if (TREE_CODE (TREE_TYPE (ip->end_exp)) == ENUMERAL_TYPE
506 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->end_exp)))
508 error ("TO expression is a numbered SET");
511 /* Convert all three expressions to a common precision,
512 which is the largest precision they exhibit, but
513 INTEGER_CST nodes are built in the lexer as
514 long_integer_type nodes. We'll treat convert them to
515 integer_type_nodes if possible, for faster loop times. */
517 if (TYPE_PRECISION (max_prec_type) <
518 TYPE_PRECISION (TREE_TYPE (ip->start_exp))
519 && !CST_FITS_INT (ip->start_exp))
520 max_prec_type = TREE_TYPE (ip->start_exp);
521 if (! discrete_type_p (TREE_TYPE (ip->end_exp)))
523 error ("TO expr must have discrete mode");
526 if (! CH_COMPATIBLE (ip->start_exp,
527 TREE_TYPE (ip->end_exp)))
529 error ("start expr and TO expr must be compatible");
532 if (TYPE_PRECISION (max_prec_type) <
533 TYPE_PRECISION (TREE_TYPE (ip->end_exp))
534 && !CST_FITS_INT (ip->end_exp))
535 max_prec_type = TREE_TYPE (ip->end_exp);
536 if (ip->step_exp != NULL_TREE)
538 /* assure that default 'BY 1' gets a useful type */
539 if (ip->step_exp == integer_one_node)
540 ip->step_exp = convert (TREE_TYPE (ip->start_exp),
542 if (! discrete_type_p (TREE_TYPE (ip->step_exp)))
544 error ("BY expr must have discrete mode");
547 if (! CH_COMPATIBLE (ip->start_exp,
548 TREE_TYPE (ip->step_exp)))
550 error ("start expr and BY expr must be compatible");
553 if (TYPE_PRECISION (max_prec_type) <
554 TYPE_PRECISION (TREE_TYPE (ip->step_exp))
555 && !CST_FITS_INT (ip->step_exp))
556 max_prec_type = TREE_TYPE (ip->step_exp);
558 if (TREE_CODE (ip->start_exp) == INTEGER_CST
559 && TREE_CODE (ip->end_exp) == INTEGER_CST
560 && compare_int_csts (ip->down_flag ? LT_EXPR : GT_EXPR,
561 ip->start_exp, ip->end_exp))
562 warning ("body of DO FOR will never execute");
565 convert (max_prec_type, ip->start_exp);
567 convert (max_prec_type, ip->end_exp);
569 if (ip->step_exp != NULL_TREE)
572 convert (max_prec_type, ip->step_exp);
574 if (TREE_CODE (ip->step_exp) != INTEGER_CST)
576 /* generate runtime check for negative BY expr */
578 check_range (ip->step_exp, ip->step_exp,
579 integer_zero_node, NULL_TREE);
581 else if (compare_int_csts (LE_EXPR, ip->step_exp, integer_zero_node))
583 error ("BY expression is negative or zero");
590 ip->error_flag = 0; /* no errors! */
594 build_loop_start (while_control, start_label)
595 tree while_control, start_label;
597 ITERATOR *firstp = loop_stack->iter_list;
599 firstp->condition = while_control;
601 if (firstp->error_flag)
604 /* We didn't know at begin_loop_scope time about the condition;
605 adjust iterator type now. */
606 if (firstp->itype == DO_OD && firstp->condition)
607 firstp->itype = DO_WHILE;
609 if (initialize_iter_var ())
612 if (maybe_skip_loop ())
615 /* use the label as an 'exit' label,
616 'goto' needs another sort of label */
617 expand_start_loop (start_label != NULL_TREE);
619 if (top_loop_end_check ())
621 emit_line_note (input_filename, lineno);
625 * Called after the last action of the loop body
631 ITERATOR *ip = loop_stack->iter_list;
633 emit_line_note (input_filename, lineno);
638 if (bottom_loop_end_check ())
641 if (increment_temps ())
644 if (ip->itype != DO_OD)
648 for (; ip != NULL; ip = ip->next)
664 * The rest of the routines in this file are called from
665 * the above three routines.
670 ITERATOR *firstp = loop_stack->iter_list, *ip;
672 firstp->error_flag = 0;
673 if (firstp->itype == DO_UNUSED || firstp->itype == DO_OD)
675 /* if we have just DO .. OD, do nothing - this is just a
676 BEGIN .. END without creating a new scope, and no looping */
677 if (firstp->condition != NULL_TREE)
678 firstp->itype = DO_WHILE;
680 firstp->itype = DO_OD;
683 /* Issue a warning if the any loop counter is mentioned more
684 than once in the iterator list. */
685 for (ip = firstp; ip != NULL; ip = ip->next)
697 /* FIXME: check for name uniqueness */
703 return firstp->error_flag;
707 * Reserve space for any loop-control temporaries, initialize them
712 ITERATOR *firstp = loop_stack->iter_list, *ip;
715 for (ip = firstp; ip != NULL; ip = ip->next)
723 ip->iter_type = chill_unsigned_type (TREE_TYPE (ip->start_exp));
725 /* create, initialize temporaries if expressions aren't constant */
726 ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start",
728 ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end",
730 /* this is just the step-expression */
731 ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step",
736 ip->iter_type = chill_unsigned_type_node;
739 (ip->down_flag ? build_chill_upper : build_chill_lower)(TREE_TYPE (ip->start_exp));
741 (ip->down_flag ? build_chill_lower : build_chill_upper)(TREE_TYPE (ip->start_exp));
743 ip->step_temp = integer_one_node;
746 if (flag_local_loop_counter)
748 /* (re-)declare the user's iteration variable in the
750 tree id_node = ip->user_var;
751 IDENTIFIER_LOCAL_VALUE (id_node) = ip->user_var =
752 decl_temp1 (id_node, ip->iter_type, 0, NULL_TREE,
757 /* in this case, it's a previously-declared
758 VAR_DECL node, checked in build_loop_iterator. */
759 if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
760 ip->user_var = lookup_name (ip->user_var);
761 if (ip->user_var == NULL_TREE)
763 error ("loop identifier undeclared");
769 decl_temp1 (get_unique_identifier ("iter_var"),
770 ip->iter_type, 0, NULL_TREE, 0, 0);
774 ip->iter_type = chill_unsigned_type (
775 TYPE_DOMAIN (TREE_TYPE (ip->start_exp)));
776 if (flag_local_loop_counter)
778 /* declare the user's iteration variable in the loop's scope. */
779 /* in this case, it's just an IDENTIFIER_NODE */
781 decl_temp1 (ip->user_var, ip->iter_type, 0, NULL_TREE, 0, 0);
785 /* in this case, it's a previously-declared VAR_DECL node */
786 ip->user_var = lookup_name (ip->user_var);
788 /* the user's powerset-expression, evaluated and saved in a temp */
789 ip->powerset_temp = maybe_make_for_temp (ip->start_exp, "for_set",
790 TREE_TYPE (ip->start_exp));
791 mark_addressable (ip->powerset_temp);
796 ip->iter_type = chill_unsigned_type_node;
797 /* create the counter temp */
799 build_temporary_variable ("iter_var", ip->iter_type);
801 if (!CH_LOCATION_P (ip->start_exp))
803 = decl_temp1 (get_unique_identifier ("iter_loc"),
804 TREE_TYPE (ip->start_exp), 0,
805 ip->start_exp, 0, 0);
807 if (ip->itype == DO_LOC)
809 tree array_type = TREE_TYPE (ip->start_exp);
813 if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
815 error ("Can't iterate through array of BOOL");
817 return ip->error_flag;
820 /* FIXME: check for array type in ip->start_exp */
822 /* create pointer temporary */
823 ip->base_type = TREE_TYPE (array_type);
824 ptr_type = build_pointer_type (ip->base_type);
826 build_temporary_variable ("loc_ptr_tmp", ptr_type);
828 /* declare the user's iteration variable in
829 the loop's scope, as an expression, to be
830 passed to build_component_ref later */
831 save_expr_under_name (ip->user_var,
832 build1 (INDIRECT_REF, ip->base_type,
835 /* FIXME: see stor_layout */
836 ip->step_temp = size_in_bytes (ip->base_type);
838 temp = TYPE_DOMAIN (array_type);
840 /* pointer to first array entry to look at */
841 start_ptr = build1 (ADDR_EXPR, ptr_type, ip->start_exp);
842 mark_addressable (ip->start_exp);
843 ip->start_temp = ip->down_flag ?
844 fold (build (PLUS_EXPR, ptr_type,
846 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
847 fold (build (MINUS_EXPR, integer_type_node,
848 TYPE_MAX_VALUE (temp),
849 TYPE_MIN_VALUE (temp)))))))
855 convert (integer_type_node,
856 build_component_ref (ip->start_exp, var_length_id));
857 tree array_type = TREE_TYPE (TREE_CHAIN (
858 TYPE_FIELDS (TREE_TYPE (ip->start_exp))));
859 tree array_data_ptr =
860 build_component_ref (ip->start_exp, var_data_id);
863 if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
865 error ("Can't iterate through array of BOOL");
866 firstp->error_flag = 1;
867 return firstp->error_flag;
870 /* create pointer temporary */
871 ip->base_type = TREE_TYPE (array_type);
872 ptr_type = build_pointer_type (ip->base_type);
874 build_temporary_variable ("loc_ptr_temp", ptr_type);
877 /* declare the user's iteration variable in
878 the loop's scope, as an expression, to be
879 passed to build_component_ref later */
880 save_expr_under_name (ip->user_var,
881 build1 (INDIRECT_REF, ip->base_type,
884 /* FIXME: see stor_layout */
885 ip->step_temp = size_in_bytes (ip->base_type);
887 /* pointer to first array entry to look at */
888 start_ptr = build1 (ADDR_EXPR, ptr_type, array_data_ptr);
889 mark_addressable (array_data_ptr);
890 ip->start_temp = ip->down_flag ?
891 fold (build (PLUS_EXPR, ptr_type,
893 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
894 fold (build (MINUS_EXPR, integer_type_node,
896 integer_one_node))))))
903 return firstp->error_flag;
907 * Initialize the hidden iteration-control variables,
908 * and the user's explicit loop variable.
911 initialize_iter_var ()
913 ITERATOR *firstp = loop_stack->iter_list, *ip;
915 for (ip = firstp; ip != NULL; ip = ip->next)
926 fold (build (PLUS_EXPR, ip->iter_type, integer_one_node,
927 fold (build (TRUNC_DIV_EXPR, ip->iter_type,
928 convert (ip->iter_type,
929 fold (build (MINUS_EXPR, ip->iter_type,
930 ip->down_flag ? ip->start_temp : ip->end_temp,
931 ip->down_flag ? ip->end_temp : ip->start_temp))),
933 /* initialize the loop's hidden counter variable */
935 build_chill_modify_expr (ip->iter_var, count));
937 /* initialize user's variable */
939 build_chill_modify_expr (ip->user_var, ip->start_temp));
946 tree array_type = TREE_TYPE (ip->start_exp);
948 fold (build (TRUNC_DIV_EXPR, integer_type_node,
949 size_in_bytes (array_type),
950 size_in_bytes (TREE_TYPE (array_type))));
953 build_chill_modify_expr (ip->iter_var, array_length));
959 build_chill_modify_expr (ip->iter_var,
960 convert (integer_type_node,
961 build_component_ref (ip->start_exp, var_length_id))));
965 build_chill_modify_expr (ip->loc_ptr_temp,
973 return firstp->error_flag;
976 /* Generate code to skip the whole loop, if start expression not
977 * <= end expression (or >= for DOWN loops). This comparison must
978 * *NOT* be done in unsigned mode, or it will fail.
979 * Also, skip processing an empty VARYING array.
984 ITERATOR *firstp = loop_stack->iter_list, *ip;
986 for (ip = firstp; ip != NULL; ip = ip->next)
992 build (ip->down_flag ? GE_EXPR : LE_EXPR,
993 TREE_TYPE (ip->start_exp),
994 ip->start_exp, ip->end_exp), 0);
998 { tree array_length =
999 convert (integer_type_node,
1000 build_component_ref (ip->start_exp, var_length_id));
1002 build (NE_EXPR, TREE_TYPE (array_length),
1003 array_length, integer_zero_node), 0);
1014 * Check at the top of the loop for a termination
1017 top_loop_end_check ()
1019 ITERATOR *firstp = loop_stack->iter_list, *ip;
1021 /* now, exit the loop if the condition isn't TRUE. */
1022 if (firstp->condition)
1024 expand_exit_loop_if_false (0,
1025 chill_truthvalue_conversion (firstp->condition));
1028 for (ip = firstp; ip != NULL; ip = ip->next)
1043 func_name = "__flsetclrpowerset";
1045 func_name = "__ffsetclrpowerset";
1047 temp1 = TYPE_MIN_VALUE
1048 (TYPE_DOMAIN (TREE_TYPE (ip->powerset_temp)));
1049 expand_exit_loop_if_false (0,
1050 build_chill_function_call (lookup_name (get_identifier (func_name)),
1051 tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp),
1052 tree_cons (NULL_TREE, powersetlen (ip->powerset_temp),
1053 tree_cons (NULL_TREE, force_addr_of (ip->user_var),
1054 tree_cons (NULL_TREE, size_in_bytes (TREE_TYPE (ip->user_var)),
1055 tree_cons (NULL_TREE,
1056 convert (long_integer_type_node, temp1),
1061 case DO_LOC_VARYING:
1067 return firstp->error_flag;
1071 * Check generated temporaries for loop's end
1074 bottom_loop_end_check ()
1076 ITERATOR *firstp = loop_stack->iter_list, *ip;
1078 emit_line_note (input_filename, lineno);
1080 /* now, generate code to check each loop counter for termination */
1081 for (ip = firstp; ip != NULL; ip = ip->next)
1091 case DO_LOC_VARYING:
1092 /* decrement iteration counter by one */
1093 chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
1094 /* exit if it's zero */
1095 expand_exit_loop_if_false (0,
1096 build (NE_EXPR, boolean_type_node,
1098 integer_zero_node));
1107 return firstp->error_flag;
1111 * increment the loop-control variables.
1116 ITERATOR *firstp = loop_stack->iter_list, *ip;
1118 for (ip = firstp; ip != NULL; ip = ip->next)
1129 fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1130 TREE_TYPE (ip->user_var), ip->user_var,
1133 build_chill_modify_expr (ip->user_var, delta));
1137 case DO_LOC_VARYING:
1138 /* This statement uses the C semantics, so that
1139 the pointer is actually incremented by the
1140 length of the object pointed to. */
1143 build_modify_expr (ip->loc_ptr_temp,
1144 ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1148 enum tree_code op = ip->down_flag ? MINUS_EXPR : PLUS_EXPR;
1149 tree el_type = TREE_TYPE (TREE_TYPE (ip->loc_ptr_temp));
1150 chill_expand_assignment (ip->loc_ptr_temp, NOP_EXPR,
1152 TREE_TYPE (ip->loc_ptr_temp),
1154 size_in_bytes (el_type)));
1164 return firstp->error_flag;
1168 * Generate a (temporary) unique identifier_node of
1169 * the form "__tmp_%s_%d"
1172 get_unique_identifier (lead)
1176 static int idcount = 0;
1178 sprintf (idbuf, "__tmp_%s_%d", lead ? lead : "", idcount++);
1179 return get_identifier (idbuf);
1183 * build a temporary variable, given its NAME and TYPE.
1184 * The name will have a number appended to assure uniqueness.
1185 * return its DECL node.
1188 build_temporary_variable (name, type)
1192 return decl_temp1 (get_unique_identifier (name), type, 0, NULL_TREE, 0, 0);
1197 * If the given expression isn't a constant, build a temp for it
1198 * and evaluate the expression into the temp. Return the tree
1199 * representing either the original constant expression or the
1200 * temp which now contains the expression's value.
1203 maybe_make_for_temp (exp, temp_name, exp_type)
1210 if (exp != NULL_TREE)
1212 /* if exp isn't constant, create a temporary for its value */
1213 if (TREE_CONSTANT (exp))
1215 /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */
1216 result = convert (exp_type, exp);
1219 /* build temp, assign the value */
1220 result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0,
1229 * Adapt the C unsigned_type function to CHILL - we need to
1230 * account for any CHILL-specific integer types here. So far,
1231 * the 16-bit integer type is the only one.
1234 chill_unsigned_type (type)
1237 extern tree chill_unsigned_type_node;
1238 tree type1 = TYPE_MAIN_VARIANT (type);
1240 if (type1 == chill_integer_type_node)
1241 return chill_unsigned_type_node;
1243 return unsigned_type (type);