aboutsummaryrefslogtreecommitdiff
path: root/gcc/ch/actions.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ch/actions.c')
-rw-r--r--gcc/ch/actions.c1836
1 files changed, 0 insertions, 1836 deletions
diff --git a/gcc/ch/actions.c b/gcc/ch/actions.c
deleted file mode 100644
index 09c8a5a23f7..00000000000
--- a/gcc/ch/actions.c
+++ /dev/null
@@ -1,1836 +0,0 @@
-/* Implement actions for CHILL.
- Copyright (C) 1992, 1993, 1994, 1998, 1999, 2000
- Free Software Foundation, Inc.
- Authors: Per Bothner, Bill Cox, Michael Tiemann, Michael North
-
-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 "config.h"
-#include "system.h"
-#include "tree.h"
-#include "rtl.h"
-#include "expr.h"
-#include "ch-tree.h"
-#include "lex.h"
-#include "flags.h"
-#include "actions.h"
-#include "obstack.h"
-#include "assert.h"
-#include "toplev.h"
-
-static int id_cmp PARAMS ((tree *, tree *));
-static void warn_unhandled PARAMS ((const char *));
-static tree adjust_return_value PARAMS ((tree, const char *));
-static tree update_else_range_for_int_const PARAMS ((tree, tree));
-static tree update_else_range_for_range PARAMS ((tree, tree, tree));
-static tree update_else_range_for_range_expr PARAMS ((tree, tree));
-static tree update_else_range_for_type PARAMS ((tree, tree));
-static tree compute_else_range PARAMS ((tree, tree, int));
-static tree check_case_value PARAMS ((tree, tree));
-static void chill_handle_case_label_range PARAMS ((tree, tree, tree));
-static tree chill_handle_multi_case_label_range PARAMS ((tree, tree, tree));
-static tree chill_handle_multi_case_else_label PARAMS ((tree));
-static tree chill_handle_multi_case_label PARAMS ((tree, tree));
-static tree chill_handle_multi_case_label_list PARAMS ((tree, tree));
-static void print_missing_cases PARAMS ((tree, const unsigned char *, long));
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* reserved tag definitions */
-
-#define TYPE_ID "id"
-#define TAG_OBJECT "chill_object"
-#define TAG_CLASS "chill_class"
-
-extern int flag_short_enums;
-extern int current_nesting_level;
-
-extern struct obstack *expression_obstack, permanent_obstack;
-extern struct obstack *current_obstack, *saveable_obstack;
-
-/* This flag is checked throughout the non-CHILL-specific
- in the front end. */
-tree chill_integer_type_node;
-tree chill_unsigned_type_node;
-
-/* Never used. Referenced from c-typeck.c, which we use. */
-int current_function_returns_value = 0;
-int current_function_returns_null = 0;
-
-/* data imported from toplev.c */
-
-extern char *dump_base_name;
-
-/* set from command line parameter, to exit after
- grant file written, generating no code. */
-int grant_only_flag = 0;
-
-const char *
-lang_identify ()
-{
- return "chill";
-}
-
-
-void
-init_chill ()
-{
-}
-
-void
-print_lang_statistics ()
-{
-}
-
-
-void
-lang_finish ()
-{
-#if 0
- extern int errorcount, sorrycount;
-
- /* this should be the last action in compiling a module.
- If there are other actions to be performed at lang_finish
- please insert before this */
-
- /* FIXME: in case of a syntax error, this leaves the grant file incomplete */
- /* for the moment we print a warning in case of errors and
- continue granting */
- if ((errorcount || sorrycount) && grant_count)
- {
- warning ("%d errors, %d sorries, do granting", errorcount, sorrycount);
- errorcount = sorrycount = 0;
- }
-#endif
-}
-
-void
-chill_check_decl (decl)
- tree decl;
-{
- tree type = TREE_TYPE (decl);
- static int alreadyWarned = 0;
-
- if (TREE_CODE (type) == RECORD_TYPE) /* && TREE_STATIC_TEMPLATE (type)) */
- {
- if (!alreadyWarned)
- {
- error ("GNU compiler does not support statically allocated objects");
- alreadyWarned = 1;
- }
- error_with_decl (decl, "`%s' cannot be statically allocated");
- }
-}
-
-/* Comparison function for sorting identifiers in RAISES lists.
- Note that because IDENTIFIER_NODEs are unique, we can sort
- them by address, saving an indirection. */
-static int
-id_cmp (p1, p2)
- tree *p1, *p2;
-{
- long diff = (long)TREE_VALUE (*p1) - (long)TREE_VALUE (*p2);
-
- return (diff < 0) ? -1 : (diff > 0);
-}
-
-/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions
- listed in RAISES. */
-tree
-build_exception_variant (type, raises)
- tree type, raises;
-{
- int i;
- tree v = TYPE_MAIN_VARIANT (type);
- tree t, t2;
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
-
- if (!raises)
- return build_type_variant (v, constp, volatilep);
-
- if (TREE_CHAIN (raises))
- { /* Sort the list */
- tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
- for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++)
- a[i] = t;
- /* NULL terminator for list. */
- a[i] = NULL_TREE;
- qsort (a, i, sizeof (tree),
- (int (*) PARAMS ((const void*, const void*))) id_cmp);
- while (i--)
- TREE_CHAIN (a[i]) = a[i+1];
- raises = a[0];
- }
-
- for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
- {
- if (TYPE_READONLY (v) != constp
- || TYPE_VOLATILE (v) != volatilep)
- continue;
-
- t = raises;
- t2 = TYPE_RAISES_EXCEPTIONS (v);
- while (t && t2)
- {
- if (TREE_TYPE (t) == TREE_TYPE (t2))
- {
- t = TREE_CHAIN (t);
- t2 = TREE_CHAIN (t2);
- }
- else break;
- }
- if (t || t2)
- continue;
- /* List of exceptions raised matches previously found list.
-
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
- return v;
- }
-
- /* Need to build a new variant. */
- if (TREE_PERMANENT (type))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- v = copy_node (type);
- pop_obstacks ();
- }
- else
- v = copy_node (type);
-
- TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
- TYPE_NEXT_VARIANT (type) = v;
- if (raises && ! TREE_PERMANENT (raises))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- raises = copy_list (raises);
- pop_obstacks ();
- }
- TYPE_RAISES_EXCEPTIONS (v) = raises;
- return v;
-}
-#if 0
-
-tree
-build_rts_call (name, type, args)
- const char *name;
- tree type, args;
-{
- tree decl = lookup_name (get_identifier (name));
- tree converted_args = NULL_TREE;
- tree result, length = NULL_TREE;
-
- assert (decl != NULL_TREE);
- while (args)
- {
- tree arg = TREE_VALUE (args);
- if (TREE_CODE (TREE_TYPE (arg)) == SET_TYPE
- || TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
- {
- length = size_in_bytes (TREE_TYPE (arg));
- arg = build_chill_addr_expr (arg, (char *)0);
- }
- converted_args = tree_cons (NULL_TREE, arg, converted_args);
- args = TREE_CHAIN (args);
- }
- if (length != NULL_TREE)
- converted_args = tree_cons (NULL_TREE, length, converted_args);
- converted_args = nreverse (converted_args);
- result = build_chill_function_call (decl, converted_args);
- if (TREE_CODE (type) == SET_TYPE || TREE_CODE (type) == ARRAY_TYPE)
- result = build1 (INDIRECT_REF, type, result);
- else
- result = convert (type, result);
- return result;
-}
-#endif
-
-/*
- * queue name of unhandled exception
- * to avoid multiple unhandled warnings
- * in one compilation module
- */
-
-struct already_type
-{
- struct already_type *next;
- char *name;
-};
-
-static struct already_type *already_warned = 0;
-
-static void
-warn_unhandled (ex)
- const char *ex;
-{
- struct already_type *p = already_warned;
-
- while (p)
- {
- if (!strcmp (p->name, ex))
- return;
- p = p->next;
- }
-
- /* not yet warned */
- p = (struct already_type *)xmalloc (sizeof (struct already_type));
- p->next = already_warned;
- p->name = xstrdup (ex);
- already_warned = p;
- pedwarn ("causing unhandled exception `%s' (this is flaged only once)", ex);
-}
-
-/*
- * build a call to the following function:
- * void __cause_ex1 (char* ex, const char *file,
- * const unsigned lineno);
- * if the exception is handled or
- * void __unhandled_ex (char *ex, char *file, unsigned lineno)
- * if the exception is not handled.
- */
-tree
-build_cause_exception (exp_name, warn_if_unhandled)
- tree exp_name;
- int warn_if_unhandled;
-{
- /* We don't use build_rts_call() here, because the string (array of char)
- would be followed by its length in the parameter list built by
- build_rts_call, and the runtime routine doesn't want a length parameter.*/
- tree exp_decl = build_chill_exception_decl (IDENTIFIER_POINTER (exp_name));
- tree function, fname, lineno, result;
- int handled = is_handled (exp_name);
-
- switch (handled)
- {
- case 0:
- /* no handler */
- if (warn_if_unhandled)
- warn_unhandled (IDENTIFIER_POINTER (exp_name));
- function = lookup_name (get_identifier ("__unhandled_ex"));
- fname = force_addr_of (get_chill_filename ());
- lineno = get_chill_linenumber ();
- break;
- case 1:
- /* local handler */
- function = lookup_name (get_identifier ("__cause_ex1"));
- fname = force_addr_of (get_chill_filename ());
- lineno = get_chill_linenumber ();
- break;
- case 2:
- /* function may propagate this exception */
- function = lookup_name (get_identifier ("__cause_ex1"));
- fname = lookup_name (get_identifier (CALLER_FILE));
- if (fname == NULL_TREE)
- fname = error_mark_node;
- lineno = lookup_name (get_identifier (CALLER_LINE));
- if (lineno == NULL_TREE)
- lineno = error_mark_node;
- break;
- default:
- abort();
- }
- result =
- build_chill_function_call (function,
- tree_cons (NULL_TREE, build_chill_addr_expr (exp_decl, (char *)0),
- tree_cons (NULL_TREE, fname,
- tree_cons (NULL_TREE, lineno, NULL_TREE))));
- return result;
-}
-
-void
-expand_cause_exception (exp_name)
- tree exp_name;
-{
- expand_expr_stmt (build_cause_exception (exp_name, 1));
-}
-
-/* If CONDITION is true, raise EXCEPTION (an IDENTIFIER_NODE);
- otherwise return EXPR. */
-
-tree
-check_expression (expr, condition, exception)
- tree expr, condition, exception;
-{
- if (integer_zerop (condition))
- return expr;
- else
- return build (COMPOUND_EXPR, TREE_TYPE (expr),
- fold (build (TRUTH_ANDIF_EXPR, boolean_type_node,
- condition, build_cause_exception (exception, 0))),
- expr);
-}
-
-/* Return an expression for VALUE < LO_LIMIT || VALUE > HI_LIMIT,
- somewhat optimized and with some warnings suppressed.
- If LO_LIMIT or HI_LIMIT is NULL_TREE, assume that (sub-)test passes. */
-
-tree
-test_range (value, lo_limit, hi_limit)
- tree value, lo_limit, hi_limit;
-{
- if (lo_limit || hi_limit)
- {
- int old_inhibit_warnings = inhibit_warnings;
- tree lo_check, hi_check, check;
-
- /* This is a hack so that `shorten_compare' doesn't warn the
- user about useless range checks that are too much work to
- optimize away here. */
- inhibit_warnings = 1;
-
- lo_check = lo_limit ?
- fold (build_compare_discrete_expr (LT_EXPR, value, lo_limit)) :
- boolean_false_node; /* fake passing the check */
-
- hi_check = hi_limit ?
- fold (build_compare_discrete_expr (GT_EXPR, value, hi_limit)) :
- boolean_false_node; /* fake passing the check */
-
- if (lo_check == boolean_false_node)
- check = hi_check;
- else if (hi_check == boolean_false_node)
- check = lo_check;
- else
- check = fold (build (TRUTH_ORIF_EXPR, boolean_type_node,
- lo_check, hi_check));
-
- inhibit_warnings = old_inhibit_warnings;
- return check;
- }
- else
- return boolean_false_node;
-}
-
-/* Return EXPR, except if range_checking is on, return an expression
- that also checks that value >= low_limit && value <= hi_limit.
- If LO_LIMIT or HI_LIMIT is NULL_TREE, assume that test passes. */
-
-tree
-check_range (expr, value, lo_limit, hi_limit)
- tree expr, value, lo_limit, hi_limit;
-{
- tree check = test_range (value, lo_limit, hi_limit);
- if (!integer_zerop (check))
- {
- if (current_function_decl == NULL_TREE)
- {
- if (TREE_CODE (check) == INTEGER_CST)
- error ("range failure (not inside function)");
- else
- warning ("possible range failure (not inside function)");
- }
- else
- {
- if (TREE_CODE (check) == INTEGER_CST)
- warning ("expression will always cause RANGEFAIL");
- if (range_checking)
- expr = check_expression (expr, check,
- ridpointers[(int) RID_RANGEFAIL]);
- }
- }
- return expr;
-}
-
-/* Same as EXPR, except raise EMPTY if EXPR is NULL. */
-
-tree
-check_non_null (expr)
- tree expr;
-{
- if (empty_checking)
- {
- expr = save_if_needed (expr);
- return check_expression (expr,
- build_compare_expr (EQ_EXPR,
- expr, null_pointer_node),
- ridpointers[(int) RID_EMPTY]);
- }
- return expr;
-}
-
-/* There are four conditions to generate a runtime check:
- 1) assigning a longer INT to a shorter (signs irrelevant)
- 2) assigning a signed to an unsigned
- 3) assigning an unsigned to a signed of the same size.
- 4) TYPE is a discrete subrange */
-
-tree
-chill_convert_for_assignment (type, expr, place)
- tree type, expr;
- const char *place; /* location description for error messages */
-{
- tree ttype = type;
- tree etype = TREE_TYPE (expr);
- tree result;
-
- if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
- return error_mark_node;
- if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK)
- return expr;
- if (TREE_CODE (expr) == TYPE_DECL)
- {
- error ("right hand side of assignment is a mode");
- return error_mark_node;
- }
-
- if (! CH_COMPATIBLE (expr, type))
- {
- error ("incompatible modes in %s", place);
- return error_mark_node;
- }
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- ttype = TREE_TYPE (ttype);
- if (etype && TREE_CODE (etype) == REFERENCE_TYPE)
- etype = TREE_TYPE (etype);
-
- if (etype
- && (CH_STRING_TYPE_P (ttype)
- || (chill_varying_type_p (ttype)
- && CH_STRING_TYPE_P (CH_VARYING_ARRAY_TYPE (ttype))))
- && (CH_STRING_TYPE_P (etype)
- || (chill_varying_type_p (etype)
- && CH_STRING_TYPE_P (CH_VARYING_ARRAY_TYPE (etype)))))
- {
- tree cond;
- if (range_checking)
- expr = save_if_needed (expr);
- cond = string_assignment_condition (ttype, expr);
- if (TREE_CODE (cond) == INTEGER_CST)
- {
- if (integer_zerop (cond))
- {
- error ("bad string length in %s", place);
- return error_mark_node;
- }
- /* Otherwise, the condition is always true, so no runtime test. */
- }
- else if (range_checking)
- expr = check_expression (expr,
- invert_truthvalue (cond),
- ridpointers[(int) RID_RANGEFAIL]);
- }
-
- if (range_checking
- && discrete_type_p (ttype)
- && etype != NULL_TREE
- && discrete_type_p (etype))
- {
- int cond1 = tree_int_cst_lt (TYPE_SIZE (ttype),
- TYPE_SIZE (etype));
- int cond2 = TREE_UNSIGNED (ttype)
- && (! TREE_UNSIGNED (etype));
- int cond3 = (! TREE_UNSIGNED (type))
- && TREE_UNSIGNED (etype)
- && tree_int_cst_equal (TYPE_SIZE (ttype),
- TYPE_SIZE (etype));
- int cond4 = TREE_TYPE (ttype)
- && discrete_type_p (TREE_TYPE (ttype));
-
- if (cond1 || cond2 || cond3 || cond4)
- {
- tree type_min = TYPE_MIN_VALUE (ttype);
- tree type_max = TYPE_MAX_VALUE (ttype);
-
- expr = save_if_needed (expr);
- if (expr && type_min && type_max)
- expr = check_range (expr, expr, type_min, type_max);
- }
- }
- result = convert (type, expr);
-
- /* If the type is a array of PACK bits and the expression is an array
- constructor, then build a CONSTRUCTOR for a bitstring. Bitstrings are
- zero based, so decrement the value of each CONSTRUCTOR element by the
- amount of the lower bound of the array. */
- if (TREE_CODE (type) == ARRAY_TYPE && TYPE_PACKED (type)
- && TREE_CODE (result) == CONSTRUCTOR)
- {
- tree domain_min = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- tree new_list = NULL_TREE;
- unsigned HOST_WIDE_INT index;
- tree element;
-
- for (element = TREE_OPERAND (result, 1);
- element != NULL_TREE;
- element = TREE_CHAIN (element))
- {
- if (!tree_int_cst_equal (TREE_VALUE (element), integer_zero_node))
- {
- tree purpose = TREE_PURPOSE (element);
- switch (TREE_CODE (purpose))
- {
- case INTEGER_CST:
- new_list
- = tree_cons (NULL_TREE,
- fold (build (MINUS_EXPR, TREE_TYPE (purpose),
- purpose, domain_min)),
- new_list);
- break;
- case RANGE_EXPR:
- for (index = TREE_INT_CST_LOW (TREE_OPERAND (purpose, 0));
- index <= TREE_INT_CST_LOW (TREE_OPERAND (purpose, 1));
- index++)
- new_list = tree_cons (NULL_TREE,
- fold (build (MINUS_EXPR,
- integer_type_node,
- build_int_2 (index, 0),
- domain_min)),
- new_list);
- break;
- default:
- abort ();
- }
- }
- }
- result = copy_node (result);
- TREE_OPERAND (result, 1) = nreverse (new_list);
- TREE_TYPE (result) = build_bitstring_type (TYPE_SIZE (type));
- }
-
- return result;
-}
-
-/* Check that EXPR has valid type for a RETURN or RESULT expression,
- converting to the right type. ACTION is "RESULT" or "RETURN". */
-
-static tree
-adjust_return_value (expr, action)
- tree expr;
- const char *action;
-{
- tree type = TREE_TYPE (TREE_TYPE (current_function_decl));
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- if (CH_LOCATION_P (expr))
- {
- if (! CH_READ_COMPATIBLE (TREE_TYPE (type),
- TREE_TYPE (expr)))
- {
- error ("mode mismatch in %s expression", action);
- return error_mark_node;
- }
- return convert (type, expr);
- }
- else
- {
- error ("%s expression must be referable", action);
- return error_mark_node;
- }
- }
- else if (! CH_COMPATIBLE (expr, type))
- {
- error ("mode mismatch in %s expression", action);
- return error_mark_node;
- }
- return convert (type, expr);
-}
-
-void
-chill_expand_result (expr, result_or_return)
- tree expr;
- int result_or_return;
-{
- tree type;
- const char *action_name = result_or_return ? "RESULT" : "RETURN";
-
- if (pass == 1)
- return;
-
- if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK)
- return;
-
- CH_FUNCTION_SETS_RESULT (current_function_decl) = 1;
-
- if (chill_at_module_level || global_bindings_p ())
- error ("%s not allowed outside a PROC", action_name);
-
- result_never_set = 0;
-
- if (chill_result_decl == NULL_TREE)
- {
- error ("%s action in PROC with no declared RESULTS", action_name);
- return;
- }
- type = TREE_TYPE (chill_result_decl);
-
- if (TREE_CODE (type) == ERROR_MARK)
- return;
-
- expr = adjust_return_value (expr, action_name);
-
- expand_expr_stmt (build_chill_modify_expr (chill_result_decl, expr));
-}
-
-/*
- * error if EXPR not NULL and procedure doesn't
- * have a return type;
- * warning if EXPR NULL,
- * procedure *has* a return type, and a previous
- * RESULT actions hasn't saved a return value.
- */
-void
-chill_expand_return (expr, implicit)
- tree expr;
- int implicit; /* 1 if an implicit return at end of function. */
-{
- tree valtype;
-
- if (expr != NULL_TREE && TREE_CODE (expr) == ERROR_MARK)
- return;
- if (chill_at_module_level || global_bindings_p ())
- {
- error ("RETURN not allowed outside PROC");
- return;
- }
-
- if (pass == 1)
- return;
-
- result_never_set = 0;
-
- valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
- if (TREE_CODE (valtype) == VOID_TYPE)
- {
- if (expr != NULL_TREE)
- error ("RETURN with a value, in PROC returning void");
- expand_null_return ();
- }
- else if (TREE_CODE (valtype) != ERROR_MARK)
- {
- if (expr == NULL_TREE)
- {
- if (!CH_FUNCTION_SETS_RESULT (current_function_decl)
- && !implicit)
- warning ("RETURN with no value and no RESULT action in procedure");
- expr = chill_result_decl;
- }
- else
- expr = adjust_return_value (expr, "RETURN");
- expr = build (MODIFY_EXPR, valtype,
- DECL_RESULT (current_function_decl),
- expr);
- TREE_SIDE_EFFECTS (expr) = 1;
- expand_return (expr);
- }
-}
-
-void
-lookup_and_expand_goto (name)
- tree name;
-{
- if (name == NULL_TREE || TREE_CODE (name) == ERROR_MARK)
- return;
- if (!ignoring)
- {
- tree decl = lookup_name (name);
- if (decl == NULL || TREE_CODE (decl) != LABEL_DECL)
- error ("no label named `%s'", IDENTIFIER_POINTER (name));
- else if (DECL_CONTEXT (decl) != current_function_decl)
- error ("cannot GOTO label `%s' outside current function",
- IDENTIFIER_POINTER (name));
- else
- {
- TREE_USED (decl) = 1;
- expand_goto_except_cleanup (DECL_ACTION_NESTING_LEVEL (decl));
- expand_goto (decl);
- }
- }
-}
-
-void
-lookup_and_handle_exit (name)
- tree name;
-{
- if (name == NULL_TREE || TREE_CODE (name) == ERROR_MARK)
- return;
- if (!ignoring)
- {
- tree label = munge_exit_label (name);
- tree decl = lookup_name (label);
- if (decl == NULL || TREE_CODE (decl) != LABEL_DECL)
- error ("no EXITable label named `%s'", IDENTIFIER_POINTER (name));
- else if (DECL_CONTEXT (decl) != current_function_decl)
- error ("cannot EXIT label `%s' outside current function",
- IDENTIFIER_POINTER (name));
- else
- {
- TREE_USED (decl) = 1;
- expand_goto_except_cleanup (DECL_ACTION_NESTING_LEVEL (decl));
- expand_goto (decl);
- }
- }
-}
-
-/* ELSE-range handling: The else-range is a chain of trees which collectively
- represent the ranges to be tested for the (ELSE) case label. Each element in
- the chain represents a range to be tested. The boundaries of the range are
- represented by INTEGER_CST trees in the PURPOSE and VALUE fields. */
-
-/* This function updates the else-range by removing the given integer constant. */
-static tree
-update_else_range_for_int_const (else_range, label)
- tree else_range, label;
-{
- int lowval = 0, highval = 0;
- int label_value = TREE_INT_CST_LOW (label);
- tree this_range, prev_range, new_range;
-
- /* First, find the range element containing the integer, if it exists. */
- prev_range = NULL_TREE;
- for (this_range = else_range ;
- this_range != NULL_TREE;
- this_range = TREE_CHAIN (this_range))
- {
- lowval = TREE_INT_CST_LOW (TREE_PURPOSE (this_range));
- highval = TREE_INT_CST_LOW (TREE_VALUE (this_range));
- if (label_value >= lowval && label_value <= highval)
- break;
- prev_range = this_range;
- }
-
- /* If a range element containing the integer was found, then update the range. */
- if (this_range != NULL_TREE)
- {
- tree next = TREE_CHAIN (this_range);
- if (label_value == lowval)
- {
- /* The integer is the lower bound of the range element. If it is also the
- upper bound, then remove this range element, otherwise update it. */
- if (label_value == highval)
- {
- if (prev_range == NULL_TREE)
- else_range = next;
- else
- TREE_CHAIN (prev_range) = next;
- }
- else
- TREE_PURPOSE (this_range) = build_int_2 (label_value + 1, 0);
- }
- else if (label_value == highval)
- {
- /* The integer is the upper bound of the range element, so ajust it. */
- TREE_VALUE (this_range) = build_int_2 (label_value - 1, 0);
- }
- else
- {
- /* The integer is in the middle of the range element, so split it. */
- new_range = tree_cons (
- build_int_2 (label_value + 1, 0), TREE_VALUE (this_range), next);
- TREE_VALUE (this_range) = build_int_2 (label_value - 1, 0);
- TREE_CHAIN (this_range) = new_range;
- }
- }
- return else_range;
-}
-
-/* Update the else-range to remove a range of values/ */
-static tree
-update_else_range_for_range (else_range, low_target, high_target)
- tree else_range, low_target, high_target;
-{
- tree this_range, prev_range, new_range, next_range;
- int low_range_val = 0, high_range_val = 0;
- int low_target_val = TREE_INT_CST_LOW (low_target);
- int high_target_val = TREE_INT_CST_LOW (high_target);
-
- /* find the first else-range element which overlaps the target range. */
- prev_range = NULL_TREE;
- for (this_range = else_range ;
- this_range != NULL_TREE;
- this_range = TREE_CHAIN (this_range))
- {
- low_range_val = TREE_INT_CST_LOW (TREE_PURPOSE (this_range));
- high_range_val = TREE_INT_CST_LOW (TREE_VALUE (this_range));
- if ((low_target_val >= low_range_val && low_target_val <= high_range_val)
- || (high_target_val >= low_range_val && high_target_val <= high_range_val))
- break;
- prev_range = this_range;
- }
- if (this_range == NULL_TREE)
- return else_range;
-
- /* This first else-range element might be truncated at the top or completely
- contain the target range. */
- if (low_range_val < low_target_val)
- {
- next_range = TREE_CHAIN (this_range);
- if (high_range_val > high_target_val)
- {
- new_range = tree_cons (
- build_int_2 (high_target_val + 1, 0), TREE_VALUE (this_range), next_range);
- TREE_VALUE (this_range) = build_int_2 (low_target_val - 1, 0);
- TREE_CHAIN (this_range) = new_range;
- return else_range;
- }
-
- TREE_VALUE (this_range) = build_int_2 (low_target_val - 1, 0);
- if (next_range == NULL_TREE)
- return else_range;
-
- prev_range = this_range;
- this_range = next_range;
- high_range_val = TREE_INT_CST_LOW (TREE_VALUE (this_range));
- }
-
- /* There may then follow zero or more else-range elements which are completely
- contained in the target range. */
- while (high_range_val <= high_target_val)
- {
- this_range = TREE_CHAIN (this_range);
- if (prev_range == NULL_TREE)
- else_range = this_range;
- else
- TREE_CHAIN (prev_range) = this_range;
-
- if (this_range == NULL_TREE)
- return else_range;
- high_range_val = TREE_INT_CST_LOW (TREE_VALUE (this_range));
- }
-
- /* Finally, there may be a else-range element which is truncated at the bottom. */
- low_range_val = TREE_INT_CST_LOW (TREE_PURPOSE (this_range));
- if (low_range_val <= high_target_val)
- TREE_PURPOSE (this_range) = build_int_2 (high_target_val + 1, 0);
-
- return else_range;
-}
-
-static tree
-update_else_range_for_range_expr (else_range, label)
- tree else_range, label;
-{
- if (TREE_OPERAND (label, 0) == NULL_TREE)
- {
- if (TREE_OPERAND (label, 1) == NULL_TREE)
- else_range = NULL_TREE; /* (*) -- matches everything */
- }
- else
- else_range = update_else_range_for_range (
- else_range, TREE_OPERAND (label, 0), TREE_OPERAND (label, 1));
-
- return else_range;
-}
-
-static tree
-update_else_range_for_type (else_range, label)
- tree else_range, label;
-{
- tree type = TREE_TYPE (label);
- else_range = update_else_range_for_range (
- else_range, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type));
- return else_range;
-}
-
-static tree
-compute_else_range (selector, alternatives, selector_no)
- tree selector, alternatives;
- int selector_no;
-{
- /* Start with an else-range that spans the entire range of the selector type. */
- tree type = TREE_TYPE (TREE_VALUE (selector));
- tree range = tree_cons (TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type), NULL_TREE);
-
- /* Now remove the values represented by each case lebel specified for that
- selector. The remaining range is the else-range. */
- for ( ; alternatives != NULL_TREE; alternatives = TREE_CHAIN (alternatives))
- {
- tree label;
- tree label_list = TREE_PURPOSE (alternatives);
- int this_selector;
- for (this_selector = 0; this_selector < selector_no ; ++this_selector)
- label_list = TREE_CHAIN (label_list);
-
- for (label = TREE_VALUE (label_list);
- label != NULL_TREE;
- label = TREE_CHAIN (label))
- {
- tree label_value = TREE_VALUE (label);
- if (TREE_CODE (label_value) == INTEGER_CST)
- range = update_else_range_for_int_const (range, label_value);
- else if (TREE_CODE (label_value) == RANGE_EXPR)
- range = update_else_range_for_range_expr (range, label_value);
- else if (TREE_CODE (label_value) == TYPE_DECL)
- range = update_else_range_for_type (range, label_value);
-
- if (range == NULL_TREE)
- break;
- }
- }
-
- return range;
-}
-
-void
-compute_else_ranges (selectors, alternatives)
- tree selectors, alternatives;
-{
- tree selector;
- int selector_no = 0;
-
- for (selector = selectors; selector != NULL_TREE; selector = TREE_CHAIN (selector))
- {
- if (ELSE_LABEL_SPECIFIED (selector))
- TREE_PURPOSE (selector) =
- compute_else_range (selector, alternatives, selector_no);
- selector_no++;
- }
-}
-
-static tree
-check_case_value (label_value, selector)
- tree label_value, selector;
-{
- if (TREE_CODE (label_value) == ERROR_MARK)
- return label_value;
- if (TREE_CODE (selector) == ERROR_MARK)
- return selector;
-
- /* Z.200 (6.4 Case action) says: "The class of any discrete expression
- in the case selector list must be compatible with the corresponding
- (by position) class of the resulting list of classes of the case label
- list occurrences ...". We don't actually construct the resulting
- list of classes, but this test should be more-or-less equivalent.
- I think... */
- if (!CH_COMPATIBLE_CLASSES (selector, label_value))
- {
- error ("case selector not compatible with label");
- return error_mark_node;
- }
-
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (label_value);
-
- if (TREE_CODE (label_value) != INTEGER_CST)
- {
- error ("case label does not reduce to an integer constant");
- return error_mark_node;
- }
-
- constant_expression_warning (label_value);
- return label_value;
-}
-
-void
-chill_handle_case_default ()
-{
- tree duplicate;
- register tree label = build_decl (LABEL_DECL, NULL_TREE,
- NULL_TREE);
- int success = pushcase (NULL_TREE, 0, label, &duplicate);
-
- if (success == 1)
- error ("ELSE label not within a CASE statement");
-#if 0
- else if (success == 2)
- {
- error ("multiple default labels found in a CASE statement");
- error_with_decl (duplicate, "this is the first ELSE label");
- }
-#endif
-}
-
-/* Handle cases label such as (I:J): or (modename): */
-
-static void
-chill_handle_case_label_range (min_value, max_value, selector)
- tree min_value, max_value, selector;
-{
- register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- min_value = check_case_value (min_value, selector);
- max_value = check_case_value (max_value, selector);
- if (TREE_CODE (min_value) != ERROR_MARK
- && TREE_CODE (max_value) != ERROR_MARK)
- {
- tree duplicate;
- int success = pushcase_range (min_value, max_value,
- convert, label, &duplicate);
- if (success == 1)
- error ("label found outside of CASE statement");
- else if (success == 2)
- {
- error ("duplicate CASE value");
- error_with_decl (duplicate, "this is the first entry for that value");
- }
- else if (success == 3)
- error ("CASE value out of range");
- else if (success == 4)
- error ("empty range");
- else if (success == 5)
- error ("label within scope of cleanup or variable array");
- }
-}
-
-void
-chill_handle_case_label (label_value, selector)
- tree label_value, selector;
-{
- if (label_value == NULL_TREE
- || TREE_CODE (label_value) == ERROR_MARK)
- return;
- if (TREE_CODE (label_value) == RANGE_EXPR)
- {
- if (TREE_OPERAND (label_value, 0) == NULL_TREE)
- chill_handle_case_default (); /* i.e. (ELSE): or (*): */
- else
- chill_handle_case_label_range (TREE_OPERAND (label_value, 0),
- TREE_OPERAND (label_value, 1),
- selector);
- }
- else if (TREE_CODE (label_value) == TYPE_DECL)
- {
- tree type = TREE_TYPE (label_value);
- if (! discrete_type_p (type))
- error ("mode in label is not discrete");
- else
- chill_handle_case_label_range (TYPE_MIN_VALUE (type),
- TYPE_MAX_VALUE (type),
- selector);
- }
- else
- {
- register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- label_value = check_case_value (label_value, selector);
-
- if (TREE_CODE (label_value) != ERROR_MARK)
- {
- tree duplicate;
- int success = pushcase (label_value, convert, label, &duplicate);
- if (success == 1)
- error ("label not within a CASE statement");
- else if (success == 2)
- {
- error ("duplicate case value");
- error_with_decl (duplicate,
- "this is the first entry for that value");
- }
- else if (success == 3)
- error ("CASE value out of range");
- else if (success == 4)
- error ("empty range");
- else if (success == 5)
- error ("label within scope of cleanup or variable array");
- }
- }
-}
-
-int
-chill_handle_single_dimension_case_label (
- selector, label_spec, expand_exit_needed, caseaction_flag
-)
- tree selector, label_spec;
- int *expand_exit_needed, *caseaction_flag;
-{
- tree labels, one_label;
- int no_completeness_check = 0;
-
- if (*expand_exit_needed || *caseaction_flag == 1)
- {
- expand_exit_something ();
- *expand_exit_needed = 0;
- }
-
- for (labels = label_spec; labels != NULL_TREE; labels = TREE_CHAIN (labels))
- for (one_label = TREE_VALUE (labels); one_label != NULL_TREE;
- one_label = TREE_CHAIN (one_label))
- {
- if (TREE_VALUE (one_label) == case_else_node)
- no_completeness_check = 1;
-
- chill_handle_case_label (TREE_VALUE (one_label), selector);
- }
-
- *caseaction_flag = 1;
-
- return no_completeness_check;
-}
-
-static tree
-chill_handle_multi_case_label_range (low, high, selector)
- tree low, high, selector;
-{
- tree low_expr, high_expr, and_expr;
- tree selector_type;
- int low_target_val, high_target_val;
- int low_type_val, high_type_val;
-
- /* we can eliminate some tests is the low and/or high value in the given range
- are outside the range of the selector type. */
- low_target_val = TREE_INT_CST_LOW (low);
- high_target_val = TREE_INT_CST_LOW (high);
- selector_type = TREE_TYPE (selector);
- low_type_val = TREE_INT_CST_LOW (TYPE_MIN_VALUE (selector_type));
- high_type_val = TREE_INT_CST_LOW (TYPE_MAX_VALUE (selector_type));
-
- if (low_target_val > high_type_val || high_target_val < low_type_val)
- return boolean_false_node; /* selector never in range */
-
- if (low_type_val >= low_target_val)
- {
- if (high_type_val <= high_target_val)
- return boolean_true_node; /* always in the range */
- return build_compare_expr (LE_EXPR, selector, high);
- }
-
- if (high_type_val <= high_target_val)
- return build_compare_expr (GE_EXPR, selector, low);
-
- /* The target range in completely within the range of the selector, but we
- might be able to save a test if the upper bound is the same as the lower
- bound. */
- if (low_target_val == high_target_val)
- return build_compare_expr (EQ_EXPR, selector, low);
-
- /* No optimizations possible. Just generate tests against the upper and lower
- bound of the target */
- low_expr = build_compare_expr (GE_EXPR, selector, low);
- high_expr = build_compare_expr (LE_EXPR, selector, high);
- and_expr = build_chill_binary_op (TRUTH_ANDIF_EXPR, low_expr, high_expr);
-
- return and_expr;
-}
-
-static tree
-chill_handle_multi_case_else_label (selector)
- tree selector;
-{
- tree else_range, selector_value, selector_type;
- tree low, high, larg;
-
- else_range = TREE_PURPOSE (selector);
- if (else_range == NULL_TREE)
- return boolean_false_node; /* no values in ELSE range */
-
- /* Test each of the ranges in the else-range chain */
- selector_value = TREE_VALUE (selector);
- selector_type = TREE_TYPE (selector_value);
- low = convert (selector_type, TREE_PURPOSE (else_range));
- high = convert (selector_type, TREE_VALUE (else_range));
- larg = chill_handle_multi_case_label_range (low, high, selector_value);
-
- for (else_range = TREE_CHAIN (else_range);
- else_range != NULL_TREE;
- else_range = TREE_CHAIN (else_range))
- {
- tree rarg;
- low = convert (selector_type, TREE_PURPOSE (else_range));
- high = convert (selector_type, TREE_VALUE (else_range));
- rarg = chill_handle_multi_case_label_range (low, high, selector_value);
- larg = build_chill_binary_op (TRUTH_ORIF_EXPR, larg, rarg);
- }
-
- return larg;
-}
-
-static tree
-chill_handle_multi_case_label (selector, label)
- tree selector, label;
-{
- tree expr = NULL_TREE;
-
- if (label == NULL_TREE || TREE_CODE (label) == ERROR_MARK)
- return NULL_TREE;
-
- if (TREE_CODE (label) == INTEGER_CST)
- {
- int target_val = TREE_INT_CST_LOW (label);
- tree selector_type = TREE_TYPE (TREE_VALUE (selector));
- int low_type_val = TREE_INT_CST_LOW (TYPE_MIN_VALUE (selector_type));
- int high_type_val = TREE_INT_CST_LOW (TYPE_MAX_VALUE (selector_type));
- if (target_val < low_type_val || target_val > high_type_val)
- expr = boolean_false_node;
- else
- expr = build_compare_expr (EQ_EXPR, TREE_VALUE (selector), label);
- }
- else if (TREE_CODE (label) == RANGE_EXPR)
- {
- if (TREE_OPERAND (label, 0) == NULL_TREE)
- {
- if (TREE_OPERAND (label, 1) == NULL_TREE)
- expr = boolean_true_node; /* (*) -- matches everything */
- else
- expr = chill_handle_multi_case_else_label (selector);
- }
- else
- {
- tree low = TREE_OPERAND (label, 0);
- tree high = TREE_OPERAND (label, 1);
- if (TREE_CODE (low) != INTEGER_CST)
- {
- error ("Lower bound of range must be a discrete literal expression");
- expr = error_mark_node;
- }
- if (TREE_CODE (high) != INTEGER_CST)
- {
- error ("Upper bound of range must be a discrete literal expression");
- expr = error_mark_node;
- }
- if (expr != error_mark_node)
- {
- expr = chill_handle_multi_case_label_range (
- low, high, TREE_VALUE (selector));
- }
- }
- }
- else if (TREE_CODE (label) == TYPE_DECL)
- {
- tree type = TREE_TYPE (label);
- if (! discrete_type_p (type))
- {
- error ("mode in label is not discrete");
- expr = error_mark_node;
- }
- else
- expr = chill_handle_multi_case_label_range (
- TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type), TREE_VALUE (selector));
- }
- else
- {
- error ("The CASE label is not valid");
- expr = error_mark_node;
- }
-
- return expr;
-}
-
-static tree
-chill_handle_multi_case_label_list (selector, labels)
- tree selector, labels;
-{
- tree one_label, larg, rarg;
-
- one_label = TREE_VALUE (labels);
- larg = chill_handle_multi_case_label (selector, TREE_VALUE (one_label));
-
- for (one_label = TREE_CHAIN (one_label);
- one_label != NULL_TREE;
- one_label = TREE_CHAIN (one_label))
- {
- rarg = chill_handle_multi_case_label (selector, TREE_VALUE (one_label));
- larg = build_chill_binary_op (TRUTH_ORIF_EXPR, larg, rarg);
- }
-
- return larg;
-}
-
-tree
-build_multi_case_selector_expression (selector_list, label_spec)
- tree selector_list, label_spec;
-{
- tree labels, selector, larg, rarg;
-
- labels = label_spec;
- selector = selector_list;
- larg = chill_handle_multi_case_label_list(selector, labels);
-
- for (labels = TREE_CHAIN (labels), selector = TREE_CHAIN (selector);
- labels != NULL_TREE && selector != NULL_TREE;
- labels = TREE_CHAIN (labels), selector = TREE_CHAIN (selector))
- {
- rarg = chill_handle_multi_case_label_list(selector, labels);
- larg = build_chill_binary_op (TRUTH_ANDIF_EXPR, larg, rarg);
- }
-
- if (labels != NULL_TREE || selector != NULL_TREE)
- error ("The number of CASE selectors does not match the number of CASE label lists");
-
- return larg;
-}
-
-#define BITARRAY_TEST(ARRAY, INDEX) \
- ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
- & (1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR)))
-#define BITARRAY_SET(ARRAY, INDEX) \
- ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
- |= 1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR))
-
-/* CASES_SEEN is a set (bitarray) of length COUNT.
- For each element that is zero, print an error message,
- assume the element have the given TYPE. */
-
-static void
-print_missing_cases (type, cases_seen, count)
- tree type;
- const unsigned char *cases_seen;
- long count;
-{
- long i;
- for (i = 0; i < count; i++)
- {
- if (BITARRAY_TEST(cases_seen, i) == 0)
- {
- char buf[20];
- long x = i;
- long j;
- tree t = type;
- const char *err_val_name = "???";
- if (TYPE_MIN_VALUE (t)
- && TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST)
- x += TREE_INT_CST_LOW (TYPE_MIN_VALUE (t));
- while (TREE_TYPE (t) != NULL_TREE)
- t = TREE_TYPE (t);
- switch (TREE_CODE (t))
- {
- tree v;
- case BOOLEAN_TYPE:
- err_val_name = x ? "TRUE" : "FALSE";
- break;
- case CHAR_TYPE:
- {
- char *bufptr;
- if ((x >= ' ' && x < 127) && x != '\'' && x != '^')
- sprintf (buf, "'%c'", (char)x);
- else
- sprintf (buf, "'^(%ld)'", x);
- bufptr = buf;
- j = i;
- while (j < count && !BITARRAY_TEST(cases_seen, j))
- j++;
- if (j > i + 1)
- {
- long y = x+j-i-1;
- bufptr += strlen (bufptr);
- if ((y >= ' ' && y < 127) && y != '\'' && y != '^')
- sprintf (bufptr, "%s:'%c'", buf, (char)y);
- else
- sprintf (bufptr, "%s:'^(%ld)'", buf, y);
- i = j - 1;
- }
- err_val_name = bufptr;
- }
- break;
- case ENUMERAL_TYPE:
- for (v = TYPE_VALUES (t); v && x; v = TREE_CHAIN (v))
- x--;
- if (v)
- err_val_name = IDENTIFIER_POINTER (TREE_PURPOSE (v));
- break;
- default:
- j = i;
- while (j < count && !BITARRAY_TEST(cases_seen, j))
- j++;
- if (j == i + 1)
- sprintf (buf, "%ld", x);
- else
- sprintf (buf, "%ld:%ld", x, x+j-i-1);
- i = j - 1;
- err_val_name = buf;
- break;
- }
- error ("incomplete CASE - %s not handled", err_val_name);
- }
- }
-}
-
-void
-check_missing_cases (type)
- tree type;
-{
- int is_sparse;
- /* For each possible selector value. a one iff it has been matched
- by a case value alternative. */
- unsigned char *cases_seen;
- /* The number of possible selector values. */
- HOST_WIDE_INT size = all_cases_count (type, &is_sparse);
- HOST_WIDE_INT bytes_needed
- = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
-
- if (size == -1)
- warning ("CASE selector with variable range");
- else if (size < 0 || size > 600000
- /* We deliberately use malloc here - not xmalloc. */
- || (cases_seen = (char*) malloc (bytes_needed)) == NULL)
- warning ("too many cases to do CASE completeness testing");
- else
- {
- memset (cases_seen, 0, bytes_needed);
- mark_seen_cases (type, cases_seen, size, is_sparse);
- print_missing_cases (type, cases_seen, size);
- free (cases_seen);
- }
-}
-
-/*
- * We build an expression tree here because, in many contexts,
- * we don't know the type of result that's desired. By the
- * time we get to expanding the tree, we do know.
- */
-tree
-build_chill_case_expr (exprlist, casealtlist_expr,
- optelsecase_expr)
- tree exprlist, casealtlist_expr, optelsecase_expr;
-{
- return build (CASE_EXPR, NULL_TREE, exprlist,
- optelsecase_expr ?
- tree_cons (NULL_TREE,
- optelsecase_expr,
- casealtlist_expr) :
- casealtlist_expr);
-}
-
-/* This function transforms the selector_list and alternatives into a COND_EXPR. */
-tree
-build_chill_multi_dimension_case_expr (selector_list, alternatives, else_expr)
- tree selector_list, alternatives, else_expr;
-{
- tree expr;
-
- selector_list = check_case_selector_list (selector_list);
-
- if (alternatives == NULL_TREE)
- return NULL_TREE;
-
- alternatives = nreverse (alternatives);
- /* alternatives represents the CASE label specifications and resulting values in
- the reverse order in which they appeared.
- If there is an ELSE expression, then use it. If there is no
- ELSE expression, make the last alternative (which is the first in the list)
- into the ELSE expression. This is safe because, if the CASE is complete
- (as required), then the last condition need not be checked anyway. */
- if (else_expr != NULL_TREE)
- expr = else_expr;
- else
- {
- expr = TREE_VALUE (alternatives);
- alternatives = TREE_CHAIN (alternatives);
- }
-
- for ( ; alternatives != NULL_TREE; alternatives = TREE_CHAIN (alternatives))
- {
- tree value = TREE_VALUE (alternatives);
- tree labels = TREE_PURPOSE (alternatives);
- tree cond = build_multi_case_selector_expression(selector_list, labels);
- expr = build_nt (COND_EXPR, cond, value, expr);
- }
-
- return expr;
-}
-
-
-/* This is called with the assumption that RHS has been stabilized.
- It has one purpose: to iterate through the CHILL list of LHS's */
-void
-expand_assignment_action (loclist, modifycode, rhs)
- tree loclist;
- enum chill_tree_code modifycode;
- tree rhs;
-{
- if (loclist == NULL_TREE || TREE_CODE (loclist) == ERROR_MARK
- || rhs == NULL_TREE || TREE_CODE (rhs) == ERROR_MARK)
- return;
-
- if (TREE_CHAIN (loclist) != NULL_TREE)
- { /* Multiple assignment */
- tree target;
- if (TREE_TYPE (rhs) != NULL_TREE)
- rhs = save_expr (rhs);
- else if (TREE_CODE (rhs) == CONSTRUCTOR)
- error ("type of tuple cannot be implicit in multiple assignent");
- else if (TREE_CODE (rhs) == CASE_EXPR || TREE_CODE (rhs) == COND_EXPR)
- error ("conditional expression cannot be used in multiple assignent");
- else
- error ("internal error - unknown type in multiple assignment");
-
- if (modifycode != NOP_EXPR)
- {
- error ("no operator allowed in multiple assignment,");
- modifycode = NOP_EXPR;
- }
-
- for (target = TREE_CHAIN (loclist); target; target = TREE_CHAIN (target))
- {
- if (!CH_EQUIVALENT (TREE_TYPE (TREE_VALUE (target)),
- TREE_TYPE (TREE_VALUE (loclist))))
- {
- error
- ("location modes in multiple assignment are not equivalent");
- break;
- }
- }
- }
- for ( ; loclist != NULL_TREE; loclist = TREE_CHAIN (loclist))
- chill_expand_assignment (TREE_VALUE (loclist), modifycode, rhs);
-}
-
-void
-chill_expand_assignment (lhs, modifycode, rhs)
- tree lhs;
- enum chill_tree_code modifycode;
- tree rhs;
-{
- tree loc;
-
- while (TREE_CODE (lhs) == COMPOUND_EXPR)
- {
- expand_expr (TREE_OPERAND (lhs, 0), const0_rtx, VOIDmode, 0);
- emit_queue ();
- lhs = TREE_OPERAND (lhs, 1);
- }
-
- if (TREE_CODE (lhs) == ERROR_MARK)
- return;
-
- /* errors for assignment to BUFFER, EVENT locations.
- what about SIGNALs? FIXME: Need similar test in
- build_chill_function_call. */
- if (TREE_CODE (lhs) == IDENTIFIER_NODE)
- {
- tree decl = lookup_name (lhs);
- if (decl)
- {
- tree type = TREE_TYPE (decl);
- if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type))
- {
- error ("You may not assign a value to a BUFFER or EVENT location");
- return;
- }
- }
- }
-
- if (TYPE_READONLY_PROPERTY (TREE_TYPE (lhs)) || TREE_READONLY (lhs))
- {
- error ("can't assign value to READonly location");
- return;
- }
- if (CH_TYPE_NONVALUE_P (TREE_TYPE (lhs)))
- {
- error ("cannot assign to location with non-value property");
- return;
- }
-
- if (TREE_CODE (TREE_TYPE (lhs)) == REFERENCE_TYPE)
- lhs = convert_from_reference (lhs);
-
- /* check for lhs is a location */
- loc = lhs;
- while (1)
- {
- if (TREE_CODE (loc) == SLICE_EXPR)
- loc = TREE_OPERAND (loc, 0);
- else if (TREE_CODE (loc) == SET_IN_EXPR)
- loc = TREE_OPERAND (loc, 1);
- else
- break;
- }
- if (! CH_LOCATION_P (loc))
- {
- error ("lefthand side of assignment is not a location");
- return;
- }
-
- /* If a binary op has been requested, combine the old LHS value with
- the RHS producing the value we should actually store into the LHS. */
-
- if (modifycode != NOP_EXPR)
- {
- lhs = stabilize_reference (lhs);
- /* This is to handle border-line cases such
- as: LHS OR := [I]. This seems to be permitted
- by the letter of Z.200, though it violates
- its spirit, since LHS:=LHS OR [I] is
- *not* legal. */
- if (TREE_TYPE (rhs) == NULL_TREE)
- rhs = convert (TREE_TYPE (lhs), rhs);
- rhs = build_chill_binary_op (modifycode, lhs, rhs);
- }
-
- rhs = chill_convert_for_assignment (TREE_TYPE (lhs), rhs, "assignment");
-
- /* handle the LENGTH (vary_array) := expr action */
- loc = lhs;
- if (TREE_CODE (loc) == NOP_EXPR)
- loc = TREE_OPERAND (loc, 0);
- if (TREE_CODE (loc) == COMPONENT_REF
- && chill_varying_type_p (TREE_TYPE (TREE_OPERAND (loc, 0)))
- && DECL_NAME (TREE_OPERAND (loc, 1)) == var_length_id)
- {
- expand_varying_length_assignment (TREE_OPERAND (loc, 0), rhs);
- }
- else if (TREE_CODE (lhs) == SLICE_EXPR)
- {
- tree func = lookup_name (get_identifier ("__pscpy"));
- tree dst = TREE_OPERAND (lhs, 0);
- tree dst_offset = TREE_OPERAND (lhs, 1);
- tree length = TREE_OPERAND (lhs, 2);
- tree src, src_offset;
- if (TREE_CODE (rhs) == SLICE_EXPR)
- {
- src = TREE_OPERAND (rhs, 0);
- /* Should check that the TREE_OPERAND (src, 0) is
- the same as length and powerserlen (src). FIXME */
- src_offset = TREE_OPERAND (rhs, 1);
- }
- else
- {
- src = rhs;
- src_offset = integer_zero_node;
- }
- expand_expr_stmt (build_chill_function_call (func,
- tree_cons (NULL_TREE, force_addr_of (dst),
- tree_cons (NULL_TREE, powersetlen (dst),
- tree_cons (NULL_TREE, convert (long_unsigned_type_node, dst_offset),
- tree_cons (NULL_TREE, force_addr_of (src),
- tree_cons (NULL_TREE, powersetlen (src),
- tree_cons (NULL_TREE, convert (long_unsigned_type_node, src_offset),
- tree_cons (NULL_TREE, convert (long_unsigned_type_node, length),
- NULL_TREE)))))))));
- }
-
- else if (TREE_CODE (lhs) == SET_IN_EXPR)
- {
- tree from_pos = save_expr (TREE_OPERAND (lhs, 0));
- tree set = TREE_OPERAND (lhs, 1);
- tree domain = TYPE_DOMAIN (TREE_TYPE (set));
- tree set_length
- = fold (build (PLUS_EXPR, integer_type_node,
- fold (build (MINUS_EXPR, integer_type_node,
- TYPE_MAX_VALUE (domain),
- TYPE_MIN_VALUE (domain))),
- integer_one_node));
- tree filename = force_addr_of (get_chill_filename());
-
- if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE)
- sorry("bitstring slice");
- expand_expr_stmt (
- build_chill_function_call (lookup_name (
- get_identifier ("__setbitpowerset")),
- tree_cons (NULL_TREE, build_chill_addr_expr (set, "powerset"),
- tree_cons (NULL_TREE, set_length,
- tree_cons (NULL_TREE, TYPE_MIN_VALUE (domain),
- tree_cons (NULL_TREE, convert (long_integer_type_node, from_pos),
- tree_cons (NULL_TREE, rhs,
- tree_cons (NULL_TREE, filename,
- tree_cons (NULL_TREE, get_chill_linenumber(),
- NULL_TREE)))))))));
- }
-
- /* Handle arrays of packed bitfields. Currently, this is limited to bitfields
- which are 1 bit wide, so use the powerset runtime function. */
- else if (TREE_CODE (lhs) == PACKED_ARRAY_REF)
- {
- tree from_pos = save_expr (TREE_OPERAND (lhs, 1));
- tree array = TREE_OPERAND (lhs, 0);
- tree domain = TYPE_DOMAIN (TREE_TYPE (array));
- tree array_length = powersetlen (array);
- tree filename = force_addr_of (get_chill_filename());
- expand_expr_stmt (
- build_chill_function_call (lookup_name (
- get_identifier ("__setbitpowerset")),
- tree_cons (NULL_TREE, build_chill_addr_expr (array, "packed bitfield array"),
- tree_cons (NULL_TREE, convert (long_unsigned_type_node, array_length),
- tree_cons (NULL_TREE, convert (long_integer_type_node,
- TYPE_MIN_VALUE (domain)),
- tree_cons (NULL_TREE, convert (long_integer_type_node, from_pos),
- tree_cons (NULL_TREE, build1 (CONVERT_EXPR, boolean_type_node, rhs),
- tree_cons (NULL_TREE, filename,
- tree_cons (NULL_TREE, get_chill_linenumber(),
- NULL_TREE)))))))));
- }
-
- /* The following is probably superceded by the
- above code for SET_IN_EXPR. FIXME! */
- else if (TREE_CODE (lhs) == BIT_FIELD_REF)
- {
- tree set = TREE_OPERAND (lhs, 0);
- tree numbits = TREE_OPERAND (lhs, 1);
- tree from_pos = save_expr (TREE_OPERAND (lhs, 2));
- tree domain = TYPE_DOMAIN (TREE_TYPE (set));
- tree set_length
- = fold (build (PLUS_EXPR, integer_type_node,
- fold (build (MINUS_EXPR, integer_type_node,
- TYPE_MAX_VALUE (domain),
- TYPE_MIN_VALUE (domain))),
- integer_one_node));
- tree filename = force_addr_of (get_chill_filename());
- tree to_pos;
-
- switch (TREE_CODE (TREE_TYPE (rhs)))
- {
- case SET_TYPE:
- to_pos = fold (build (MINUS_EXPR, integer_type_node,
- fold (build (PLUS_EXPR, integer_type_node,
- from_pos, numbits)),
- integer_one_node));
- break;
- case BOOLEAN_TYPE:
- to_pos = from_pos;
- break;
- default:
- abort ();
- }
-
- if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE)
- sorry("bitstring slice");
- expand_expr_stmt (
- build_chill_function_call( lookup_name (
- get_identifier ("__setbitpowerset")),
- tree_cons (NULL_TREE, build_chill_addr_expr (set, "powerset"),
- tree_cons (NULL_TREE, set_length,
- tree_cons (NULL_TREE, TYPE_MIN_VALUE (domain),
- tree_cons (NULL_TREE, from_pos,
- tree_cons (NULL_TREE, rhs,
- tree_cons (NULL_TREE, filename,
- tree_cons (NULL_TREE, get_chill_linenumber(),
- NULL_TREE)))))))));
- }
-
- else
- expand_expr_stmt (build_chill_modify_expr (lhs, rhs));
-}
-
-/* Also assumes that rhs has been stabilized */
-void
-expand_varying_length_assignment (lhs, rhs)
- tree lhs, rhs;
-{
- tree base_array, min_domain_val;
-
- pedwarn ("LENGTH on left-hand-side is non-portable");
-
- if (! CH_LOCATION_P (lhs))
- {
- error ("Can only set LENGTH of array location");
- return;
- }
-
- /* cause a RANGE exception if rhs would cause a 'hole' in the array. */
- rhs = valid_array_index_p (lhs, rhs, "new array length too large", 1);
-
- base_array = CH_VARYING_ARRAY_TYPE (TREE_TYPE (lhs));
- min_domain_val = TYPE_MIN_VALUE (TYPE_DOMAIN (base_array));
-
- lhs = build_component_ref (lhs, var_length_id);
- rhs = fold (build (MINUS_EXPR, TREE_TYPE (rhs), rhs, min_domain_val));
-
- expand_expr_stmt (build_chill_modify_expr (lhs, rhs));
-}
-
-void
-push_action ()
-{
- push_handler ();
- if (ignoring)
- return;
- emit_line_note (input_filename, lineno);
-}