1 /* Implement looping actions for CHILL.
2 Copyright (C) 1992, 93, 94, 2000 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 = 0;
38 extern tree chill_truthvalue_conversion PARAMS ((tree));
39 extern rtx emit_line_note PARAMS ((char *, int));
40 extern void error PARAMS ((char *, ...));
41 extern rtx expand_assignment PARAMS ((tree, tree, int, int));
42 extern void save_expr_under_name PARAMS ((tree, tree));
43 extern void stamp_nesting_label PARAMS ((tree));
44 extern int int_fits_type_p PARAMS ((tree, tree));
45 extern void warning PARAMS ((char *, ...));
47 /* forward declarations */
48 static int classify_loop PARAMS ((void));
49 static int declare_temps PARAMS ((void));
50 static int initialize_iter_var PARAMS ((void));
51 static int maybe_skip_loop PARAMS ((void));
52 static int top_loop_end_check PARAMS ((void));
53 static int bottom_loop_end_check PARAMS ((void));
54 static int increment_temps PARAMS ((void));
55 static tree build_temporary_variable PARAMS ((char *, tree));
56 static tree maybe_make_for_temp PARAMS ((tree, char *, tree));
57 static tree chill_unsigned_type PARAMS ((tree));
59 /* In terms of the parameters passed to build_loop_iterator,
60 * there are several types of loops. They are encoded by
61 * the ITER_TYPE enumeration.
63 * 1) DO FOR EVER; ... OD
64 * indicated by a NULL_TREE start_exp, step_exp and end_exp,
65 * condition == NULL, in_flag = 0, and ever_flag == 1 in the
68 * 2) DO WHILE cond; ... OD
69 * indicated by NULL_TREE start_exp, step_exp and end_exp,
70 * in_flag = 0, and condition != NULL.
73 * indicated by NULL_TREEs in start_exp, step_exp and end_exp,
74 * condition != NULL, in_flag == 0 and ever_flag == 0. This
75 * is not really a loop, but a compound statement.
77 * 4) DO FOR user_var := start_exp
78 * [DOWN] TO end_exp BY step_exp; ... DO
79 * indicated by non-NULL_TREE start_exp, step_exp and end_exp.
81 * 5) DO FOR user_var [DOWN] IN discrete_mode; ... OD
82 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
83 * discrete mode, with an optional down_flag.
85 * 6) DO FOR user_var [DOWN] IN powerset_expr; ... OD
86 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
87 * powerset mode, with an optional down_flag.
89 * 7) DO FOR user_var [DOWN] IN location; ... OD
90 * indicated by in_flag == 1. start_exp is a non-NULL_TREE
91 * location mode, with an optional down_flag.
107 typedef struct iterator
109 /* These variables only have meaning in the first ITERATOR structure. */
110 ITER_TYPE itype; /* type of this iterator */
111 int error_flag; /* TRUE if no loop was started due to
113 tree condition; /* WHILE condition expression */
114 int down_flag; /* TRUE if DOWN was coded */
116 /* These variables have meaning in every ITERATOR structure. */
117 tree user_var; /* user's explicit iteration variable */
118 tree start_exp; /* user's start expression
119 or IN expression of a FOR .. IN*/
120 tree step_exp; /* user's step expression */
121 tree end_exp; /* user's end expression */
122 tree start_temp; /* temp holding evaluated start_exp */
123 tree end_temp; /* temp holding evaluated end_exp */
124 tree step_temp; /* temp holding evaluated step_exp */
125 tree powerset_temp; /* temp holding user's initial powerset expression */
126 tree loc_ptr_temp; /* temp holding count for LOC enumeration ptr */
127 tree iter_var; /* hidden variable for the loop */
128 tree iter_type; /* hidden variable's type */
129 tree base_type; /* LOC enumeration base type */
130 struct iterator *next; /* ptr to next iterator for this loop */
134 * There's an entry like this for each nested DO loop.
135 * The list is maintained by push_loop_block
136 * and pop_loop_block.
138 typedef struct loop {
139 struct loop *nxt_level; /* pointer to enclosing loop */
140 ITERATOR *iter_list; /* iterators for the current loop */
143 static LOOP *loop_stack = (LOOP *)0;
147 Here is a CHILL DO FOR statement:
149 DO FOR user_var := start_exp BY step_exp [DOWN] TO end_exp
152 For this loop to be 'safe', like a Pascal FOR loop, the start,
153 end, and increment expressions are computed once, before the
154 assignment to the iteration variable and saved in temporaries,
155 before the first assignment of the iteration variable, so the
158 FOR i := (i+1) TO (i+10) DO
160 To prevent changes to the start/end/step expressions from
161 effecting the loop''s termination, and to make the loop end-check
162 as simple as possible, we evaluate the step expression into
163 a temporary and compute a hidden iteration count before entering
164 the loop''s body. User code cannot effect the counter, and the
165 end-loop check simply decrements the counter and checks for zero.
167 The whole phrase FOR iter := ... TO end_exp can be repeated
168 multiple times, with different user-iteration variables. This
171 The loop counter calculations need careful design since a loop
172 from MININT TO MAXINT must work, in the precision of integers.
174 Here''s how it works, in C:
176 0) The DO ... OD loop is simply a block with
179 1) The DO FOR EVER is simply implemented:
188 2) The DO WHILE is also simple:
192 if (!condition) goto end_loop
200 3) The DO FOR [while condition] loop (no DOWN)
206 start_temp = start_exp
208 if (end_exp < start_exp) goto end_loop
209 /* following line is all unsigned arithmetic */
210 iter_var = (end_exp - start_exp + step_exp) / step_exp
211 user_var = start_temp
213 if (!condition) goto end_loop
218 if (iter_var == 0) goto end_loop
219 user_var += step_temp
224 4) The proposed CHILL for [while condition] loop (with DOWN)
229 start_temp = start_exp
231 if (end_exp > start_exp) goto end_loop
232 /* following line is all unsigned arithmetic */
233 iter_var = (start_exp - end_exp + step_exp) / step_exp
234 user_var = start_temp
236 if (!condition) goto end_loop
241 if (iter_var == 0) goto end_loop
242 user_var -= step_temp
248 5) The range loop, which iterates over a mode''s possible
249 values, works just like the above step loops, but with
250 the start and end values taken from the mode''s lower
251 and upper domain values.
254 6) The FOR IN loop, where a location enumeration is
255 specified (see spec on page 81 of Z.200, bottom
259 decl iter_var as an unsigned integer
260 loc_ptr_temp as pointer to a composite base type
263 iter_var = array''s length field
265 iter_var = sizeof array / sizeof base_type
266 loc_ptr_temp = &of highest or lowest indexable entry
268 if (!condition) goto end_loop
273 if (iter_var == 0) goto end_loop
274 loc_ptr_temp +/-= sizeof array base_type
279 7) The DO FOR (DOWN) IN powerset_exp
283 decl iterator as basetype of powerset
285 powerset_temp := start_exp
288 if (__flsetclrpowerset () == 0) goto end_loop;
290 if (__ffsetclrpowerset () == 0) goto end_loop;
291 if (!condition) goto end_loop
300 So, here''s the general DO FOR schema, as implemented here:
302 classify_loop -- what type of loop have we?
303 -- build_iterator does some of this, also
304 expand_start_loop -- start the loop''s control scope
305 -- start scope for synthesized loop variables
306 declare_temps -- create, initialize temporary variables
307 maybe_skip_loop -- skip loop if end conditions unsatisfiable
308 initialize_iter_var -- initialize the iteration counter
309 -- initialize user''s loop variable
310 expand_start_loop -- generate top-of-loop label
311 top_loop_end_check -- generate while code and/or
312 powerset find-a-bit function call
315 . user''s loop body code
318 bottom_loop_end_check -- exit if counter has become zero
319 increment_temps -- update temps for next iteration
320 expand_end_loop -- generate jump back to top of loop
321 expand_end_cond -- generate label for end of conditional
322 -- end of scope for synthesized loop variables
323 free_iterators -- free up iterator space
325 When there are two or more iterator phrases, each of the
326 above loop steps must act upon all iterators. For example,
327 the 'increment_temps' step must increment all temporaries
328 (associated with all iterators).
330 NOTE: Z.200, section 10.1 says that a block is ...
331 "the actions statement list in a do action, including any
332 loop counter and while control". This means that an exp-
333 ression in a WHILE control can include references to the
334 loop counters created for the loop''s exclusive use.
339 DO FOR j IN a WHILE j > 0;
342 The 'j' referenced in the while is the loc-identity 'j'
343 created inside the loop''s scope, and NOT the 'j' declared
348 * The following routines are called directly by the
354 LOOP *temp = (LOOP *)xmalloc (sizeof (LOOP));
356 /* push a new loop onto the stack */
357 temp->nxt_level = loop_stack;
358 temp->iter_list = (ITERATOR *)0;
365 LOOP *do_temp = loop_stack;
368 /* pop loop block off the list */
369 loop_stack = do_temp->nxt_level;
371 /* free the loop's iterator blocks */
372 ip = do_temp->iter_list;
375 ITERATOR *temp = ip->next;
385 ITERATOR *firstp = loop_stack->iter_list;
391 * We need to classify the loop and declare its temporaries
392 * here, so as to define them before the WHILE condition
393 * (if any) is parsed. The WHILE expression may refer to
396 if (classify_loop ())
399 if (firstp->itype != DO_OD)
404 expand_start_bindings (0);
409 end_loop_scope (opt_label)
413 possibly_define_exit_label (opt_label);
419 expand_end_bindings (getdecls (), kept_level_p (), 0);
423 /* The iterator structure records all aspects of a
424 * 'FOR i := start [DOWN] TO end' clause or
425 * 'FOR i IN modename' or 'FOR i IN powerset' clause.
426 * It's saved on the iter_list of the current LOOP.
429 build_loop_iterator (user_var, start_exp, step_exp, end_exp,
430 down_flag, in_flag, ever_flag)
431 tree user_var, start_exp, step_exp, end_exp;
432 int down_flag, in_flag, ever_flag;
434 ITERATOR *ip = (ITERATOR *)xmalloc (sizeof (ITERATOR));
436 /* chain this iterator onto the current loop */
437 if (loop_stack->iter_list == NULL)
438 loop_stack->iter_list = ip;
441 ITERATOR *temp = loop_stack->iter_list;
442 while (temp->next != NULL)
447 ip->itype = DO_UNUSED;
448 ip->user_var = user_var;
449 ip->start_exp = start_exp;
450 ip->step_exp = step_exp;
451 ip->end_exp = end_exp;
452 ip->condition = NULL_TREE;
453 ip->start_temp = NULL_TREE;
454 ip->end_temp = NULL_TREE;
455 ip->step_temp = NULL_TREE;
456 ip->down_flag = down_flag;
457 ip->powerset_temp = NULL_TREE;
458 ip->iter_var = NULL_TREE;
459 ip->iter_type = NULL_TREE;
460 ip->loc_ptr_temp = NULL_TREE;
461 ip->error_flag = 1; /* assume error will be found */
462 ip->next = (ITERATOR *)0;
465 ip->itype = DO_FOREVER;
466 else if (in_flag && start_exp != NULL_TREE)
468 if (TREE_CODE (start_exp) == ERROR_MARK)
470 if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE)
471 ip->itype = DO_POWERSET;
472 else if (discrete_type_p (TREE_TYPE (ip->start_exp)))
473 ip->itype = DO_RANGE;
474 else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE)
476 else if (chill_varying_type_p (TREE_TYPE (ip->start_exp)))
477 ip->itype = DO_LOC_VARYING;
480 error ("Loop's IN expression is not a composite object");
484 else if (start_exp == NULL_TREE && end_exp == NULL_TREE
485 && step_exp == NULL_TREE && !down_flag)
489 /* FIXME: Move this to the lexer? */
490 #define CST_FITS_INT(NODE) (TREE_CODE(NODE) == INTEGER_CST &&\
491 int_fits_type_p (NODE, integer_type_node))
493 tree max_prec_type = integer_type_node;
495 if (! discrete_type_p (TREE_TYPE (ip->start_exp)))
497 error ("start expr must have discrete mode");
500 if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ENUMERAL_TYPE
501 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->start_exp)))
503 error ("DO FOR start expression is a numbered SET");
506 if (TREE_CODE (TREE_TYPE (ip->end_exp)) == ENUMERAL_TYPE
507 && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->end_exp)))
509 error ("TO expression is a numbered SET");
512 /* Convert all three expressions to a common precision,
513 which is the largest precision they exhibit, but
514 INTEGER_CST nodes are built in the lexer as
515 long_integer_type nodes. We'll treat convert them to
516 integer_type_nodes if possible, for faster loop times. */
518 if (TYPE_PRECISION (max_prec_type) <
519 TYPE_PRECISION (TREE_TYPE (ip->start_exp))
520 && !CST_FITS_INT (ip->start_exp))
521 max_prec_type = TREE_TYPE (ip->start_exp);
522 if (! discrete_type_p (TREE_TYPE (ip->end_exp)))
524 error ("TO expr must have discrete mode");
527 if (! CH_COMPATIBLE (ip->start_exp,
528 TREE_TYPE (ip->end_exp)))
530 error ("start expr and TO expr must be compatible");
533 if (TYPE_PRECISION (max_prec_type) <
534 TYPE_PRECISION (TREE_TYPE (ip->end_exp))
535 && !CST_FITS_INT (ip->end_exp))
536 max_prec_type = TREE_TYPE (ip->end_exp);
537 if (ip->step_exp != NULL_TREE)
539 /* assure that default 'BY 1' gets a useful type */
540 if (ip->step_exp == integer_one_node)
541 ip->step_exp = convert (TREE_TYPE (ip->start_exp),
543 if (! discrete_type_p (TREE_TYPE (ip->step_exp)))
545 error ("BY expr must have discrete mode");
548 if (! CH_COMPATIBLE (ip->start_exp,
549 TREE_TYPE (ip->step_exp)))
551 error ("start expr and BY expr must be compatible");
554 if (TYPE_PRECISION (max_prec_type) <
555 TYPE_PRECISION (TREE_TYPE (ip->step_exp))
556 && !CST_FITS_INT (ip->step_exp))
557 max_prec_type = TREE_TYPE (ip->step_exp);
559 if (TREE_CODE (ip->start_exp) == INTEGER_CST
560 && TREE_CODE (ip->end_exp) == INTEGER_CST
561 && compare_int_csts (ip->down_flag ? LT_EXPR : GT_EXPR,
562 ip->start_exp, ip->end_exp))
563 warning ("body of DO FOR will never execute");
566 convert (max_prec_type, ip->start_exp);
568 convert (max_prec_type, ip->end_exp);
570 if (ip->step_exp != NULL_TREE)
573 convert (max_prec_type, ip->step_exp);
575 if (TREE_CODE (ip->step_exp) != INTEGER_CST)
577 /* generate runtime check for negative BY expr */
579 check_range (ip->step_exp, ip->step_exp,
580 integer_zero_node, NULL_TREE);
582 else if (compare_int_csts (LE_EXPR, ip->step_exp, integer_zero_node))
584 error ("BY expression is negative or zero");
591 ip->error_flag = 0; /* no errors! */
595 build_loop_start (while_control, start_label)
596 tree while_control, start_label;
598 ITERATOR *firstp = loop_stack->iter_list;
600 firstp->condition = while_control;
602 if (firstp->error_flag)
605 /* We didn't know at begin_loop_scope time about the condition;
606 adjust iterator type now. */
607 if (firstp->itype == DO_OD && firstp->condition)
608 firstp->itype = DO_WHILE;
610 if (initialize_iter_var ())
613 if (maybe_skip_loop ())
616 /* use the label as an 'exit' label,
617 'goto' needs another sort of label */
618 expand_start_loop (start_label != NULL_TREE);
620 if (top_loop_end_check ())
622 emit_line_note (input_filename, lineno);
626 * Called after the last action of the loop body
632 ITERATOR *ip = loop_stack->iter_list;
634 emit_line_note (input_filename, lineno);
639 if (bottom_loop_end_check ())
642 if (increment_temps ())
645 if (ip->itype != DO_OD)
649 for (; ip != NULL; ip = ip->next)
665 * The rest of the routines in this file are called from
666 * the above three routines.
671 ITERATOR *firstp = loop_stack->iter_list, *ip;
673 firstp->error_flag = 0;
674 if (firstp->itype == DO_UNUSED || firstp->itype == DO_OD)
676 /* if we have just DO .. OD, do nothing - this is just a
677 BEGIN .. END without creating a new scope, and no looping */
678 if (firstp->condition != NULL_TREE)
679 firstp->itype = DO_WHILE;
681 firstp->itype = DO_OD;
684 /* Issue a warning if the any loop counter is mentioned more
685 than once in the iterator list. */
686 for (ip = firstp; ip != NULL; ip = ip->next)
698 /* FIXME: check for name uniqueness */
704 return firstp->error_flag;
708 * Reserve space for any loop-control temporaries, initialize them
713 ITERATOR *firstp = loop_stack->iter_list, *ip;
716 for (ip = firstp; ip != NULL; ip = ip->next)
724 ip->iter_type = chill_unsigned_type (TREE_TYPE (ip->start_exp));
726 /* create, initialize temporaries if expressions aren't constant */
727 ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start",
729 ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end",
731 /* this is just the step-expression */
732 ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step",
737 ip->iter_type = chill_unsigned_type_node;
740 (ip->down_flag ? build_chill_upper : build_chill_lower)(TREE_TYPE (ip->start_exp));
742 (ip->down_flag ? build_chill_lower : build_chill_upper)(TREE_TYPE (ip->start_exp));
744 ip->step_temp = integer_one_node;
747 if (flag_local_loop_counter)
749 /* (re-)declare the user's iteration variable in the
751 tree id_node = ip->user_var;
752 IDENTIFIER_LOCAL_VALUE (id_node) = ip->user_var =
753 decl_temp1 (id_node, ip->iter_type, 0, NULL_TREE,
758 /* in this case, it's a previously-declared
759 VAR_DECL node, checked in build_loop_iterator. */
760 if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
761 ip->user_var = lookup_name (ip->user_var);
762 if (ip->user_var == NULL_TREE)
764 error ("loop identifier undeclared");
770 decl_temp1 (get_unique_identifier ("iter_var"),
771 ip->iter_type, 0, NULL_TREE, 0, 0);
775 ip->iter_type = chill_unsigned_type (
776 TYPE_DOMAIN (TREE_TYPE (ip->start_exp)));
777 if (flag_local_loop_counter)
779 /* declare the user's iteration variable in the loop's scope. */
780 /* in this case, it's just an IDENTIFIER_NODE */
782 decl_temp1 (ip->user_var, ip->iter_type, 0, NULL_TREE, 0, 0);
786 /* in this case, it's a previously-declared VAR_DECL node */
787 ip->user_var = lookup_name (ip->user_var);
789 /* the user's powerset-expression, evaluated and saved in a temp */
790 ip->powerset_temp = maybe_make_for_temp (ip->start_exp, "for_set",
791 TREE_TYPE (ip->start_exp));
792 mark_addressable (ip->powerset_temp);
797 ip->iter_type = chill_unsigned_type_node;
798 /* create the counter temp */
800 build_temporary_variable ("iter_var", ip->iter_type);
802 if (!CH_LOCATION_P (ip->start_exp))
804 = decl_temp1 (get_unique_identifier ("iter_loc"),
805 TREE_TYPE (ip->start_exp), 0,
806 ip->start_exp, 0, 0);
808 if (ip->itype == DO_LOC)
810 tree array_type = TREE_TYPE (ip->start_exp);
814 if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
816 error ("Can't iterate through array of BOOL");
818 return ip->error_flag;
821 /* FIXME: check for array type in ip->start_exp */
823 /* create pointer temporary */
824 ip->base_type = TREE_TYPE (array_type);
825 ptr_type = build_pointer_type (ip->base_type);
827 build_temporary_variable ("loc_ptr_tmp", ptr_type);
829 /* declare the user's iteration variable in
830 the loop's scope, as an expression, to be
831 passed to build_component_ref later */
832 save_expr_under_name (ip->user_var,
833 build1 (INDIRECT_REF, ip->base_type,
836 /* FIXME: see stor_layout */
837 ip->step_temp = size_in_bytes (ip->base_type);
839 temp = TYPE_DOMAIN (array_type);
841 /* pointer to first array entry to look at */
842 start_ptr = build1 (ADDR_EXPR, ptr_type, ip->start_exp);
843 mark_addressable (ip->start_exp);
844 ip->start_temp = ip->down_flag ?
845 fold (build (PLUS_EXPR, ptr_type,
847 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
848 fold (build (MINUS_EXPR, integer_type_node,
849 TYPE_MAX_VALUE (temp),
850 TYPE_MIN_VALUE (temp)))))))
856 convert (integer_type_node,
857 build_component_ref (ip->start_exp, var_length_id));
858 tree array_type = TREE_TYPE (TREE_CHAIN (
859 TYPE_FIELDS (TREE_TYPE (ip->start_exp))));
860 tree array_data_ptr =
861 build_component_ref (ip->start_exp, var_data_id);
864 if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
866 error ("Can't iterate through array of BOOL");
867 firstp->error_flag = 1;
868 return firstp->error_flag;
871 /* create pointer temporary */
872 ip->base_type = TREE_TYPE (array_type);
873 ptr_type = build_pointer_type (ip->base_type);
875 build_temporary_variable ("loc_ptr_temp", ptr_type);
878 /* declare the user's iteration variable in
879 the loop's scope, as an expression, to be
880 passed to build_component_ref later */
881 save_expr_under_name (ip->user_var,
882 build1 (INDIRECT_REF, ip->base_type,
885 /* FIXME: see stor_layout */
886 ip->step_temp = size_in_bytes (ip->base_type);
888 /* pointer to first array entry to look at */
889 start_ptr = build1 (ADDR_EXPR, ptr_type, array_data_ptr);
890 mark_addressable (array_data_ptr);
891 ip->start_temp = ip->down_flag ?
892 fold (build (PLUS_EXPR, ptr_type,
894 fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
895 fold (build (MINUS_EXPR, integer_type_node,
897 integer_one_node))))))
904 return firstp->error_flag;
908 * Initialize the hidden iteration-control variables,
909 * and the user's explicit loop variable.
912 initialize_iter_var ()
914 ITERATOR *firstp = loop_stack->iter_list, *ip;
916 for (ip = firstp; ip != NULL; ip = ip->next)
927 fold (build (PLUS_EXPR, ip->iter_type, integer_one_node,
928 fold (build (TRUNC_DIV_EXPR, ip->iter_type,
929 convert (ip->iter_type,
930 fold (build (MINUS_EXPR, ip->iter_type,
931 ip->down_flag ? ip->start_temp : ip->end_temp,
932 ip->down_flag ? ip->end_temp : ip->start_temp))),
934 /* initialize the loop's hidden counter variable */
936 build_chill_modify_expr (ip->iter_var, count));
938 /* initialize user's variable */
940 build_chill_modify_expr (ip->user_var, ip->start_temp));
947 tree array_type = TREE_TYPE (ip->start_exp);
949 fold (build (TRUNC_DIV_EXPR, integer_type_node,
950 size_in_bytes (array_type),
951 size_in_bytes (TREE_TYPE (array_type))));
954 build_chill_modify_expr (ip->iter_var, array_length));
960 build_chill_modify_expr (ip->iter_var,
961 convert (integer_type_node,
962 build_component_ref (ip->start_exp, var_length_id))));
966 build_chill_modify_expr (ip->loc_ptr_temp,
974 return firstp->error_flag;
977 /* Generate code to skip the whole loop, if start expression not
978 * <= end expression (or >= for DOWN loops). This comparison must
979 * *NOT* be done in unsigned mode, or it will fail.
980 * Also, skip processing an empty VARYING array.
985 ITERATOR *firstp = loop_stack->iter_list, *ip;
987 for (ip = firstp; ip != NULL; ip = ip->next)
993 build (ip->down_flag ? GE_EXPR : LE_EXPR,
994 TREE_TYPE (ip->start_exp),
995 ip->start_exp, ip->end_exp), 0);
999 { tree array_length =
1000 convert (integer_type_node,
1001 build_component_ref (ip->start_exp, var_length_id));
1003 build (NE_EXPR, TREE_TYPE (array_length),
1004 array_length, integer_zero_node), 0);
1015 * Check at the top of the loop for a termination
1018 top_loop_end_check ()
1020 ITERATOR *firstp = loop_stack->iter_list, *ip;
1022 /* now, exit the loop if the condition isn't TRUE. */
1023 if (firstp->condition)
1025 expand_exit_loop_if_false (0,
1026 chill_truthvalue_conversion (firstp->condition));
1029 for (ip = firstp; ip != NULL; ip = ip->next)
1044 func_name = "__flsetclrpowerset";
1046 func_name = "__ffsetclrpowerset";
1048 temp1 = TYPE_MIN_VALUE
1049 (TYPE_DOMAIN (TREE_TYPE (ip->powerset_temp)));
1050 expand_exit_loop_if_false (0,
1051 build_chill_function_call (lookup_name (get_identifier (func_name)),
1052 tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp),
1053 tree_cons (NULL_TREE, powersetlen (ip->powerset_temp),
1054 tree_cons (NULL_TREE, force_addr_of (ip->user_var),
1055 tree_cons (NULL_TREE, size_in_bytes (TREE_TYPE (ip->user_var)),
1056 tree_cons (NULL_TREE,
1057 convert (long_integer_type_node, temp1),
1062 case DO_LOC_VARYING:
1068 return firstp->error_flag;
1072 * Check generated temporaries for loop's end
1075 bottom_loop_end_check ()
1077 ITERATOR *firstp = loop_stack->iter_list, *ip;
1079 emit_line_note (input_filename, lineno);
1081 /* now, generate code to check each loop counter for termination */
1082 for (ip = firstp; ip != NULL; ip = ip->next)
1092 case DO_LOC_VARYING:
1093 /* decrement iteration counter by one */
1094 chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
1095 /* exit if it's zero */
1096 expand_exit_loop_if_false (0,
1097 build (NE_EXPR, boolean_type_node,
1099 integer_zero_node));
1108 return firstp->error_flag;
1112 * increment the loop-control variables.
1117 ITERATOR *firstp = loop_stack->iter_list, *ip;
1119 for (ip = firstp; ip != NULL; ip = ip->next)
1130 fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1131 TREE_TYPE (ip->user_var), ip->user_var,
1134 build_chill_modify_expr (ip->user_var, delta));
1138 case DO_LOC_VARYING:
1139 /* This statement uses the C semantics, so that
1140 the pointer is actually incremented by the
1141 length of the object pointed to. */
1144 build_modify_expr (ip->loc_ptr_temp,
1145 ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
1149 enum tree_code op = ip->down_flag ? MINUS_EXPR : PLUS_EXPR;
1150 tree el_type = TREE_TYPE (TREE_TYPE (ip->loc_ptr_temp));
1151 chill_expand_assignment (ip->loc_ptr_temp, NOP_EXPR,
1153 TREE_TYPE (ip->loc_ptr_temp),
1155 size_in_bytes (el_type)));
1165 return firstp->error_flag;
1169 * Generate a (temporary) unique identifier_node of
1170 * the form "__tmp_%s_%d"
1173 get_unique_identifier (lead)
1177 static int idcount = 0;
1179 sprintf (idbuf, "__tmp_%s_%d", lead ? lead : "", idcount++);
1180 return get_identifier (idbuf);
1184 * build a temporary variable, given its NAME and TYPE.
1185 * The name will have a number appended to assure uniqueness.
1186 * return its DECL node.
1189 build_temporary_variable (name, type)
1193 return decl_temp1 (get_unique_identifier (name), type, 0, NULL_TREE, 0, 0);
1198 * If the given expression isn't a constant, build a temp for it
1199 * and evaluate the expression into the temp. Return the tree
1200 * representing either the original constant expression or the
1201 * temp which now contains the expression's value.
1204 maybe_make_for_temp (exp, temp_name, exp_type)
1211 if (exp != NULL_TREE)
1213 /* if exp isn't constant, create a temporary for its value */
1214 if (TREE_CONSTANT (exp))
1216 /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */
1217 result = convert (exp_type, exp);
1220 /* build temp, assign the value */
1221 result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0,
1230 * Adapt the C unsigned_type function to CHILL - we need to
1231 * account for any CHILL-specific integer types here. So far,
1232 * the 16-bit integer type is the only one.
1235 chill_unsigned_type (type)
1238 extern tree chill_unsigned_type_node;
1239 tree type1 = TYPE_MAIN_VARIANT (type);
1241 if (type1 == chill_integer_type_node)
1242 return chill_unsigned_type_node;
1244 return unsigned_type (type);