aboutsummaryrefslogtreecommitdiff
path: root/gcc/ch/nloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ch/nloop.c')
-rw-r--r--gcc/ch/nloop.c1246
1 files changed, 0 insertions, 1246 deletions
diff --git a/gcc/ch/nloop.c b/gcc/ch/nloop.c
deleted file mode 100644
index 2a7a4600fad..00000000000
--- a/gcc/ch/nloop.c
+++ /dev/null
@@ -1,1246 +0,0 @@
-/* Implement looping actions for CHILL.
- Copyright (C) 1992, 1993, 1994, 2000
- Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <stdio.h>
-#include <limits.h>
-#include "config.h"
-#include "tree.h"
-#include "ch-tree.h"
-#include "lex.h"
-#include "flags.h"
-#include "actions.h"
-#include "input.h"
-#include "obstack.h"
-#include "assert.h"
-#include "rtl.h"
-
-/* if the user codes '-flocal-loop-counter' on the command line,
- ch-actions.c (lang_decode_option) will set this flag. */
-int flag_local_loop_counter = 0;
-
-extern tree chill_truthvalue_conversion PARAMS ((tree));
-extern rtx emit_line_note PARAMS ((char *, int));
-extern void error PARAMS ((char *, ...));
-extern rtx expand_assignment PARAMS ((tree, tree, int, int));
-extern void save_expr_under_name PARAMS ((tree, tree));
-extern void stamp_nesting_label PARAMS ((tree));
-extern int int_fits_type_p PARAMS ((tree, tree));
-extern void warning PARAMS ((char *, ...));
-
-/* forward declarations */
-static int classify_loop PARAMS ((void));
-static int declare_temps PARAMS ((void));
-static int initialize_iter_var PARAMS ((void));
-static int maybe_skip_loop PARAMS ((void));
-static int top_loop_end_check PARAMS ((void));
-static int bottom_loop_end_check PARAMS ((void));
-static int increment_temps PARAMS ((void));
-static tree build_temporary_variable PARAMS ((char *, tree));
-static tree maybe_make_for_temp PARAMS ((tree, char *, tree));
-static tree chill_unsigned_type PARAMS ((tree));
-
-/* In terms of the parameters passed to build_loop_iterator,
- * there are several types of loops. They are encoded by
- * the ITER_TYPE enumeration.
- *
- * 1) DO FOR EVER; ... OD
- * indicated by a NULL_TREE start_exp, step_exp and end_exp,
- * condition == NULL, in_flag = 0, and ever_flag == 1 in the
- * first ITERATOR.
- *
- * 2) DO WHILE cond; ... OD
- * indicated by NULL_TREE start_exp, step_exp and end_exp,
- * in_flag = 0, and condition != NULL.
- *
- * 3) DO; ... OD
- * indicated by NULL_TREEs in start_exp, step_exp and end_exp,
- * condition != NULL, in_flag == 0 and ever_flag == 0. This
- * is not really a loop, but a compound statement.
- *
- * 4) DO FOR user_var := start_exp
- * [DOWN] TO end_exp BY step_exp; ... DO
- * indicated by non-NULL_TREE start_exp, step_exp and end_exp.
- *
- * 5) DO FOR user_var [DOWN] IN discrete_mode; ... OD
- * indicated by in_flag == 1. start_exp is a non-NULL_TREE
- * discrete mode, with an optional down_flag.
- *
- * 6) DO FOR user_var [DOWN] IN powerset_expr; ... OD
- * indicated by in_flag == 1. start_exp is a non-NULL_TREE
- * powerset mode, with an optional down_flag.
- *
- * 7) DO FOR user_var [DOWN] IN location; ... OD
- * indicated by in_flag == 1. start_exp is a non-NULL_TREE
- * location mode, with an optional down_flag.
- */
-typedef enum
-{
- DO_UNUSED,
- DO_FOREVER,
- DO_WHILE,
- DO_OD,
- DO_STEP,
- DO_RANGE,
- DO_POWERSET,
- DO_LOC,
- DO_LOC_VARYING
-} ITER_TYPE;
-
-
-typedef struct iterator
-{
-/* These variables only have meaning in the first ITERATOR structure. */
- ITER_TYPE itype; /* type of this iterator */
- int error_flag; /* TRUE if no loop was started due to
- user error */
- tree condition; /* WHILE condition expression */
- int down_flag; /* TRUE if DOWN was coded */
-
-/* These variables have meaning in every ITERATOR structure. */
- tree user_var; /* user's explicit iteration variable */
- tree start_exp; /* user's start expression
- or IN expression of a FOR .. IN*/
- tree step_exp; /* user's step expression */
- tree end_exp; /* user's end expression */
- tree start_temp; /* temp holding evaluated start_exp */
- tree end_temp; /* temp holding evaluated end_exp */
- tree step_temp; /* temp holding evaluated step_exp */
- tree powerset_temp; /* temp holding user's initial powerset expression */
- tree loc_ptr_temp; /* temp holding count for LOC enumeration ptr */
- tree iter_var; /* hidden variable for the loop */
- tree iter_type; /* hidden variable's type */
- tree base_type; /* LOC enumeration base type */
- struct iterator *next; /* ptr to next iterator for this loop */
-} ITERATOR;
-
-/*
- * There's an entry like this for each nested DO loop.
- * The list is maintained by push_loop_block
- * and pop_loop_block.
- */
-typedef struct loop {
- struct loop *nxt_level; /* pointer to enclosing loop */
- ITERATOR *iter_list; /* iterators for the current loop */
-} LOOP;
-
-static LOOP *loop_stack = (LOOP *)0;
-
-/*
-
-Here is a CHILL DO FOR statement:
-
-DO FOR user_var := start_exp BY step_exp [DOWN] TO end_exp
- WHILE condition;
-
-For this loop to be 'safe', like a Pascal FOR loop, the start,
-end, and increment expressions are computed once, before the
-assignment to the iteration variable and saved in temporaries,
-before the first assignment of the iteration variable, so the
-following works:
-
- FOR i := (i+1) TO (i+10) DO
-
-To prevent changes to the start/end/step expressions from
-effecting the loop's termination, and to make the loop end-check
-as simple as possible, we evaluate the step expression into
-a temporary and compute a hidden iteration count before entering
-the loop's body. User code cannot effect the counter, and the
-end-loop check simply decrements the counter and checks for zero.
-
-The whole phrase FOR iter := ... TO end_exp can be repeated
-multiple times, with different user-iteration variables. This
-is discussed later.
-
-The loop counter calculations need careful design since a loop
-from MININT TO MAXINT must work, in the precision of integers.
-
-Here's how it works, in C:
-
- 0) The DO ... OD loop is simply a block with
- its own scope.
-
- 1) The DO FOR EVER is simply implemented:
-
- loop_top:
- .
- . body of loop
- .
- goto loop_top
- end_loop:
-
- 2) The DO WHILE is also simple:
-
-
- loop_top:
- if (!condition) goto end_loop
- .
- . body of loop
- .
- goto loop_top
- end_loop:
-
-
- 3) The DO FOR [while condition] loop (no DOWN)
-
- push a new scope,
- decl iter_var
-
- step_temp = step_exp
- start_temp = start_exp
- end_temp = end_exp
- if (end_exp < start_exp) goto end_loop
- // following line is all unsigned arithmetic
- iter_var = (end_exp - start_exp + step_exp) / step_exp
- user_var = start_temp
- loop_top:
- if (!condition) goto end_loop
- .
- . body of loop
- .
- iter_var--
- if (iter_var == 0) goto end_loop
- user_var += step_temp
- goto loop_top
- end_loop:
- pop scope
-
- 4) The proposed CHILL for [while condition] loop (with DOWN)
-
- push a new scope,
- decl iter
- step_temp = step_exp
- start_temp = start_exp
- end_temp = end_exp
- if (end_exp > start_exp) goto end_loop
- // following line is all unsigned arithmetic
- iter_var = (start_exp - end_exp + step_exp) / step_exp
- user_var = start_temp
- loop_top:
- if (!condition) goto end_loop
- .
- . body of loop
- .
- iter_var--
- if (iter_var == 0) goto end_loop
- user_var -= step_temp
- goto loop_top
- end_loop:
- pop scope
-
-
- 5) The range loop, which iterates over a mode's possible
- values, works just like the above step loops, but with
- the start and end values taken from the mode's lower
- and upper domain values.
-
-
- 6) The FOR IN loop, where a location enumeration is
- specified (see spec on page 81 of Z.200, bottom
- of page 186):
-
- push a new scope,
- decl iter_var as an unsigned integer
- loc_ptr_temp as pointer to a composite base type
-
- if array is varying
- iter_var = array's length field
- else
- iter_var = sizeof array / sizeof base_type
- loc_ptr_temp = &of highest or lowest indexable entry
- loop_top:
- if (!condition) goto end_loop
- .
- . body of loop
- .
- iter_var--
- if (iter_var == 0) goto end_loop
- loc_ptr_temp +/-= sizeof array base_type
- goto loop_top
- end_loop:
- pop scope
-
- 7) The DO FOR (DOWN) IN powerset_exp
-
- push a new scope,
- decl powerset_temp
- decl iterator as basetype of powerset
-
- powerset_temp := start_exp
- loop_top:
- // if DOWN
- if (__flsetclrpowerset () == 0) goto end_loop;
- // not DOWN
- if (__ffsetclrpowerset () == 0) goto end_loop;
- if (!condition) goto end_loop
- .
- . body of loop
- .
- goto loop_top
- end_loop:
- pop scope
-
-
-So, here's the general DO FOR schema, as implemented here:
-
- classify_loop -- what type of loop have we?
- -- build_iterator does some of this, also
- expand_start_loop -- start the loop's control scope
- -- start scope for synthesized loop variables
- declare_temps -- create, initialize temporary variables
- maybe_skip_loop -- skip loop if end conditions unsatisfiable
- initialize_iter_var -- initialize the iteration counter
- -- initialize user's loop variable
- expand_start_loop -- generate top-of-loop label
- top_loop_end_check -- generate while code and/or
- powerset find-a-bit function call
- .
- .
- . user's loop body code
- .
- .
- bottom_loop_end_check -- exit if counter has become zero
- increment_temps -- update temps for next iteration
- expand_end_loop -- generate jump back to top of loop
- expand_end_cond -- generate label for end of conditional
- -- end of scope for synthesized loop variables
- free_iterators -- free up iterator space
-
-When there are two or more iterator phrases, each of the
-above loop steps must act upon all iterators. For example,
-the 'increment_temps' step must increment all temporaries
-(associated with all iterators).
-
- NOTE: Z.200, section 10.1 says that a block is ...
- "the actions statement list in a do action, including any
- loop counter and while control". This means that an exp-
- ression in a WHILE control can include references to the
- loop counters created for the loop's exclusive use.
- Example:
-
- DCL a (1:10) INT;
- DCL j INT;
- DO FOR j IN a WHILE j > 0;
- ...
- OD;
- The 'j' referenced in the while is the loc-identity 'j'
- created inside the loop's scope, and NOT the 'j' declared
- before the loop.
-*/
-
-/*
- * The following routines are called directly by the
- * CHILL parser.
- */
-void
-push_loop_block ()
-{
- LOOP *temp = (LOOP *)xmalloc (sizeof (LOOP));
-
- /* push a new loop onto the stack */
- temp->nxt_level = loop_stack;
- temp->iter_list = (ITERATOR *)0;
- loop_stack = temp;
-}
-
-void
-pop_loop_block ()
-{
- LOOP *do_temp = loop_stack;
- ITERATOR *ip;
-
- /* pop loop block off the list */
- loop_stack = do_temp->nxt_level;
-
- /* free the loop's iterator blocks */
- ip = do_temp->iter_list;
- while (ip != NULL)
- {
- ITERATOR *temp = ip->next;
- free (ip);
- ip = temp;
- }
- free (do_temp);
-}
-
-void
-begin_loop_scope ()
-{
- ITERATOR *firstp = loop_stack->iter_list;
-
- if (pass < 2)
- return;
-
- /*
- * We need to classify the loop and declare its temporaries
- * here, so as to define them before the WHILE condition
- * (if any) is parsed. The WHILE expression may refer to
- * a temporary.
- */
- if (classify_loop ())
- return;
-
- if (firstp->itype != DO_OD)
- declare_temps ();
-
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-}
-
-
-void
-end_loop_scope (opt_label)
- tree opt_label;
-{
- if (opt_label)
- possibly_define_exit_label (opt_label);
- poplevel (0, 0, 0);
-
- if (pass < 2)
- return;
-
- expand_end_bindings (getdecls (), kept_level_p (), 0);
- pop_momentary ();
-}
-
-/* The iterator structure records all aspects of a
- * 'FOR i := start [DOWN] TO end' clause or
- * 'FOR i IN modename' or 'FOR i IN powerset' clause.
- * It's saved on the iter_list of the current LOOP.
- */
-void
-build_loop_iterator (user_var, start_exp, step_exp, end_exp,
- down_flag, in_flag, ever_flag)
- tree user_var, start_exp, step_exp, end_exp;
- int down_flag, in_flag, ever_flag;
-{
- ITERATOR *ip = (ITERATOR *)xmalloc (sizeof (ITERATOR));
-
- /* chain this iterator onto the current loop */
- if (loop_stack->iter_list == NULL)
- loop_stack->iter_list = ip;
- else
- {
- ITERATOR *temp = loop_stack->iter_list;
- while (temp->next != NULL)
- temp = temp->next;
- temp->next = ip;
- }
-
- ip->itype = DO_UNUSED;
- ip->user_var = user_var;
- ip->start_exp = start_exp;
- ip->step_exp = step_exp;
- ip->end_exp = end_exp;
- ip->condition = NULL_TREE;
- ip->start_temp = NULL_TREE;
- ip->end_temp = NULL_TREE;
- ip->step_temp = NULL_TREE;
- ip->down_flag = down_flag;
- ip->powerset_temp = NULL_TREE;
- ip->iter_var = NULL_TREE;
- ip->iter_type = NULL_TREE;
- ip->loc_ptr_temp = NULL_TREE;
- ip->error_flag = 1; /* assume error will be found */
- ip->next = (ITERATOR *)0;
-
- if (ever_flag)
- ip->itype = DO_FOREVER;
- else if (in_flag && start_exp != NULL_TREE)
- {
- if (TREE_CODE (start_exp) == ERROR_MARK)
- return;
- if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE)
- ip->itype = DO_POWERSET;
- else if (discrete_type_p (TREE_TYPE (ip->start_exp)))
- ip->itype = DO_RANGE;
- else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE)
- ip->itype = DO_LOC;
- else if (chill_varying_type_p (TREE_TYPE (ip->start_exp)))
- ip->itype = DO_LOC_VARYING;
- else
- {
- error ("loop's IN expression is not a composite object");
- return;
- }
- }
- else if (start_exp == NULL_TREE && end_exp == NULL_TREE
- && step_exp == NULL_TREE && !down_flag)
- ip->itype = DO_OD;
- else
- {
- /* FIXME: Move this to the lexer? */
-#define CST_FITS_INT(NODE) (TREE_CODE(NODE) == INTEGER_CST &&\
- int_fits_type_p (NODE, integer_type_node))
-
- tree max_prec_type = integer_type_node;
-
- if (! discrete_type_p (TREE_TYPE (ip->start_exp)))
- {
- error ("start expr must have discrete mode");
- return;
- }
- if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ENUMERAL_TYPE
- && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->start_exp)))
- {
- error ("DO FOR start expression is a numbered SET");
- return;
- }
- if (TREE_CODE (TREE_TYPE (ip->end_exp)) == ENUMERAL_TYPE
- && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->end_exp)))
- {
- error ("TO expression is a numbered SET");
- return;
- }
- /* Convert all three expressions to a common precision,
- which is the largest precision they exhibit, but
- INTEGER_CST nodes are built in the lexer as
- long_integer_type nodes. We'll treat convert them to
- integer_type_nodes if possible, for faster loop times. */
-
- if (TYPE_PRECISION (max_prec_type) <
- TYPE_PRECISION (TREE_TYPE (ip->start_exp))
- && !CST_FITS_INT (ip->start_exp))
- max_prec_type = TREE_TYPE (ip->start_exp);
- if (! discrete_type_p (TREE_TYPE (ip->end_exp)))
- {
- error ("TO expr must have discrete mode");
- return;
- }
- if (! CH_COMPATIBLE (ip->start_exp,
- TREE_TYPE (ip->end_exp)))
- {
- error ("start expr and TO expr must be compatible");
- return;
- }
- if (TYPE_PRECISION (max_prec_type) <
- TYPE_PRECISION (TREE_TYPE (ip->end_exp))
- && !CST_FITS_INT (ip->end_exp))
- max_prec_type = TREE_TYPE (ip->end_exp);
- if (ip->step_exp != NULL_TREE)
- {
- /* assure that default 'BY 1' gets a useful type */
- if (ip->step_exp == integer_one_node)
- ip->step_exp = convert (TREE_TYPE (ip->start_exp),
- ip->step_exp);
- if (! discrete_type_p (TREE_TYPE (ip->step_exp)))
- {
- error ("BY expr must have discrete mode");
- return;
- }
- if (! CH_COMPATIBLE (ip->start_exp,
- TREE_TYPE (ip->step_exp)))
- {
- error ("start expr and BY expr must be compatible");
- return;
- }
- if (TYPE_PRECISION (max_prec_type) <
- TYPE_PRECISION (TREE_TYPE (ip->step_exp))
- && !CST_FITS_INT (ip->step_exp))
- max_prec_type = TREE_TYPE (ip->step_exp);
- }
- if (TREE_CODE (ip->start_exp) == INTEGER_CST
- && TREE_CODE (ip->end_exp) == INTEGER_CST
- && compare_int_csts (ip->down_flag ? LT_EXPR : GT_EXPR,
- ip->start_exp, ip->end_exp))
- warning ("body of DO FOR will never execute");
-
- ip->start_exp =
- convert (max_prec_type, ip->start_exp);
- ip->end_exp =
- convert (max_prec_type, ip->end_exp);
-
- if (ip->step_exp != NULL_TREE)
- {
- ip->step_exp =
- convert (max_prec_type, ip->step_exp);
-
- if (TREE_CODE (ip->step_exp) != INTEGER_CST)
- {
- /* generate runtime check for negative BY expr */
- ip->step_exp =
- check_range (ip->step_exp, ip->step_exp,
- integer_zero_node, NULL_TREE);
- }
- else if (compare_int_csts (LE_EXPR, ip->step_exp, integer_zero_node))
- {
- error ("BY expression is negative or zero");
- return;
- }
- }
- ip->itype = DO_STEP;
- }
-
- ip->error_flag = 0; /* no errors! */
-}
-
-void
-build_loop_start (while_control, start_label)
- tree while_control, start_label;
-{
- ITERATOR *firstp = loop_stack->iter_list;
-
- firstp->condition = while_control;
-
- if (firstp->error_flag)
- return;
-
- /* We didn't know at begin_loop_scope time about the condition;
- adjust iterator type now. */
- if (firstp->itype == DO_OD && firstp->condition)
- firstp->itype = DO_WHILE;
-
- if (initialize_iter_var ())
- return;
-
- if (maybe_skip_loop ())
- return;
-
- /* use the label as an 'exit' label,
- 'goto' needs another sort of label */
- expand_start_loop (start_label != NULL_TREE);
-
- if (top_loop_end_check ())
- return;
- emit_line_note (input_filename, lineno);
-}
-
-/*
- * Called after the last action of the loop body
- * has been parsed.
- */
-void
-build_loop_end ()
-{
- ITERATOR *ip = loop_stack->iter_list;
-
- emit_line_note (input_filename, lineno);
-
- if (ip->error_flag)
- return;
-
- if (bottom_loop_end_check ())
- return;
-
- if (increment_temps ())
- return;
-
- if (ip->itype != DO_OD)
- {
- expand_end_loop ();
-
- for (; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_LOC_VARYING:
- case DO_STEP:
- expand_end_cond ();
- break;
- default:
- break;
- }
- }
- }
-}
-
-/*
- * The rest of the routines in this file are called from
- * the above three routines.
- */
-static int
-classify_loop ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- firstp->error_flag = 0;
- if (firstp->itype == DO_UNUSED || firstp->itype == DO_OD)
- {
- /* if we have just DO .. OD, do nothing - this is just a
- BEGIN .. END without creating a new scope, and no looping */
- if (firstp->condition != NULL_TREE)
- firstp->itype = DO_WHILE;
- else
- firstp->itype = DO_OD;
- }
-
- /* Issue a warning if the any loop counter is mentioned more
- than once in the iterator list. */
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- break;
- case DO_STEP:
- case DO_RANGE:
- case DO_POWERSET:
- case DO_LOC:
- case DO_LOC_VARYING:
- /* FIXME: check for name uniqueness */
- break;
- default:
- ;
- }
- }
- return firstp->error_flag;
-}
-
-/*
- * Reserve space for any loop-control temporaries, initialize them
- */
-static int
-declare_temps ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
- tree start_ptr;
-
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- break;
- case DO_STEP:
- ip->iter_type = chill_unsigned_type (TREE_TYPE (ip->start_exp));
-
- /* create, initialize temporaries if expressions aren't constant */
- ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start",
- ip->iter_type);
- ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end",
- ip->iter_type);
- /* this is just the step-expression */
- ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step",
- ip->iter_type);
- goto do_step_range;
-
- case DO_RANGE:
- ip->iter_type = chill_unsigned_type_node;
-
- ip->start_temp =
- (ip->down_flag ? build_chill_upper : build_chill_lower)(TREE_TYPE (ip->start_exp));
- ip->end_temp =
- (ip->down_flag ? build_chill_lower : build_chill_upper)(TREE_TYPE (ip->start_exp));
-
- ip->step_temp = integer_one_node;
-
- do_step_range:
- if (flag_local_loop_counter)
- {
- /* (re-)declare the user's iteration variable in the
- loop's scope. */
- tree id_node = ip->user_var;
- IDENTIFIER_LOCAL_VALUE (id_node) = ip->user_var =
- decl_temp1 (id_node, ip->iter_type, 0, NULL_TREE,
- 0, 0);
- }
- else
- {
- /* in this case, it's a previously-declared
- VAR_DECL node, checked in build_loop_iterator. */
- if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE)
- ip->user_var = lookup_name (ip->user_var);
- if (ip->user_var == NULL_TREE)
- {
- error ("loop identifier undeclared");
- ip->error_flag = 1;
- return 1;
- }
- }
- ip->iter_var =
- decl_temp1 (get_unique_identifier ("iter_var"),
- ip->iter_type, 0, NULL_TREE, 0, 0);
- break;
-
- case DO_POWERSET:
- ip->iter_type = chill_unsigned_type (
- TYPE_DOMAIN (TREE_TYPE (ip->start_exp)));
- if (flag_local_loop_counter)
- {
- /* declare the user's iteration variable in the loop's scope. */
- /* in this case, it's just an IDENTIFIER_NODE */
- ip->user_var =
- decl_temp1 (ip->user_var, ip->iter_type, 0, NULL_TREE, 0, 0);
- }
- else
- {
- /* in this case, it's a previously-declared VAR_DECL node */
- ip->user_var = lookup_name (ip->user_var);
- }
- /* the user's powerset-expression, evaluated and saved in a temp */
- ip->powerset_temp = maybe_make_for_temp (ip->start_exp, "for_set",
- TREE_TYPE (ip->start_exp));
- mark_addressable (ip->powerset_temp);
- break;
-
- case DO_LOC:
- case DO_LOC_VARYING:
- ip->iter_type = chill_unsigned_type_node;
- /* create the counter temp */
- ip->iter_var =
- build_temporary_variable ("iter_var", ip->iter_type);
-
- if (!CH_LOCATION_P (ip->start_exp))
- ip->start_exp
- = decl_temp1 (get_unique_identifier ("iter_loc"),
- TREE_TYPE (ip->start_exp), 0,
- ip->start_exp, 0, 0);
-
- if (ip->itype == DO_LOC)
- {
- tree array_type = TREE_TYPE (ip->start_exp);
- tree ptr_type;
- tree temp;
-
- if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
- {
- error ("can't iterate through array of BOOL");
- ip->error_flag = 1;
- return ip->error_flag;
- }
-
- /* FIXME: check for array type in ip->start_exp */
-
- /* create pointer temporary */
- ip->base_type = TREE_TYPE (array_type);
- ptr_type = build_pointer_type (ip->base_type);
- ip->loc_ptr_temp =
- build_temporary_variable ("loc_ptr_tmp", ptr_type);
-
- /* declare the user's iteration variable in
- the loop's scope, as an expression, to be
- passed to build_component_ref later */
- save_expr_under_name (ip->user_var,
- build1 (INDIRECT_REF, ip->base_type,
- ip->loc_ptr_temp));
-
- /* FIXME: see stor_layout */
- ip->step_temp = size_in_bytes (ip->base_type);
-
- temp = TYPE_DOMAIN (array_type);
-
- /* pointer to first array entry to look at */
- start_ptr = build1 (ADDR_EXPR, ptr_type, ip->start_exp);
- mark_addressable (ip->start_exp);
- ip->start_temp = ip->down_flag ?
- fold (build (PLUS_EXPR, ptr_type,
- start_ptr,
- fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
- fold (build (MINUS_EXPR, integer_type_node,
- TYPE_MAX_VALUE (temp),
- TYPE_MIN_VALUE (temp)))))))
- : start_ptr;
- }
- else
- {
- tree array_length =
- convert (integer_type_node,
- build_component_ref (ip->start_exp, var_length_id));
- tree array_type = TREE_TYPE (TREE_CHAIN (
- TYPE_FIELDS (TREE_TYPE (ip->start_exp))));
- tree array_data_ptr =
- build_component_ref (ip->start_exp, var_data_id);
- tree ptr_type;
-
- if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE)
- {
- error ("Can't iterate through array of BOOL");
- firstp->error_flag = 1;
- return firstp->error_flag;
- }
-
- /* create pointer temporary */
- ip->base_type = TREE_TYPE (array_type);
- ptr_type = build_pointer_type (ip->base_type);
- ip->loc_ptr_temp =
- build_temporary_variable ("loc_ptr_temp", ptr_type);
-
-
- /* declare the user's iteration variable in
- the loop's scope, as an expression, to be
- passed to build_component_ref later */
- save_expr_under_name (ip->user_var,
- build1 (INDIRECT_REF, ip->base_type,
- ip->loc_ptr_temp));
-
- /* FIXME: see stor_layout */
- ip->step_temp = size_in_bytes (ip->base_type);
-
- /* pointer to first array entry to look at */
- start_ptr = build1 (ADDR_EXPR, ptr_type, array_data_ptr);
- mark_addressable (array_data_ptr);
- ip->start_temp = ip->down_flag ?
- fold (build (PLUS_EXPR, ptr_type,
- start_ptr,
- fold (build (MULT_EXPR, integer_type_node, ip->step_temp,
- fold (build (MINUS_EXPR, integer_type_node,
- array_length,
- integer_one_node))))))
- : start_ptr;
- }
- default:
- ;
- }
- }
- return firstp->error_flag;
-}
-
-/*
- * Initialize the hidden iteration-control variables,
- * and the user's explicit loop variable.
- */
-static int
-initialize_iter_var ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- break;
- case DO_STEP:
- case DO_RANGE:
- {
- tree count =
- fold (build (PLUS_EXPR, ip->iter_type, integer_one_node,
- fold (build (TRUNC_DIV_EXPR, ip->iter_type,
- convert (ip->iter_type,
- fold (build (MINUS_EXPR, ip->iter_type,
- ip->down_flag ? ip->start_temp : ip->end_temp,
- ip->down_flag ? ip->end_temp : ip->start_temp))),
- ip->step_temp))));
- /* initialize the loop's hidden counter variable */
- expand_expr_stmt (
- build_chill_modify_expr (ip->iter_var, count));
-
- /* initialize user's variable */
- expand_expr_stmt (
- build_chill_modify_expr (ip->user_var, ip->start_temp));
- }
- break;
- case DO_POWERSET:
- break;
- case DO_LOC:
- {
- tree array_type = TREE_TYPE (ip->start_exp);
- tree array_length =
- fold (build (TRUNC_DIV_EXPR, integer_type_node,
- size_in_bytes (array_type),
- size_in_bytes (TREE_TYPE (array_type))));
-
- expand_expr_stmt (
- build_chill_modify_expr (ip->iter_var, array_length));
- goto do_loc_common;
- }
-
- case DO_LOC_VARYING:
- expand_expr_stmt (
- build_chill_modify_expr (ip->iter_var,
- convert (integer_type_node,
- build_component_ref (ip->start_exp, var_length_id))));
-
- do_loc_common:
- expand_expr_stmt (
- build_chill_modify_expr (ip->loc_ptr_temp,
- ip->start_temp));
- break;
-
- default:
- ;
- }
- }
- return firstp->error_flag;
-}
-
-/* Generate code to skip the whole loop, if start expression not
- * <= end expression (or >= for DOWN loops). This comparison must
- * *NOT* be done in unsigned mode, or it will fail.
- * Also, skip processing an empty VARYING array.
- */
-static int
-maybe_skip_loop ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_STEP:
- expand_start_cond (
- build (ip->down_flag ? GE_EXPR : LE_EXPR,
- TREE_TYPE (ip->start_exp),
- ip->start_exp, ip->end_exp), 0);
- break;
-
- case DO_LOC_VARYING:
- { tree array_length =
- convert (integer_type_node,
- build_component_ref (ip->start_exp, var_length_id));
- expand_start_cond (
- build (NE_EXPR, TREE_TYPE (array_length),
- array_length, integer_zero_node), 0);
- break;
- }
- default:
- break;
- }
- }
- return 0;
-}
-
-/*
- * Check at the top of the loop for a termination
- */
-static int
-top_loop_end_check ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- /* now, exit the loop if the condition isn't TRUE. */
- if (firstp->condition)
- {
- expand_exit_loop_if_false (0,
- chill_truthvalue_conversion (firstp->condition));
- }
-
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- case DO_STEP:
- case DO_RANGE:
- break;
- case DO_POWERSET:
- {
- tree temp1;
- char *func_name;
-
- if (ip->down_flag)
- func_name = "__flsetclrpowerset";
- else
- func_name = "__ffsetclrpowerset";
-
- temp1 = TYPE_MIN_VALUE
- (TYPE_DOMAIN (TREE_TYPE (ip->powerset_temp)));
- expand_exit_loop_if_false (0,
- build_chill_function_call (lookup_name (get_identifier (func_name)),
- tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp),
- tree_cons (NULL_TREE, powersetlen (ip->powerset_temp),
- tree_cons (NULL_TREE, force_addr_of (ip->user_var),
- tree_cons (NULL_TREE, size_in_bytes (TREE_TYPE (ip->user_var)),
- tree_cons (NULL_TREE,
- convert (long_integer_type_node, temp1),
- NULL_TREE)))))));
- }
- break;
- case DO_LOC:
- case DO_LOC_VARYING:
- break;
- default:
- ;
- }
- }
- return firstp->error_flag;
-}
-
-/*
- * Check generated temporaries for loop's end
- */
-static int
-bottom_loop_end_check ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- emit_line_note (input_filename, lineno);
-
- /* now, generate code to check each loop counter for termination */
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- break;
- case DO_STEP:
- case DO_RANGE:
- case DO_LOC:
- case DO_LOC_VARYING:
- /* decrement iteration counter by one */
- chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node);
- /* exit if it's zero */
- expand_exit_loop_if_false (0,
- build (NE_EXPR, boolean_type_node,
- ip->iter_var,
- integer_zero_node));
- break;
- case DO_POWERSET:
- break;
- default:
- ;
- }
- }
-
- return firstp->error_flag;
-}
-
-/*
- * increment the loop-control variables.
- */
-static int
-increment_temps ()
-{
- ITERATOR *firstp = loop_stack->iter_list, *ip;
-
- for (ip = firstp; ip != NULL; ip = ip->next)
- {
- switch (ip->itype)
- {
- case DO_FOREVER:
- case DO_WHILE:
- break;
- case DO_STEP:
- case DO_RANGE:
- {
- tree delta =
- fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
- TREE_TYPE (ip->user_var), ip->user_var,
- ip->step_temp));
- expand_expr_stmt (
- build_chill_modify_expr (ip->user_var, delta));
- }
- break;
- case DO_LOC:
- case DO_LOC_VARYING:
- /* This statement uses the C semantics, so that
- the pointer is actually incremented by the
- length of the object pointed to. */
-#if 1
- expand_expr_stmt (
- build_modify_expr (ip->loc_ptr_temp,
- ip->down_flag ? MINUS_EXPR : PLUS_EXPR,
- integer_one_node));
-#else
- {
- enum tree_code op = ip->down_flag ? MINUS_EXPR : PLUS_EXPR;
- tree el_type = TREE_TYPE (TREE_TYPE (ip->loc_ptr_temp));
- chill_expand_assignment (ip->loc_ptr_temp, NOP_EXPR,
- build (op,
- TREE_TYPE (ip->loc_ptr_temp),
- ip->loc_ptr_temp,
- size_in_bytes (el_type)));
- }
-#endif
- break;
- case DO_POWERSET:
- break;
- default:
- ;
- }
- }
- return firstp->error_flag;
-}
-
-/*
- * Generate a (temporary) unique identifier_node of
- * the form "__tmp_%s_%d"
- */
-tree
-get_unique_identifier (lead)
- char *lead;
-{
- char idbuf [256];
- static int idcount = 0;
-
- sprintf (idbuf, "__tmp_%s_%d", lead ? lead : "", idcount++);
- return get_identifier (idbuf);
-}
-
-/*
- * build a temporary variable, given its NAME and TYPE.
- * The name will have a number appended to assure uniqueness.
- * return its DECL node.
- */
-static tree
-build_temporary_variable (name, type)
- char *name;
- tree type;
-{
- return decl_temp1 (get_unique_identifier (name), type, 0, NULL_TREE, 0, 0);
-}
-
-
-/*
- * If the given expression isn't a constant, build a temp for it
- * and evaluate the expression into the temp. Return the tree
- * representing either the original constant expression or the
- * temp which now contains the expression's value.
- */
-static tree
-maybe_make_for_temp (exp, temp_name, exp_type)
- tree exp;
- char *temp_name;
- tree exp_type;
-{
- tree result = exp;
-
- if (exp != NULL_TREE)
- {
- /* if exp isn't constant, create a temporary for its value */
- if (TREE_CONSTANT (exp))
- {
- /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */
- result = convert (exp_type, exp);
- }
- else {
- /* build temp, assign the value */
- result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0,
- exp, 0, 0);
- }
- }
- return result;
-}
-
-
-/*
- * Adapt the C unsigned_type function to CHILL - we need to
- * account for any CHILL-specific integer types here. So far,
- * the 16-bit integer type is the only one.
- */
-static tree
-chill_unsigned_type (type)
- tree type;
-{
- extern tree chill_unsigned_type_node;
- tree type1 = TYPE_MAIN_VARIANT (type);
-
- if (type1 == chill_integer_type_node)
- return chill_unsigned_type_node;
- else
- return unsigned_type (type);
-}