diff options
Diffstat (limited to 'gcc/ch/expr.c')
-rw-r--r-- | gcc/ch/expr.c | 4512 |
1 files changed, 0 insertions, 4512 deletions
diff --git a/gcc/ch/expr.c b/gcc/ch/expr.c deleted file mode 100644 index da92ab9614b..00000000000 --- a/gcc/ch/expr.c +++ /dev/null @@ -1,4512 +0,0 @@ -/* Convert language-specific tree expression to rtl instructions, - for GNU CHILL compiler. - Copyright (C) 1992, 1993, 1994, 1998, 1999, 2000, 2001 - 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 "config.h" -#include "system.h" -#include "rtl.h" -#include "tree.h" -#include "flags.h" -#include "expr.h" -#include "ch-tree.h" -#include "assert.h" -#include "lex.h" -#include "convert.h" -#include "toplev.h" - -extern char **boolean_code_name; -extern int flag_old_strings; -extern int ignore_case; -extern int special_UC; - -/* definitions for duration built-ins */ -#define MILLISECS_MULTIPLIER 1 -#define SECS_MULTIPLIER MILLISECS_MULTIPLIER * 1000 -#define MINUTES_MULTIPLIER SECS_MULTIPLIER * 60 -#define HOURS_MULTIPLIER MINUTES_MULTIPLIER * 60 -#define DAYS_MULTIPLIER HOURS_MULTIPLIER * 24 - -/* the maximum value for each of the calls */ -#define MILLISECS_MAX 0xffffffff -#define SECS_MAX 4294967 -#define MINUTES_MAX 71582 -#define HOURS_MAX 1193 -#define DAYS_MAX 49 - -/* forward declarations */ -static rtx chill_expand_expr PARAMS ((tree, rtx, enum machine_mode, - enum expand_modifier)); -static tree chill_expand_case_expr PARAMS ((tree)); -static int check_arglist_length PARAMS ((tree, int, int, tree)); -static tree internal_build_compound_expr PARAMS ((tree, int)); -static int is_really_instance PARAMS ((tree)); -static int invalid_operand PARAMS ((enum chill_tree_code, - tree, int)); -static int invalid_right_operand PARAMS ((enum chill_tree_code, tree)); -static tree build_chill_abstime PARAMS ((tree)); -static tree build_allocate_memory_call PARAMS ((tree, tree)); -static tree build_allocate_global_memory_call PARAMS ((tree, tree)); -static tree build_return_memory PARAMS ((tree)); -static tree build_chill_duration PARAMS ((tree, unsigned long, - tree, unsigned long)); -static tree build_chill_floatcall PARAMS ((tree, const char *, - const char *)); -static tree build_allocate_getstack PARAMS ((tree, tree, const char *, - const char *, tree, tree)); -static tree build_chill_allocate PARAMS ((tree, tree)); -static tree build_chill_getstack PARAMS ((tree, tree)); -static tree build_chill_terminate PARAMS ((tree)); -static tree build_chill_inttime PARAMS ((tree, tree)); -static tree build_chill_lower_or_upper PARAMS ((tree, int)); -static tree build_max_min PARAMS ((tree, int)); -static tree build_chill_pred_or_succ PARAMS ((tree, enum tree_code)); -static tree expand_packed_set PARAMS ((const char *, int, tree)); -static tree fold_set_expr PARAMS ((enum chill_tree_code, - tree, tree)); -static tree build_compare_set_expr PARAMS ((enum tree_code, tree, tree)); -static tree scalar_to_string PARAMS ((tree)); -static tree build_concat_expr PARAMS ((tree, tree)); -static tree build_compare_string_expr PARAMS ((enum tree_code, tree, tree)); -static tree compare_records PARAMS ((tree, tree)); -static tree string_char_rep PARAMS ((int, tree)); -static tree build_boring_bitstring PARAMS ((long, int)); - -/* variable to hold the type the DESCR built-in returns */ -static tree descr_type = NULL_TREE; - - -/* called from ch-lex.l */ -void -init_chill_expand () -{ - lang_expand_expr = chill_expand_expr; -} - -/* Take the address of something that needs to be passed by reference. */ -tree -force_addr_of (value) - tree value; -{ - /* FIXME. Move to memory, if needed. */ - if (TREE_CODE (value) == INDIRECT_REF) - return convert_to_pointer (ptr_type_node, TREE_OPERAND (value, 0)); - mark_addressable (value); - return build1 (ADDR_EXPR, ptr_type_node, value); -} - -/* Check that EXP has a known type. */ - -tree -check_have_mode (exp, context) - tree exp; - const char *context; -{ - if (TREE_CODE (exp) != ERROR_MARK && TREE_TYPE (exp) == NULL_TREE) - { - if (TREE_CODE (exp) == CONSTRUCTOR) - error ("tuple without specified mode not allowed in %s", context); - else if (TREE_CODE (exp) == COND_EXPR || TREE_CODE (exp) == CASE_EXPR) - error ("conditional expression not allowed in %s", context); - else - error ("internal error: unknown expression mode in %s", context); - - return error_mark_node; - } - return exp; -} - -/* Check that EXP is discrete. Handle conversion if flag_old_strings. */ - -tree -check_case_selector (exp) - tree exp; -{ - if (exp != NULL_TREE && TREE_TYPE (exp) != NULL_TREE) - exp = convert_to_discrete (exp); - if (exp) - return exp; - error ("CASE selector is not a discrete expression"); - return error_mark_node; -} - -tree -check_case_selector_list (list) - tree list; -{ - tree selector, exp, return_list = NULL_TREE; - - for (selector = list; selector != NULL_TREE; selector = TREE_CHAIN (selector)) - { - exp = check_case_selector (TREE_VALUE (selector)); - if (exp == error_mark_node) - { - return_list = error_mark_node; - break; - } - return_list = tree_cons (TREE_PURPOSE (selector), exp, return_list); - } - - return nreverse(return_list); -} - -static tree -chill_expand_case_expr (expr) - tree expr; -{ - tree selector_list = TREE_OPERAND (expr, 0), selector; - tree alternatives = TREE_OPERAND (expr, 1); - tree type = TREE_TYPE (expr); - int else_seen = 0; - tree result; - - if (TREE_CODE (selector_list) != TREE_LIST - || TREE_CODE (alternatives) != TREE_LIST) - abort(); - if (TREE_CHAIN (selector_list) != NULL_TREE) - abort (); - - /* make a temp for the case result */ - result = decl_temp1 (get_unique_identifier ("CASE_EXPR"), - type, 0, NULL_TREE, 0, 0); - - selector = check_case_selector (TREE_VALUE (selector_list)); - - expand_start_case (1, selector, TREE_TYPE (selector), "CASE expression"); - - alternatives = nreverse (alternatives); - for ( ; alternatives != NULL_TREE; alternatives = TREE_CHAIN (alternatives)) - { - tree labels = TREE_PURPOSE (alternatives), t; - - if (labels == NULL_TREE) - { - chill_handle_case_default (); - else_seen++; - } - else - { - tree label; - if (labels != NULL_TREE) - { - for (label = TREE_VALUE (labels); - label != NULL_TREE; label = TREE_CHAIN (label)) - chill_handle_case_label (TREE_VALUE (label), selector); - labels = TREE_CHAIN (labels); - if (labels != NULL_TREE) - error ("The number of CASE selectors does not match the number of CASE label lists"); - - } - } - - t = build (MODIFY_EXPR, type, result, - convert (type, TREE_VALUE (alternatives))); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr_stmt (t); - expand_exit_something (); - } - - if (!else_seen) - { - chill_handle_case_default (); - expand_exit_something (); -#if 0 - expand_raise (); -#endif - - check_missing_cases (TREE_TYPE (selector)); - } - - expand_end_case (selector); - return result; -} - -/* Hook used by expand_expr to expand CHILL-specific tree codes. */ - -static rtx -chill_expand_expr (exp, target, tmode, modifier) - tree exp; - rtx target; - enum machine_mode tmode; - enum expand_modifier modifier; -{ - tree type = TREE_TYPE (exp); - register enum machine_mode mode = TYPE_MODE (type); - register enum tree_code code = TREE_CODE (exp); - rtx original_target = target; - rtx op0, op1; - int ignore = target == const0_rtx; - const char *lib_func; /* name of library routine */ - - if (ignore) - target = 0, original_target = 0; - - /* No sense saving up arithmetic to be done - if it's all in the wrong mode to form part of an address. - And force_operand won't know whether to sign-extend or zero-extend. */ - - if (mode != Pmode && modifier == EXPAND_SUM) - modifier = EXPAND_NORMAL; - - switch (code) - { - case STRING_EQ_EXPR: - case STRING_LT_EXPR: - { - rtx func = gen_rtx (SYMBOL_REF, Pmode, - code == STRING_EQ_EXPR ? "__eqstring" - : "__ltstring"); - tree exp0 = TREE_OPERAND (exp, 0); - tree exp1 = TREE_OPERAND (exp, 1); - tree size0, size1; - rtx op0, op1, siz0, siz1; - if (chill_varying_type_p (TREE_TYPE (exp0))) - { - exp0 = save_if_needed (exp0); - size0 = convert (integer_type_node, - build_component_ref (exp0, var_length_id)); - exp0 = build_component_ref (exp0, var_data_id); - } - else - size0 = size_in_bytes (TREE_TYPE (exp0)); - if (chill_varying_type_p (TREE_TYPE (exp1))) - { - exp1 = save_if_needed (exp1); - size1 = convert (integer_type_node, - build_component_ref (exp1, var_length_id)); - exp1 = build_component_ref (exp1, var_data_id); - } - else - size1 = size_in_bytes (TREE_TYPE (exp1)); - - op0 = expand_expr (force_addr_of (exp0), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - op1 = expand_expr (force_addr_of (exp1), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - siz0 = expand_expr (size0, NULL_RTX, VOIDmode, 0); - siz1 = expand_expr (size1, NULL_RTX, VOIDmode, 0); - return emit_library_call_value (func, target, - 0, QImode, 4, - op0, GET_MODE (op0), - siz0, TYPE_MODE (sizetype), - op1, GET_MODE (op1), - siz1, TYPE_MODE (sizetype)); - } - - case CASE_EXPR: - return expand_expr (chill_expand_case_expr (exp), - NULL_RTX, VOIDmode, 0); - break; - - case SLICE_EXPR: - { - tree func_call; - tree array = TREE_OPERAND (exp, 0); - tree min_value = TREE_OPERAND (exp, 1); - tree length = TREE_OPERAND (exp, 2); - tree new_type = TREE_TYPE (exp); - tree temp = decl_temp1 (get_unique_identifier ("BITSTRING"), - new_type, 0, NULL_TREE, 0, 0); - if (! CH_REFERABLE (array) && TYPE_MODE (TREE_TYPE (array)) != BLKmode) - array = decl_temp1 (get_unique_identifier ("BSTRINGVAL"), - TREE_TYPE (array), 0, array, 0, 0); - func_call = build_chill_function_call ( - lookup_name (get_identifier ("__psslice")), - tree_cons (NULL_TREE, - build_chill_addr_expr (temp, (char *)0), - tree_cons (NULL_TREE, length, - tree_cons (NULL_TREE, - force_addr_of (array), - tree_cons (NULL_TREE, powersetlen (array), - tree_cons (NULL_TREE, convert (integer_type_node, min_value), - tree_cons (NULL_TREE, length, NULL_TREE))))))); - expand_expr (func_call, const0_rtx, VOIDmode, 0); - emit_queue (); - return expand_expr (temp, ignore ? const0_rtx : target, - VOIDmode, 0); - } - - /* void __concatstring (char *out, char *left, unsigned left_len, - char *right, unsigned right_len) */ - case CONCAT_EXPR: - { - tree exp0 = TREE_OPERAND (exp, 0); - tree exp1 = TREE_OPERAND (exp, 1); - rtx size0 = NULL_RTX, size1 = NULL_RTX; - rtx targetx; - - if (TREE_CODE (exp1) == UNDEFINED_EXPR) - { - if (TYPE_MODE (TREE_TYPE (exp0)) == BLKmode - && TYPE_MODE (TREE_TYPE (exp)) == BLKmode) - { - rtx temp = expand_expr (exp0, target, tmode, modifier); - if (temp == target || target == NULL_RTX) - return temp; - emit_block_move (target, temp, expr_size (exp0), - TYPE_ALIGN (TREE_TYPE(exp0))); - return target; - } - else - { - exp0 = force_addr_of (exp0); - exp0 = convert (build_pointer_type (TREE_TYPE (exp)), exp0); - exp0 = build1 (INDIRECT_REF, TREE_TYPE (exp), exp0); - return expand_expr (exp0, - NULL_RTX, Pmode, EXPAND_CONST_ADDRESS); - } - } - - if (TREE_CODE (type) == ARRAY_TYPE) - { - /* No need to handle scalars or varying strings here, since that - was done in convert or build_concat_expr. */ - size0 = expand_expr (size_in_bytes (TREE_TYPE (exp0)), - NULL_RTX, Pmode, EXPAND_CONST_ADDRESS); - - size1 = expand_expr (size_in_bytes (TREE_TYPE (exp1)), - NULL_RTX, Pmode, EXPAND_CONST_ADDRESS); - - /* build a temp for the result, target is its address */ - if (target == NULL_RTX) - { - tree type0 = TREE_TYPE (exp0); - tree type1 = TREE_TYPE (exp1); - HOST_WIDE_INT len0 = int_size_in_bytes (type0); - HOST_WIDE_INT len1 = int_size_in_bytes (type1); - - if (len0 < 0 && TYPE_ARRAY_MAX_SIZE (type0) - && host_integerp (TYPE_ARRAY_MAX_SIZE (type0), 1)) - len0 = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type0), 1); - - if (len1 < 0 && TYPE_ARRAY_MAX_SIZE (type1) - && host_integerp (TYPE_ARRAY_MAX_SIZE (type1), 1)) - len1 = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type1), 1); - - if (len0 < 0 || len1 < 0) - abort (); - - target = assign_stack_temp (mode, len0 + len1, 0); - preserve_temp_slots (target); - } - } - else if (TREE_CODE (type) == SET_TYPE) - { - if (target == NULL_RTX) - { - target = assign_stack_temp (mode, int_size_in_bytes (type), 0); - preserve_temp_slots (target); - } - } - else - abort (); - - if (GET_CODE (target) == MEM) - targetx = target; - else - targetx = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0); - - /* expand 1st operand to a pointer to the array */ - op0 = expand_expr (force_addr_of (exp0), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - - /* expand 2nd operand to a pointer to the array */ - op1 = expand_expr (force_addr_of (exp1), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - - if (TREE_CODE (type) == SET_TYPE) - { - size0 = expand_expr (powersetlen (exp0), - NULL_RTX, VOIDmode, 0); - size1 = expand_expr (powersetlen (exp1), - NULL_RTX, VOIDmode, 0); - - emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__concatps"), - 0, Pmode, 5, XEXP (targetx, 0), Pmode, - op0, GET_MODE (op0), - convert_to_mode (TYPE_MODE (sizetype), - size0, TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype), - op1, GET_MODE (op1), - convert_to_mode (TYPE_MODE (sizetype), - size1, TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); - } - else - { - /* copy left, then right array to target */ - emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__concatstring"), - 0, Pmode, 5, XEXP (targetx, 0), Pmode, - op0, GET_MODE (op0), - convert_to_mode (TYPE_MODE (sizetype), - size0, TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype), - op1, GET_MODE (op1), - convert_to_mode (TYPE_MODE (sizetype), - size1, TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); - } - if (targetx != target) - emit_move_insn (target, targetx); - return target; - } - - /* FIXME: the set_length computed below is a compile-time constant; - you'll need to re-write that part for VARYING bit arrays, and - possibly the set pointer will need to be adjusted to point past - the word containing its dynamic length. */ - - /* void __notpowerset (char *out, char *src, - unsigned long bitlength) */ - case SET_NOT_EXPR: - { - - tree expr = TREE_OPERAND (exp, 0); - tree tsize = powersetlen (expr); - rtx targetx; - - if (TREE_CODE (TREE_TYPE (expr)) != SET_TYPE) - tsize = fold (build (MULT_EXPR, sizetype, tsize, - size_int (BITS_PER_UNIT))); - - /* expand 1st operand to a pointer to the set */ - op0 = expand_expr (force_addr_of (expr), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - - /* build a temp for the result, target is its address */ - if (target == NULL_RTX) - { - target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), - int_size_in_bytes (TREE_TYPE (exp)), - 0); - preserve_temp_slots (target); - } - if (GET_CODE (target) == MEM) - targetx = target; - else - targetx = assign_stack_temp (GET_MODE (target), - GET_MODE_SIZE (GET_MODE (target)), - 0); - emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__notpowerset"), - 0, VOIDmode, 3, XEXP (targetx, 0), Pmode, - op0, GET_MODE (op0), - expand_expr (tsize, NULL_RTX, MEM, - EXPAND_CONST_ADDRESS), - TYPE_MODE (long_unsigned_type_node)); - if (targetx != target) - emit_move_insn (target, targetx); - return target; - } - - case SET_DIFF_EXPR: - lib_func = "__diffpowerset"; - goto format_2; - - case SET_IOR_EXPR: - lib_func = "__orpowerset"; - goto format_2; - - case SET_XOR_EXPR: - lib_func = "__xorpowerset"; - goto format_2; - - /* void __diffpowerset (char *out, char *left, char *right, - unsigned bitlength) */ - case SET_AND_EXPR: - lib_func = "__andpowerset"; - format_2: - { - tree expr = TREE_OPERAND (exp, 0); - tree tsize = powersetlen (expr); - rtx targetx; - - if (TREE_CODE (TREE_TYPE (expr)) != SET_TYPE) - tsize = fold (build (MULT_EXPR, long_unsigned_type_node, - tsize, - size_int (BITS_PER_UNIT))); - - /* expand 1st operand to a pointer to the set */ - op0 = expand_expr (force_addr_of (expr), - NULL_RTX, MEM, EXPAND_CONST_ADDRESS); - - /* expand 2nd operand to a pointer to the set */ - op1 = expand_expr (force_addr_of (TREE_OPERAND (exp, 1)), - NULL_RTX, MEM, - EXPAND_CONST_ADDRESS); - -/* FIXME: re-examine this code - the unary operator code above has recently - (93/03/12) been changed a lot. Should this code also change? */ - /* build a temp for the result, target is its address */ - if (target == NULL_RTX) - { - target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), - int_size_in_bytes (TREE_TYPE (exp)), - 0); - preserve_temp_slots (target); - } - if (GET_CODE (target) == MEM) - targetx = target; - else - targetx = assign_stack_temp (GET_MODE (target), - GET_MODE_SIZE (GET_MODE (target)), 0); - emit_library_call (gen_rtx(SYMBOL_REF, Pmode, lib_func), - 0, VOIDmode, 4, XEXP (targetx, 0), Pmode, - op0, GET_MODE (op0), op1, GET_MODE (op1), - expand_expr (tsize, NULL_RTX, MEM, - EXPAND_CONST_ADDRESS), - TYPE_MODE (long_unsigned_type_node)); - if (target != targetx) - emit_move_insn (target, targetx); - return target; - } - - case SET_IN_EXPR: - { - tree set = TREE_OPERAND (exp, 1); - tree pos = convert (long_unsigned_type_node, TREE_OPERAND (exp, 0)); - tree set_type = TREE_TYPE (set); - tree set_length = discrete_count (TYPE_DOMAIN (set_type)); - tree min_val = convert (long_integer_type_node, - TYPE_MIN_VALUE (TYPE_DOMAIN (set_type))); - tree fcall; - - /* FIXME: Function-call not needed if pos and width are constant! */ - if (! mark_addressable (set)) - { - error ("powerset is not addressable"); - return const0_rtx; - } - /* we use different functions for bitstrings and powersets */ - if (CH_BOOLS_TYPE_P (set_type)) - fcall = - build_chill_function_call ( - lookup_name (get_identifier ("__inbitstring")), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, pos), - tree_cons (NULL_TREE, - build1 (ADDR_EXPR, build_pointer_type (set_type), set), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, set_length), - tree_cons (NULL_TREE, min_val, - tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - build_tree_list (NULL_TREE, get_chill_linenumber ()))))))); - else - fcall = - build_chill_function_call ( - lookup_name (get_identifier ("__inpowerset")), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, pos), - tree_cons (NULL_TREE, - build1 (ADDR_EXPR, build_pointer_type (set_type), set), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, set_length), - build_tree_list (NULL_TREE, min_val))))); - return expand_expr (fcall, NULL_RTX, VOIDmode, 0); - } - - case PACKED_ARRAY_REF: - { - tree array = TREE_OPERAND (exp, 0); - tree pos = save_expr (TREE_OPERAND (exp, 1)); - tree array_type = TREE_TYPE (array); - tree array_length = discrete_count (TYPE_DOMAIN (array_type)); - tree min_val = convert (long_integer_type_node, - TYPE_MIN_VALUE (TYPE_DOMAIN (array_type))); - tree fcall; - - /* FIXME: Function-call not needed if pos and width are constant! */ - /* TODO: make sure this makes sense. */ - if (! mark_addressable (array)) - { - error ("array is not addressable"); - return const0_rtx; - } - fcall = - build_chill_function_call ( - lookup_name (get_identifier ("__inpowerset")), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, pos), - tree_cons (NULL_TREE, - build1 (ADDR_EXPR, build_pointer_type (array_type), array), - tree_cons (NULL_TREE, - convert (long_unsigned_type_node, array_length), - build_tree_list (NULL_TREE, min_val))))); - return expand_expr (fcall, NULL_RTX, VOIDmode, 0); - } - - case UNDEFINED_EXPR: - if (target == 0) - { - target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), - int_size_in_bytes (TREE_TYPE (exp)), 0); - preserve_temp_slots (target); - } - /* We don't actually need to *do* anything ... */ - return target; - - default: - break; - } - - /* NOTREACHED */ - return NULL; -} - -/* Check that the argument list has a length in [min_length .. max_length]. - (max_length == -1 means "infinite".) - If so return the actual length. - Otherwise, return an error message and return -1. */ - -static int -check_arglist_length (args, min_length, max_length, name) - tree args; - int min_length; - int max_length; - tree name; -{ - int length = list_length (args); - if (length < min_length) - error ("too few arguments in call to `%s'", IDENTIFIER_POINTER (name)); - else if (max_length != -1 && length > max_length) - error ("too many arguments in call to `%s'", IDENTIFIER_POINTER (name)); - else - return length; - return -1; -} - -/* - * This is the code from c-typeck.c, with the C-specific cruft - * removed (possibly I just didn't understand it, but it was - * apparently simply discarding part of my LIST). - */ -static tree -internal_build_compound_expr (list, first_p) - tree list; - int first_p ATTRIBUTE_UNUSED; -{ - register tree rest; - - if (TREE_CHAIN (list) == 0) - return TREE_VALUE (list); - - rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); - - if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) - return rest; - - return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); -} - - -/* Given a list of expressions, return a compound expression - that performs them all and returns the value of the last of them. */ -/* FIXME: this should be merged with the C version */ -tree -build_chill_compound_expr (list) - tree list; -{ - return internal_build_compound_expr (list, TRUE); -} - -/* Given an expression PTR for a pointer, return an expression - for the value pointed to. - do_empty_check is 0, don't perform a NULL pointer check, - else do it. */ - -tree -build_chill_indirect_ref (ptr, mode, do_empty_check) - tree ptr; - tree mode; - int do_empty_check; -{ - register tree type; - - if (ptr == NULL_TREE || TREE_CODE (ptr) == ERROR_MARK) - return ptr; - if (mode != NULL_TREE && TREE_CODE (mode) == ERROR_MARK) - return error_mark_node; - - type = TREE_TYPE (ptr); - - if (TREE_CODE (type) == REFERENCE_TYPE) - { - type = TREE_TYPE (type); - ptr = convert (type, ptr); - } - - /* check for ptr is really a POINTER */ - if (TREE_CODE (type) != POINTER_TYPE) - { - error ("cannot dereference, not a pointer"); - return error_mark_node; - } - - if (mode && TREE_CODE (mode) == IDENTIFIER_NODE) - { - tree decl = lookup_name (mode); - if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL) - { - if (pass == 2) - error ("missing '.' operator or undefined mode name `%s'", - IDENTIFIER_POINTER (mode)); -#if 0 - error ("you have forgotten the '.' operator which must"); - error (" precede a STRUCT field reference, or `%s' is an undefined mode", - IDENTIFIER_POINTER (mode)); -#endif - return error_mark_node; - } - } - - if (mode) - { - mode = get_type_of (mode); - ptr = convert (build_pointer_type (mode), ptr); - } - else if (type == ptr_type_node) - { - error ("can't dereference PTR value using unary `->'"); - return error_mark_node; - } - - if (do_empty_check) - ptr = check_non_null (ptr); - - type = TREE_TYPE (ptr); - - if (TREE_CODE (type) == POINTER_TYPE) - { - if (TREE_CODE (ptr) == ADDR_EXPR - && !flag_volatile - && (TREE_TYPE (TREE_OPERAND (ptr, 0)) - == TREE_TYPE (type))) - return TREE_OPERAND (ptr, 0); - else - { - tree t = TREE_TYPE (type); - register tree ref = build1 (INDIRECT_REF, - TYPE_MAIN_VARIANT (t), ptr); - - if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE) - { - error ("dereferencing pointer to incomplete type"); - return error_mark_node; - } - if (TREE_CODE (t) == VOID_TYPE) - warning ("dereferencing `void *' pointer"); - - /* We *must* set TREE_READONLY when dereferencing a pointer to const, - so that we get the proper error message if the result is used - to assign to. Also, &* is supposed to be a no-op. - And ANSI C seems to specify that the type of the result - should be the const type. */ - /* A de-reference of a pointer to const is not a const. It is valid - to change it via some other pointer. */ - TREE_READONLY (ref) = TYPE_READONLY (t); - TREE_SIDE_EFFECTS (ref) - = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (ptr) || flag_volatile; - TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t) || flag_volatile; - return ref; - } - } - else if (TREE_CODE (ptr) != ERROR_MARK) - error ("invalid type argument of `->'"); - return error_mark_node; -} - -/* NODE is a COMPONENT_REF whose mode is an IDENTIFIER, - which is replaced by the proper FIELD_DECL. - Also do the right thing for variant records. */ - -tree -resolve_component_ref (node) - tree node; -{ - tree datum = TREE_OPERAND (node, 0); - tree field_name = TREE_OPERAND (node, 1); - tree type = TREE_TYPE (datum); - tree field; - if (TREE_CODE (datum) == ERROR_MARK) - return error_mark_node; - if (TREE_CODE (type) == REFERENCE_TYPE) - { - type = TREE_TYPE (type); - TREE_OPERAND (node, 0) = datum = convert (type, datum); - } - if (TREE_CODE (type) != RECORD_TYPE) - { - error ("operand of '.' is not a STRUCT"); - return error_mark_node; - } - - TREE_READONLY (node) = TREE_READONLY (datum); - TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (datum); - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - if (TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree variant; - for (variant = TYPE_FIELDS (TREE_TYPE (field)); - variant; variant = TREE_CHAIN (variant)) - { - tree vfield; - for (vfield = TYPE_FIELDS (TREE_TYPE (variant)); - vfield; vfield = TREE_CHAIN (vfield)) - { - if (DECL_NAME (vfield) == field_name) - { /* Found a variant field */ - datum = build (COMPONENT_REF, TREE_TYPE (field), - datum, field); - datum = build (COMPONENT_REF, TREE_TYPE (variant), - datum, variant); - TREE_OPERAND (node, 0) = datum; - TREE_OPERAND (node, 1) = vfield; - TREE_TYPE (node) = TREE_TYPE (vfield); - TREE_READONLY (node) |= TYPE_READONLY (TREE_TYPE (node)); -#if 0 - if (flag_testing_tags) - { - tree tagtest = NOT IMPLEMENTED; - tree tagf = ridpointers[(int) RID_RANGEFAIL]; - node = check_expression (node, tagtest, - tagf); - } -#endif - return node; - } - } - } - } - - if (DECL_NAME (field) == field_name) - { /* Found a fixed field */ - TREE_OPERAND (node, 1) = field; - TREE_TYPE (node) = TREE_TYPE (field); - TREE_READONLY (node) |= TYPE_READONLY (TREE_TYPE (node)); - return fold (node); - } - } - - error ("no field named `%s'", IDENTIFIER_POINTER (field_name)); - return error_mark_node; -} - -tree -build_component_ref (datum, field_name) - tree datum, field_name; -{ - tree node = build_nt (COMPONENT_REF, datum, field_name); - if (pass != 1) - node = resolve_component_ref (node); - return node; -} - -/* - function checks (for build_chill_component_ref) if a given - type is really an instance type. CH_IS_INSTANCE_MODE is not - strict enough in this case, i.e. SYNMODE foo = STRUCT (a, b UINT) - is compatible to INSTANCE. */ - -static int -is_really_instance (type) - tree type; -{ - tree decl = TYPE_NAME (type); - - if (decl == NULL_TREE) - /* this is not an instance */ - return 0; - - if (DECL_NAME (decl) == ridpointers[(int)RID_INSTANCE]) - /* this is an instance */ - return 1; - - if (TYPE_FIELDS (type) == TYPE_FIELDS (instance_type_node)) - /* we have a NEWMODE'd instance */ - return 1; - - return 0; -} - -/* This function is called by the parse. - Here we check if the user tries to access a field in a type which is - layouted as a structure but isn't like INSTANCE, BUFFER, EVENT, ASSOCIATION, - ACCESS, TEXT, or VARYING array or character string. - We don't do this in build_component_ref cause this function gets - called from the compiler to access fields in one of the above mentioned - modes. */ -tree -build_chill_component_ref (datum, field_name) - tree datum, field_name; -{ - tree type = TREE_TYPE (datum); - if ((type != NULL_TREE && TREE_CODE (type) == RECORD_TYPE) && - ((CH_IS_INSTANCE_MODE (type) && is_really_instance (type)) || - CH_IS_BUFFER_MODE (type) || - CH_IS_EVENT_MODE (type) || CH_IS_ASSOCIATION_MODE (type) || - CH_IS_ACCESS_MODE (type) || CH_IS_TEXT_MODE (type) || - chill_varying_type_p (type))) - { - error ("operand of '.' is not a STRUCT"); - return error_mark_node; - } - return build_component_ref (datum, field_name); -} - -/* - * Check for invalid binary operands & unary operands - * RIGHT is 1 if checking right operand or unary operand; - * it is 0 if checking left operand. - * - * return 1 if the given operand is NOT compatible as the - * operand of the given operator - * - * return 0 if they might be compatible - */ -static int -invalid_operand (code, type, right) - enum chill_tree_code code; - tree type; - int right; /* 1 if right operand */ -{ - switch ((int)code) - { - case ADDR_EXPR: - break; - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_NOT_EXPR: - case BIT_XOR_EXPR: - goto relationals; - case CASE_EXPR: - break; - case CEIL_MOD_EXPR: - goto numerics; - case CONCAT_EXPR: /* must be static or varying char array */ - if (TREE_CODE (type) == CHAR_TYPE) - return 0; - if (TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) - return 0; - if (!chill_varying_type_p (type)) - return 1; - if (TREE_CODE (TREE_TYPE (CH_VARYING_ARRAY_TYPE (type))) - == CHAR_TYPE) - return 0; - else - return 1; - /* note: CHILL conditional expressions (COND_EXPR) won't come - * through here; they're routed straight to C-specific code */ - case EQ_EXPR: - return 0; /* ANYTHING can be compared equal */ - case FLOOR_MOD_EXPR: - if (TREE_CODE (type) == REAL_TYPE) - return 1; - goto numerics; - case GE_EXPR: - case GT_EXPR: - goto relatables; - case SET_IN_EXPR: - if (TREE_CODE (type) == SET_TYPE) - return 0; - else - return 1; - case PACKED_ARRAY_REF: - if (TREE_CODE (type) == ARRAY_TYPE) - return 0; - else - return 1; - case LE_EXPR: - case LT_EXPR: - relatables: - switch ((int)TREE_CODE(type)) /* right operand must be set/bitarray type */ - { - case ARRAY_TYPE: - if (TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) - return 0; - else - return 1; - case BOOLEAN_TYPE: - case CHAR_TYPE: - case COMPLEX_TYPE: - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case OFFSET_TYPE: - case POINTER_TYPE: - case REAL_TYPE: - case SET_TYPE: - return 0; - case FILE_TYPE: - case FUNCTION_TYPE: - case GRANT_TYPE: - case LANG_TYPE: - case METHOD_TYPE: - return 1; - case RECORD_TYPE: - if (chill_varying_type_p (type) - && TREE_CODE (TREE_TYPE (CH_VARYING_ARRAY_TYPE (type))) == CHAR_TYPE) - return 0; - else - return 1; - case REFERENCE_TYPE: - case SEIZE_TYPE: - case UNION_TYPE: - case VOID_TYPE: - return 1; - } - break; - case MINUS_EXPR: - case MULT_EXPR: - goto numerics; - case NEGATE_EXPR: - if (TREE_CODE (type) == BOOLEAN_TYPE) - return 0; - else - goto numerics; - case NE_EXPR: - return 0; /* ANYTHING can be compared unequal */ - case NOP_EXPR: - return 0; /* ANYTHING can be converted */ - case PLUS_EXPR: - numerics: - switch ((int)TREE_CODE(type)) /* left operand must be discrete type */ - { - case ARRAY_TYPE: - if (right || TREE_CODE (TREE_TYPE (type)) != BOOLEAN_TYPE) - return 1; - else - return 0; - case CHAR_TYPE: - return right; - case BOOLEAN_TYPE: - case COMPLEX_TYPE: - case FILE_TYPE: - case FUNCTION_TYPE: - case GRANT_TYPE: - case LANG_TYPE: - case METHOD_TYPE: - case RECORD_TYPE: - case REFERENCE_TYPE: - case SEIZE_TYPE: - case UNION_TYPE: - case VOID_TYPE: - return 1; - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case OFFSET_TYPE: - case POINTER_TYPE: - case REAL_TYPE: - case SET_TYPE: - return 0; - } - break; - case RANGE_EXPR: - break; - - case REPLICATE_EXPR: - switch ((int)TREE_CODE(type)) /* right operand must be set/bitarray type */ - { - case COMPLEX_TYPE: - case FILE_TYPE: - case FUNCTION_TYPE: - case GRANT_TYPE: - case LANG_TYPE: - case METHOD_TYPE: - case OFFSET_TYPE: - case POINTER_TYPE: - case RECORD_TYPE: - case REAL_TYPE: - case SEIZE_TYPE: - case UNION_TYPE: - case VOID_TYPE: - return 1; - case ARRAY_TYPE: - case BOOLEAN_TYPE: - case CHAR_TYPE: - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case REFERENCE_TYPE: - case SET_TYPE: - return 0; - } - - case TRUNC_DIV_EXPR: - goto numerics; - case TRUNC_MOD_EXPR: - if (TREE_CODE (type) == REAL_TYPE) - return 1; - goto numerics; - case TRUTH_ANDIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_NOT_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_OR_EXPR: - relationals: - switch ((int)TREE_CODE(type)) /* left operand must be discrete type */ - { - case ARRAY_TYPE: - case CHAR_TYPE: - case COMPLEX_TYPE: - case ENUMERAL_TYPE: - case FILE_TYPE: - case FUNCTION_TYPE: - case GRANT_TYPE: - case INTEGER_TYPE: - case LANG_TYPE: - case METHOD_TYPE: - case OFFSET_TYPE: - case POINTER_TYPE: - case REAL_TYPE: - case RECORD_TYPE: - case REFERENCE_TYPE: - case SEIZE_TYPE: - case UNION_TYPE: - case VOID_TYPE: - return 1; - case BOOLEAN_TYPE: - case SET_TYPE: - return 0; - } - break; - - default: - return 1; /* perhaps you forgot to add a new DEFTREECODE? */ - } - return 1; -} - - -static int -invalid_right_operand (code, type) - enum chill_tree_code code; - tree type; -{ - return invalid_operand (code, type, 1); -} - -tree -build_chill_abs (expr) - tree expr; -{ - tree temp; - - if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE - || discrete_type_p (TREE_TYPE (expr))) - temp = fold (build1 (ABS_EXPR, TREE_TYPE (expr), expr)); - else - { - error("ABS argument must be discrete or real mode"); - return error_mark_node; - } - /* FIXME: should call - * cond_type_range_exception (temp); - */ - return temp; -} - -static tree -build_chill_abstime (exprlist) - tree exprlist; -{ - int mask = 0, i, numargs; - tree args = NULL_TREE; - tree filename, lineno; - int had_errors = 0; - tree tmp; - - if (exprlist != NULL_TREE && TREE_CODE (exprlist) == ERROR_MARK) - return error_mark_node; - - /* check for integer expressions */ - i = 1; - tmp = exprlist; - while (tmp != NULL_TREE) - { - tree exp = TREE_VALUE (tmp); - - if (exp == NULL_TREE || TREE_CODE (exp) == ERROR_MARK) - had_errors = 1; - else if (TREE_CODE (TREE_TYPE (exp)) != INTEGER_TYPE) - { - error ("argument %d to ABSTIME must be of integer type", i); - had_errors = 1; - } - tmp = TREE_CHAIN (tmp); - i++; - } - if (had_errors) - return error_mark_node; - - numargs = list_length (exprlist); - for (i = 0; i < numargs; i++) - mask |= (1 << i); - - /* make it all arguments */ - for (i = numargs; i < 6; i++) - exprlist = tree_cons (NULL_TREE, integer_zero_node, exprlist); - - args = tree_cons (NULL_TREE, build_int_2 (mask, 0), exprlist); - - filename = force_addr_of (get_chill_filename ()); - lineno = get_chill_linenumber (); - args = chainon (args, tree_cons (NULL_TREE, filename, - tree_cons (NULL_TREE, lineno, NULL_TREE))); - - return build_chill_function_call ( - lookup_name (get_identifier ("_abstime")), args); -} - - -static tree -build_allocate_memory_call (ptr, size) - tree ptr, size; -{ - int err = 0; - - /* check for ptr is referable */ - if (! CH_REFERABLE (ptr)) - { - error ("parameter 1 must be referable"); - err++; - } - /* check for pointer */ - else if (TREE_CODE (TREE_TYPE (ptr)) != POINTER_TYPE) - { - error ("mode mismatch in parameter 1"); - err++; - } - - /* check for size > 0 if it is a constant */ - if (TREE_CODE (size) == INTEGER_CST && TREE_INT_CST_LOW (size) <= 0) - { - error ("parameter 2 must be a positive integer"); - err++; - } - if (err) - return error_mark_node; - - if (TREE_TYPE (ptr) != ptr_type_node) - ptr = build_chill_cast (ptr_type_node, ptr); - - return build_chill_function_call ( - lookup_name (get_identifier ("_allocate_memory")), - tree_cons (NULL_TREE, ptr, - tree_cons (NULL_TREE, size, - tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - tree_cons (NULL_TREE, get_chill_linenumber (), - NULL_TREE))))); -} - - -static tree -build_allocate_global_memory_call (ptr, size) - tree ptr, size; -{ - int err = 0; - - /* check for ptr is referable */ - if (! CH_REFERABLE (ptr)) - { - error ("parameter 1 must be referable"); - err++; - } - /* check for pointer */ - else if (TREE_CODE (TREE_TYPE (ptr)) != POINTER_TYPE) - { - error ("mode mismatch in parameter 1"); - err++; - } - - /* check for size > 0 if it is a constant */ - if (TREE_CODE (size) == INTEGER_CST && TREE_INT_CST_LOW (size) <= 0) - { - error ("parameter 2 must be a positive integer"); - err++; - } - if (err) - return error_mark_node; - - if (TREE_TYPE (ptr) != ptr_type_node) - ptr = build_chill_cast (ptr_type_node, ptr); - - return build_chill_function_call ( - lookup_name (get_identifier ("_allocate_global_memory")), - tree_cons (NULL_TREE, ptr, - tree_cons (NULL_TREE, size, - tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - tree_cons (NULL_TREE, get_chill_linenumber (), - NULL_TREE))))); -} - - -static tree -build_return_memory (ptr) - tree ptr; -{ - /* check input */ - if (ptr == NULL_TREE || TREE_CODE (ptr) == ERROR_MARK) - return error_mark_node; - - /* check for pointer */ - if (TREE_CODE (TREE_TYPE (ptr)) != POINTER_TYPE) - { - error ("mode mismatch in parameter 1"); - return error_mark_node; - } - - if (TREE_TYPE (ptr) != ptr_type_node) - ptr = build_chill_cast (ptr_type_node, ptr); - - return build_chill_function_call ( - lookup_name (get_identifier ("_return_memory")), - tree_cons (NULL_TREE, ptr, - tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - tree_cons (NULL_TREE, get_chill_linenumber (), - NULL_TREE)))); -} - - -/* Compute the number of runtime members of the - * given powerset. - */ -tree -build_chill_card (powerset) - tree powerset; -{ - if (pass == 2) - { - tree temp; - tree card_func = lookup_name (get_identifier ("__cardpowerset")); - - if (powerset == NULL_TREE || TREE_CODE (powerset) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (powerset) == IDENTIFIER_NODE) - powerset = lookup_name (powerset); - - if (TREE_CODE (TREE_TYPE(powerset)) == SET_TYPE) - { int size; - - /* Do constant folding, if possible. */ - if (TREE_CODE (powerset) == CONSTRUCTOR - && TREE_CONSTANT (powerset) - && (size = int_size_in_bytes (TREE_TYPE (powerset))) >= 0) - { - int bit_size = size * BITS_PER_UNIT; - char* buffer = (char*) alloca (bit_size); - temp = get_set_constructor_bits (powerset, buffer, bit_size); - if (!temp) - { int i; - int count = 0; - for (i = 0; i < bit_size; i++) - if (buffer[i]) - count++; - temp = build_int_2 (count, 0); - TREE_TYPE (temp) = TREE_TYPE (TREE_TYPE (card_func)); - return temp; - } - } - temp = build_chill_function_call (card_func, - tree_cons (NULL_TREE, force_addr_of (powerset), - tree_cons (NULL_TREE, powersetlen (powerset), NULL_TREE))); - /* FIXME: should call - * cond_type_range_exception (op0); - */ - return temp; - } - error("CARD argument must be powerset mode"); - return error_mark_node; - } - return NULL_TREE; -} - -/* function to build the type needed for the DESCR-built-in - */ - -void build_chill_descr_type () -{ - tree decl1, decl2; - - if (descr_type != NULL_TREE) - /* already done */ - return; - - decl1 = build_decl (FIELD_DECL, get_identifier ("datap"), ptr_type_node); - decl2 = build_decl (FIELD_DECL, get_identifier ("len"), - TREE_TYPE (lookup_name ( - get_identifier ((ignore_case || ! special_UC) ? "ulong" : "ULONG")))); - TREE_CHAIN (decl1) = decl2; - TREE_CHAIN (decl2) = NULL_TREE; - decl2 = build_chill_struct_type (decl1); - descr_type = build_decl (TYPE_DECL, get_identifier ("__tmp_DESCR_type"), decl2); - pushdecl (descr_type); - DECL_SOURCE_LINE (descr_type) = 0; - satisfy_decl (descr_type, 0); -} - -/* build a pointer to a descriptor. - * descriptor = STRUCT (datap PTR, - * len ULONG); - * This descriptor is build in variable descr_type. - */ - -tree -build_chill_descr (expr) - tree expr; -{ - if (pass == 2) - { - tree tuple, decl, descr_var, datap, len, tmp; - int is_static; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - /* check for expression is referable */ - if (! CH_REFERABLE (expr)) - { - error ("expression for DESCR-built-in must be referable"); - return error_mark_node; - } - - mark_addressable (expr); -#if 0 - datap = build1 (ADDR_EXPR, build_chill_pointer_type (descr_type), expr); -#else - datap = build_chill_arrow_expr (expr, 1); -#endif - len = size_in_bytes (TREE_TYPE (expr)); - - descr_var = get_unique_identifier ("DESCR"); - tuple = build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (NULL_TREE, datap, - tree_cons (NULL_TREE, len, NULL_TREE))); - - is_static = (current_function_decl == global_function_decl) && TREE_STATIC (expr); - decl = decl_temp1 (descr_var, TREE_TYPE (descr_type), is_static, - tuple, 0, 0); -#if 0 - tmp = force_addr_of (decl); -#else - tmp = build_chill_arrow_expr (decl, 1); -#endif - return tmp; - } - return NULL_TREE; -} - -/* this function process the builtin's - MILLISECS, SECS, MINUTES, HOURS and DAYS. - The built duration value is in milliseconds. */ - -static tree -build_chill_duration (expr, multiplier, fnname, maxvalue) - tree expr; - unsigned long multiplier; - tree fnname; - unsigned long maxvalue; -{ - tree temp; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE) - { - error ("argument to `%s' must be of integer type", IDENTIFIER_POINTER (fnname)); - return error_mark_node; - } - - temp = convert (duration_timing_type_node, expr); - temp = fold (build (MULT_EXPR, duration_timing_type_node, - temp, build_int_2 (multiplier, 0))); - - if (range_checking) - temp = check_range (temp, expr, integer_zero_node, build_int_2 (maxvalue, 0)); - - return temp; -} - -/* build function call to one of the floating point functions */ -static tree -build_chill_floatcall (expr, chillname, funcname) - tree expr; - const char *chillname; - const char *funcname; -{ - tree result; - tree type; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - /* look if expr is a REAL_TYPE */ - type = TREE_TYPE (expr); - if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK) - return error_mark_node; - if (TREE_CODE (type) != REAL_TYPE) - { - error ("argument 1 to `%s' must be of floating point mode", chillname); - return error_mark_node; - } - result = build_chill_function_call ( - lookup_name (get_identifier (funcname)), - tree_cons (NULL_TREE, expr, NULL_TREE)); - return result; -} - -/* common function for ALLOCATE and GETSTACK */ -static tree -build_allocate_getstack (mode, value, chill_name, fnname, filename, linenumber) - tree mode; - tree value; - const char *chill_name; - const char *fnname; - tree filename; - tree linenumber; -{ - tree type, result; - tree expr = NULL_TREE; - tree args, tmpvar, fncall, ptr, outlist = NULL_TREE; - - if (mode == NULL_TREE || TREE_CODE (mode) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (mode) == TYPE_DECL) - type = TREE_TYPE (mode); - else - type = mode; - - /* check if we have a mode */ - if (TREE_CODE_CLASS (TREE_CODE (type)) != 't') - { - error ("first argument to `%s' must be a mode", chill_name); - return error_mark_node; - } - - /* check if we have a value if type is READonly */ - if (TYPE_READONLY_PROPERTY (type) && value == NULL_TREE) - { - error ("READonly modes for %s must have a value", chill_name); - return error_mark_node; - } - - if (value != NULL_TREE) - { - if (TREE_CODE (value) == ERROR_MARK) - return error_mark_node; - expr = chill_convert_for_assignment (type, value, "assignment"); - } - - /* build function arguments */ - if (filename == NULL_TREE) - args = tree_cons (NULL_TREE, size_in_bytes (type), NULL_TREE); - else - args = tree_cons (NULL_TREE, size_in_bytes (type), - tree_cons (NULL_TREE, force_addr_of (filename), - tree_cons (NULL_TREE, linenumber, NULL_TREE))); - - ptr = build_chill_pointer_type (type); - tmpvar = decl_temp1 (get_unique_identifier (chill_name), - ptr, 0, NULL_TREE, 0, 0); - fncall = build_chill_function_call ( - lookup_name (get_identifier (fnname)), args); - outlist = tree_cons (NULL_TREE, - build_chill_modify_expr (tmpvar, fncall), outlist); - if (expr == NULL_TREE) - { - /* set allocated memory to 0 */ - fncall = build_chill_function_call ( - lookup_name (get_identifier ("memset")), - tree_cons (NULL_TREE, convert (ptr_type_node, tmpvar), - tree_cons (NULL_TREE, integer_zero_node, - tree_cons (NULL_TREE, size_in_bytes (type), NULL_TREE)))); - outlist = tree_cons (NULL_TREE, fncall, outlist); - } - else - { - /* write the init value to allocated memory */ - outlist = tree_cons (NULL_TREE, - build_chill_modify_expr (build_chill_indirect_ref (tmpvar, NULL_TREE, 0), - expr), - outlist); - } - outlist = tree_cons (NULL_TREE, tmpvar, outlist); - result = build_chill_compound_expr (nreverse (outlist)); - return result; -} - -/* process the ALLOCATE built-in */ -static tree -build_chill_allocate (mode, value) - tree mode; - tree value; -{ - return build_allocate_getstack (mode, value, "ALLOCATE", "__allocate", - get_chill_filename (), get_chill_linenumber ()); -} - -/* process the GETSTACK built-in */ -static tree -build_chill_getstack (mode, value) - tree mode; - tree value; -{ - return build_allocate_getstack (mode, value, "GETSTACK", "__builtin_alloca", - NULL_TREE, NULL_TREE); -} - -/* process the TERMINATE built-in */ -static tree -build_chill_terminate (ptr) - tree ptr; -{ - tree result; - tree type; - - if (ptr == NULL_TREE || TREE_CODE (ptr) == ERROR_MARK) - return error_mark_node; - - type = TREE_TYPE (ptr); - if (type == NULL_TREE || TREE_CODE (type) != POINTER_TYPE) - { - error ("argument to TERMINATE must be a reference primitive value"); - return error_mark_node; - } - result = build_chill_function_call ( - lookup_name (get_identifier ("__terminate")), - tree_cons (NULL_TREE, convert (ptr_type_node, ptr), - tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - tree_cons (NULL_TREE, get_chill_linenumber (), NULL_TREE)))); - return result; -} - -/* build the type passed to _inttime function */ -void -build_chill_inttime_type () -{ - tree idxlist; - tree arrtype; - tree decl; - - idxlist = build_tree_list (NULL_TREE, - build_chill_range_type (NULL_TREE, - integer_zero_node, - build_int_2 (5, 0))); - arrtype = build_chill_array_type (ptr_type_node, idxlist, 0, NULL_TREE); - - decl = build_decl (TYPE_DECL, get_identifier ("__tmp_INTTIME_type"), arrtype); - pushdecl (decl); - DECL_SOURCE_LINE (decl) = 0; - satisfy_decl (decl, 0); -} - -static tree -build_chill_inttime (t, loclist) - tree t, loclist; -{ - int had_errors = 0, cnt; - tree tmp; - tree init = NULL_TREE; - int numargs; - tree tuple, var; - - if (t == NULL_TREE || TREE_CODE (t) == ERROR_MARK) - return error_mark_node; - if (loclist == NULL_TREE || TREE_CODE (loclist) == ERROR_MARK) - return error_mark_node; - - /* check first argument to be NEWMODE TIME */ - if (TREE_TYPE (t) != abs_timing_type_node) - { - error ("argument 1 to INTTIME must be of mode TIME"); - had_errors = 1; - } - - cnt = 2; - tmp = loclist; - while (tmp != NULL_TREE) - { - tree loc = TREE_VALUE (tmp); - char errmsg[200]; - char *p, *p1; - int write_error = 0; - - sprintf (errmsg, "argument %d to INTTIME must be ", cnt); - p = errmsg + strlen (errmsg); - p1 = p; - - if (loc == NULL_TREE || TREE_CODE (loc) == ERROR_MARK) - had_errors = 1; - else - { - if (! CH_REFERABLE (loc)) - { - strcpy (p, "referable"); - p += strlen (p); - write_error = 1; - had_errors = 1; - } - if (TREE_CODE (TREE_TYPE (loc)) != INTEGER_TYPE) - { - if (p != p1) - { - strcpy (p, " and "); - p += strlen (p); - } - strcpy (p, "of integer type"); - write_error = 1; - had_errors = 1; - } - /* FIXME: what's about ranges can't hold the result ?? */ - if (write_error) - error ("%s", errmsg); - } - /* next location */ - tmp = TREE_CHAIN (tmp); - cnt++; - } - - if (had_errors) - return error_mark_node; - - /* make it always 6 arguments */ - numargs = list_length (loclist); - for (cnt = numargs; cnt < 6; cnt++) - init = tree_cons (NULL_TREE, null_pointer_node, init); - - /* append the given one's */ - tmp = loclist; - while (tmp != NULL_TREE) - { - init = chainon (init, - build_tree_list (NULL_TREE, - build_chill_descr (TREE_VALUE (tmp)))); - tmp = TREE_CHAIN (tmp); - } - - tuple = build_nt (CONSTRUCTOR, NULL_TREE, init); - var = decl_temp1 (get_unique_identifier ("INTTIME"), - TREE_TYPE (lookup_name (get_identifier ("__tmp_INTTIME_type"))), - 0, tuple, 0, 0); - - return build_chill_function_call ( - lookup_name (get_identifier ("_inttime")), - tree_cons (NULL_TREE, t, - tree_cons (NULL_TREE, force_addr_of (var), - NULL_TREE))); -} - - -/* Compute the runtime length of the given string variable - * or expression. - */ -tree -build_chill_length (expr) - tree expr; -{ - if (pass == 2) - { - tree type; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (expr) == IDENTIFIER_NODE) - expr = lookup_name (expr); - - type = TREE_TYPE (expr); - - if (TREE_CODE(type) == ERROR_MARK) - return type; - if (chill_varying_type_p (type)) - { - tree temp = convert (integer_type_node, - build_component_ref (expr, var_length_id)); - /* FIXME: should call - * cond_type_range_exception (temp); - */ - return temp; - } - - if ((TREE_CODE (type) == ARRAY_TYPE || - /* should work for a bitstring too */ - (TREE_CODE (type) == SET_TYPE && TREE_CODE (TREE_TYPE (type)) == BOOLEAN_TYPE)) && - integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (type)))) - { - tree temp = fold (build (PLUS_EXPR, chill_integer_type_node, - integer_one_node, - TYPE_MAX_VALUE (TYPE_DOMAIN (type)))); - return convert (chill_integer_type_node, temp); - } - - if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type)) - { - tree len = max_queue_size (type); - - if (len == NULL_TREE) - len = integer_minus_one_node; - return len; - } - - if (CH_IS_TEXT_MODE (type)) - { - if (TREE_CODE (expr) == TYPE_DECL) - { - /* text mode name */ - return text_length (type); - } - else - { - /* text location */ - tree temp = build_component_ref ( - build_component_ref (expr, get_identifier ("tloc")), - var_length_id); - return convert (integer_type_node, temp); - } - } - - error("LENGTH argument must be string, buffer, event mode, text location or mode"); - return error_mark_node; - } - return NULL_TREE; -} - -/* Compute the declared minimum/maximum value of the variable, - * expression or declared type - */ -static tree -build_chill_lower_or_upper (what, is_upper) - tree what; - int is_upper; /* o -> LOWER; 1 -> UPPER */ -{ - if (pass == 2) - { - tree type; - struct ch_class class; - - if (what == NULL_TREE || TREE_CODE (what) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE_CLASS (TREE_CODE (what)) == 't') - type = what; - else - type = TREE_TYPE (what); - if (type == NULL_TREE) - { - if (is_upper) - error ("UPPER argument must have a mode, or be a mode"); - else - error ("LOWER argument must have a mode, or be a mode"); - return error_mark_node; - } - while (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - if (chill_varying_type_p (type)) - type = CH_VARYING_ARRAY_TYPE (type); - - if (discrete_type_p (type)) - { - tree val = is_upper ? TYPE_MAX_VALUE (type) : TYPE_MIN_VALUE (type); - class.kind = CH_VALUE_CLASS; - class.mode = type; - return convert_to_class (class, val); - } - else if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == SET_TYPE) - { - if (TYPE_STRING_FLAG (type)) - { - class.kind = CH_DERIVED_CLASS; - class.mode = integer_type_node; - } - else - { - class.kind = CH_VALUE_CLASS; - class.mode = TYPE_DOMAIN (type); - } - type = TYPE_DOMAIN (type); - return convert_to_class (class, - is_upper - ? TYPE_MAX_VALUE (type) - : TYPE_MIN_VALUE (type)); - } - if (is_upper) - error("UPPER argument must be string, array, mode or integer"); - else - error("LOWER argument must be string, array, mode or integer"); - return error_mark_node; - } - return NULL_TREE; -} - -tree -build_chill_lower (what) - tree what; -{ - return build_chill_lower_or_upper (what, 0); -} - -static tree -build_max_min (expr, max_min) - tree expr; - int max_min; /* 0: calculate MIN; 1: calculate MAX */ -{ - if (pass == 2) - { - tree type, temp, setminval; - tree set_base_type; - int size_in_bytes; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (expr) == IDENTIFIER_NODE) - expr = lookup_name (expr); - - type = TREE_TYPE (expr); - set_base_type = TYPE_DOMAIN (type); - setminval = TYPE_MIN_VALUE (set_base_type); - - if (TREE_CODE (type) != SET_TYPE) - { - error("%s argument must be POWERSET mode", - max_min ? "MAX" : "MIN"); - return error_mark_node; - } - - /* find max/min of constant powerset at compile time */ - if (TREE_CODE (expr) == CONSTRUCTOR && TREE_CONSTANT (expr) - && (size_in_bytes = int_size_in_bytes (type)) >= 0) - { - HOST_WIDE_INT min_val = -1, max_val = -1; - HOST_WIDE_INT i, i_hi = 0; - HOST_WIDE_INT size_in_bits = size_in_bytes * BITS_PER_UNIT; - char *buffer = (char*) alloca (size_in_bits); - if (buffer == NULL - || get_set_constructor_bits (expr, buffer, size_in_bits)) - abort (); - for (i = 0; i < size_in_bits; i++) - { - if (buffer[i]) - { - if (min_val < 0) - min_val = i; - max_val = i; - } - } - if (min_val < 0) - error ("%s called for empty POWERSET", max_min ? "MAX" : "MIN"); - i = max_min ? max_val : min_val; - temp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (expr))); - add_double (i, i_hi, - TREE_INT_CST_LOW (temp), TREE_INT_CST_HIGH (temp), - &i, &i_hi); - temp = build_int_2 (i, i_hi); - TREE_TYPE (temp) = set_base_type; - return temp; - } - else - { - tree parmlist, filename, lineno; - const char *funcname; - - /* set up to call appropriate runtime function */ - if (max_min) - funcname = "__flsetpowerset"; - else - funcname = "__ffsetpowerset"; - - setminval = convert (long_integer_type_node, setminval); - filename = force_addr_of (get_chill_filename()); - lineno = get_chill_linenumber(); - parmlist = tree_cons (NULL_TREE, force_addr_of (expr), - tree_cons (NULL_TREE, powersetlen (expr), - tree_cons (NULL_TREE, setminval, - tree_cons (NULL_TREE, filename, - build_tree_list (NULL_TREE, lineno))))); - temp = lookup_name (get_identifier (funcname)); - temp = build_chill_function_call (temp, parmlist); - TREE_TYPE (temp) = set_base_type; - return temp; - } - } - return NULL_TREE; -} - - -/* Compute the current runtime maximum value of the powerset - */ -tree -build_chill_max (expr) - tree expr; -{ - return build_max_min (expr, 1); -} - - -/* Compute the current runtime minimum value of the powerset - */ -tree -build_chill_min (expr) - tree expr; -{ - return build_max_min (expr, 0); -} - - -/* Build a conversion from the given expression to an INT, - * but only when the expression's type is the same size as - * an INT. - */ -tree -build_chill_num (expr) - tree expr; -{ - if (pass == 2) - { - tree temp; - int need_unsigned; - - if (expr == NULL_TREE || TREE_CODE(expr) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (expr) == IDENTIFIER_NODE) - expr = lookup_name (expr); - - expr = convert_to_discrete (expr); - if (expr == NULL_TREE) - { - error ("argument to NUM is not discrete"); - return error_mark_node; - } - - /* enumeral types and string slices of length 1 must be kept unsigned */ - need_unsigned = (TREE_CODE (TREE_TYPE (expr)) == ENUMERAL_TYPE) - || TREE_UNSIGNED (TREE_TYPE (expr)); - - temp = type_for_size (TYPE_PRECISION (TREE_TYPE (expr)), - need_unsigned); - if (temp == NULL_TREE) - { - error ("no integer mode which matches expression's mode"); - return integer_zero_node; - } - temp = convert (temp, expr); - - if (TREE_CONSTANT (temp)) - { - if (tree_int_cst_lt (temp, - TYPE_MIN_VALUE (TREE_TYPE (temp)))) - error ("NUM's parameter is below its mode range"); - if (tree_int_cst_lt (TYPE_MAX_VALUE (TREE_TYPE (temp)), - temp)) - error ("NUM's parameter is above its mode range"); - } -#if 0 - else - { - if (range_checking) - cond_overflow_exception (temp, - TYPE_MIN_VALUE (TREE_TYPE (temp)), - TYPE_MAX_VALUE (TREE_TYPE (temp))); - } -#endif - - /* NUM delivers the INT derived class */ - CH_DERIVED_FLAG (temp) = 1; - - return temp; - } - return NULL_TREE; -} - - -static tree -build_chill_pred_or_succ (expr, op) - tree expr; - enum tree_code op; /* PLUS_EXPR for SUCC; MINUS_EXPR for PRED. */ -{ - struct ch_class class; - tree etype, cond; - - if (pass == 1) - return NULL_TREE; - - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - /* disallow numbered SETs */ - if (TREE_CODE (TREE_TYPE (expr)) == ENUMERAL_TYPE - && CH_ENUM_IS_NUMBERED (TREE_TYPE (expr))) - { - error ("cannot take SUCC or PRED of a numbered SET"); - return error_mark_node; - } - - if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) - { - if (TREE_TYPE (TREE_TYPE (expr)) == void_type_node) - { - error ("SUCC or PRED must not be done on a PTR"); - return error_mark_node; - } - pedwarn ("SUCC or PRED for a reference type is not standard"); - return fold (build (op, TREE_TYPE (expr), - expr, - size_in_bytes (TREE_TYPE (TREE_TYPE (expr))))); - } - - expr = convert_to_discrete (expr); - - if (expr == NULL_TREE) - { - error ("SUCC or PRED argument must be a discrete mode"); - return error_mark_node; - } - - class = chill_expr_class (expr); - if (class.mode) - class.mode = CH_ROOT_MODE (class.mode); - etype = class.mode; - expr = convert (etype, expr); - - /* Exception if expression is already at the - min (PRED)/max(SUCC) valid value for its type. */ - cond = fold (build (op == PLUS_EXPR ? GE_EXPR : LE_EXPR, - boolean_type_node, - expr, - convert (etype, - op == PLUS_EXPR ? TYPE_MAX_VALUE (etype) - : TYPE_MIN_VALUE (etype)))); - if (TREE_CODE (cond) == INTEGER_CST - && tree_int_cst_equal (cond, integer_one_node)) - { - error ("taking the %s of a value already at its %s value", - op == PLUS_EXPR ? "SUCC" : "PRED", - op == PLUS_EXPR ? "maximum" : "minimum"); - return error_mark_node; - } - - if (range_checking) - expr = check_expression (expr, cond, - ridpointers[(int) RID_OVERFLOW]); - - expr = fold (build (op, etype, expr, - convert (etype, integer_one_node))); - return convert_to_class (class, expr); -} - -/* Compute the value of the CHILL `size' operator just - * like the C 'sizeof' operator (code stolen from c-typeck.c) - * TYPE may be a location or mode tree. In pass 1, we build - * a function-call syntax tree; in pass 2, we evaluate it. - */ -tree -build_chill_sizeof (type) - tree type; -{ - if (pass == 2) - { - tree temp; - struct ch_class class; - enum tree_code code; - tree signame = NULL_TREE; - - if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE (type) == IDENTIFIER_NODE) - type = lookup_name (type); - - code = TREE_CODE (type); - if (code == ERROR_MARK) - return error_mark_node; - - if (TREE_CODE_CLASS (TREE_CODE (type)) != 't') - { - if (TREE_CODE (type) == TYPE_DECL && CH_DECL_SIGNAL (type)) - signame = DECL_NAME (type); - type = TREE_TYPE (type); - } - - if (code == FUNCTION_TYPE) - { - if (pedantic || warn_pointer_arith) - pedwarn ("size applied to a function mode"); - return error_mark_node; - } - if (code == VOID_TYPE) - { - if (pedantic || warn_pointer_arith) - pedwarn ("sizeof applied to a void mode"); - return error_mark_node; - } - if (TYPE_SIZE (type) == 0) - { - error ("sizeof applied to an incomplete mode"); - return error_mark_node; - } - - temp = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), - size_int (TYPE_PRECISION (char_type_node) - / BITS_PER_UNIT)); - if (signame != NULL_TREE) - { - /* we have a signal definition. This signal may have no - data items specified. The definition however says that - there are data, cause we cannot build a structure without - fields. In this case return 0. */ - if (IDENTIFIER_SIGNAL_DATA (signame) == 0) - temp = integer_zero_node; - } - - /* FIXME: should call - * cond_type_range_exception (temp); - */ - class.kind = CH_DERIVED_CLASS; - class.mode = integer_type_node; - return convert_to_class (class, temp); - } - return NULL_TREE; -} - -/* Compute the declared maximum value of the variable, - * expression or declared type - */ -tree -build_chill_upper (what) - tree what; -{ - return build_chill_lower_or_upper (what, 1); -} - -/* - * Here at the site of a function/procedure call.. We need to build - * temps for the INOUT and OUT parameters, and copy the actual parameters - * into the temps. After the call, we 'copy back' the values from the - * temps to the actual parameter variables. This somewhat verbose pol- - * icy meets the requirement that the actual parameters are undisturbed - * if the function/procedure causes an exception. They are updated only - * upon a normal return from the function. - * - * Note: the expr_list, which collects all of the above assignments, etc, - * is built in REVERSE execution order. The list is corrected by nreverse - * inside the build_chill_compound_expr call. - */ -tree -build_chill_function_call (function, expr) - tree function, expr; -{ - register tree typetail, valtail, typelist; - register tree temp, actual_args = NULL_TREE; - tree name = NULL_TREE; - tree function_call; - tree fntype; - int parmno = 1; /* parameter number for error message */ - int callee_raise_exception = 0; - - /* list of assignments to run after the actual call, - copying from the temps back to the user's variables. */ - tree copy_back = NULL_TREE; - - /* list of expressions to run before the call, copying from - the user's variable to the temps that are passed to the function */ - tree expr_list = NULL_TREE; - - if (function == NULL_TREE || TREE_CODE (function) == ERROR_MARK) - return error_mark_node; - - if (expr != NULL_TREE && TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - - if (pass < 2) - return error_mark_node; - - fntype = TREE_TYPE (function); - if (TREE_CODE (function) == FUNCTION_DECL) - { - callee_raise_exception = TYPE_RAISES_EXCEPTIONS (fntype) != NULL_TREE; - - /* Differs from default_conversion by not setting TREE_ADDRESSABLE - (because calling an inline function does not mean the function - needs to be separately compiled). */ - fntype = build_type_variant (fntype, - TREE_READONLY (function), - TREE_THIS_VOLATILE (function)); - name = DECL_NAME (function); - - /* check that function is not a PROCESS */ - if (CH_DECL_PROCESS (function)) - { - error ("cannot call a PROCESS, you START a PROCESS"); - return error_mark_node; - } - - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - } - else if (TREE_CODE (fntype) == POINTER_TYPE) - { - fntype = TREE_TYPE (fntype); - callee_raise_exception = TYPE_RAISES_EXCEPTIONS (fntype) != NULL_TREE; - - /* Z.200 6.7 Call Action: - "A procedure call causes the EMPTY exception if the - procedure primitive value delivers NULL. */ - if (TREE_CODE (function) != ADDR_EXPR - || TREE_CODE (TREE_OPERAND (function, 0)) != FUNCTION_DECL) - function = check_non_null (function); - } - - typelist = TYPE_ARG_TYPES (fntype); - if (callee_raise_exception) - { - /* remove last two arguments from list for subsequent checking. - They will get added automatically after checking */ - int len = list_length (typelist); - int i; - tree newtypelist = NULL_TREE; - tree wrk = typelist; - - for (i = 0; i < len - 3; i++) - { - newtypelist = tree_cons (TREE_PURPOSE (wrk), TREE_VALUE (wrk), newtypelist); - wrk = TREE_CHAIN (wrk); - } - /* add the void_type_node */ - newtypelist = tree_cons (NULL_TREE, void_type_node, newtypelist); - typelist = nreverse (newtypelist); - } - - /* Scan the given expressions and types, producing individual - converted arguments and pushing them on ACTUAL_ARGS in - reverse order. */ - for (valtail = expr, typetail = typelist; - valtail != NULL_TREE && typetail != NULL_TREE; parmno++, - valtail = TREE_CHAIN (valtail), typetail = TREE_CHAIN (typetail)) - { - register tree actual = TREE_VALUE (valtail); - register tree attr = TREE_PURPOSE (typetail) - ? TREE_PURPOSE (typetail) : ridpointers[(int) RID_IN]; - register tree type = TREE_VALUE (typetail); - char place[30]; - sprintf (place, "parameter %d", parmno); - - /* if we have reached void_type_node in typelist we are at the - end of formal parameters and then we have too many actual - parameters */ - if (type == void_type_node) - break; - - /* check if actual is a TYPE_DECL. FIXME: what else ? */ - if (TREE_CODE (actual) == TYPE_DECL) - { - error ("invalid %s", place); - actual = error_mark_node; - } - /* INOUT or OUT param to handle? */ - else if (attr == ridpointers[(int) RID_OUT] - || attr == ridpointers[(int)RID_INOUT]) - { - char temp_name[20]; - tree parmtmp; - tree in_actual = NULL_TREE, out_actual; - - /* actual parameter must be a location so we can - build a reference to it */ - if (!CH_LOCATION_P (actual)) - { - error ("%s parameter %d must be a location", - (attr == ridpointers[(int) RID_OUT]) ? - "OUT" : "INOUT", parmno); - continue; - } - if (TYPE_READONLY_PROPERTY (TREE_TYPE (actual)) - || TREE_READONLY (actual)) - { - error ("%s parameter %d is READ-only", - (attr == ridpointers[(int) RID_OUT]) ? - "OUT" : "INOUT", parmno); - continue; - } - - sprintf (temp_name, "PARM_%d_%s", parmno, - (attr == ridpointers[(int)RID_OUT]) ? - "OUT" : "INOUT"); - parmtmp = decl_temp1 (get_unique_identifier (temp_name), - TREE_TYPE (type), 0, NULL_TREE, 0, 0); - /* this temp *must not* be optimized into a register */ - mark_addressable (parmtmp); - - if (attr == ridpointers[(int)RID_INOUT]) - { - tree in_actual = chill_convert_for_assignment (TREE_TYPE (type), - actual, place); - tree tmp = build_chill_modify_expr (parmtmp, in_actual); - expr_list = tree_cons (NULL_TREE, tmp, expr_list); - } - if (in_actual != error_mark_node) - { - /* list of copy back assignments to perform, from the temp - back to the actual parameter */ - out_actual = chill_convert_for_assignment (TREE_TYPE (actual), - parmtmp, place); - copy_back = tree_cons (NULL_TREE, - build_chill_modify_expr (actual, - out_actual), - copy_back); - } - /* we can do this because build_chill_function_type - turned these parameters into REFERENCE_TYPEs. */ - actual = build1 (ADDR_EXPR, type, parmtmp); - } - else if (attr == ridpointers[(int) RID_LOC]) - { - int is_location = chill_location (actual); - if (is_location) - { - if (is_location == 1) - { - error ("LOC actual parameter %d is a non-referable location", - parmno); - actual = error_mark_node; - } - else if (! CH_READ_COMPATIBLE (type, TREE_TYPE (actual))) - { - error ("mode mismatch in parameter %d", parmno); - actual = error_mark_node; - } - else - actual = convert (type, actual); - } - else - { - sprintf (place, "parameter_%d", parmno); - actual = decl_temp1 (get_identifier (place), - TREE_TYPE (type), 0, actual, 0, 0); - actual = convert (type, actual); - } - mark_addressable (actual); - } - else - actual = chill_convert_for_assignment (type, actual, place); - - actual_args = tree_cons (NULL_TREE, actual, actual_args); - } - - if (valtail != 0 && TREE_VALUE (valtail) != void_type_node) - { - if (name) - error ("too many arguments to procedure `%s'", - IDENTIFIER_POINTER (name)); - else - error ("too many arguments to procedure"); - return error_mark_node; - } - else if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) - { - if (name) - error ("too few arguments to procedure `%s'", - IDENTIFIER_POINTER (name)); - else - error ("too few arguments to procedure"); - return error_mark_node; - } - - if (callee_raise_exception) - { - /* add linenumber and filename of the caller as arguments */ - actual_args = tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), - actual_args); - actual_args = tree_cons (NULL_TREE, get_chill_linenumber (), actual_args); - } - - function_call = build (CALL_EXPR, TREE_TYPE (fntype), - function, nreverse (actual_args), NULL_TREE); - TREE_SIDE_EFFECTS (function_call) = 1; - - if (copy_back == NULL_TREE && expr_list == NULL_TREE) - return function_call; /* no copying to do, either way */ - else - { - tree result_type = TREE_TYPE (fntype); - tree result_tmp = NULL_TREE; - - /* no result wanted from procedure call */ - if (result_type == NULL_TREE || result_type == void_type_node) - expr_list = tree_cons (NULL_TREE, function_call, expr_list); - else - { - /* create a temp for the function's result. this is so that we can - evaluate this temp as the last expression in the list, which will - make the function's return value the value of the whole list of - expressions (by the C rules for compound expressions) */ - result_tmp = decl_temp1 (get_unique_identifier ("FUNC_RESULT"), - result_type, 0, NULL_TREE, 0, 0); - expr_list = tree_cons (NULL_TREE, - build_chill_modify_expr (result_tmp, function_call), - expr_list); - } - - expr_list = chainon (copy_back, expr_list); - - /* last, but not least, the function's result */ - if (result_tmp != NULL_TREE) - expr_list = tree_cons (NULL_TREE, result_tmp, expr_list); - temp = build_chill_compound_expr (nreverse (expr_list)); - return temp; - } -} - -/* We saw something that looks like a function call, - but if it's pass 1, we're not sure. */ - -tree -build_generalized_call (func, args) - tree func, args; -{ - tree type = TREE_TYPE (func); - - if (pass == 1) - return build (CALL_EXPR, NULL_TREE, func, args, NULL_TREE); - - /* Handle string repetition */ - if (TREE_CODE (func) == INTEGER_CST) - { - if (args == NULL_TREE || TREE_CHAIN (args) != NULL_TREE) - { - error ("syntax error (integer used as function)"); - return error_mark_node; - } - if (TREE_CODE (args) == TREE_LIST) - args = TREE_VALUE (args); - return build_chill_repetition_op (func, args); - } - - if (args != NULL_TREE) - { - if (TREE_CODE (args) == RANGE_EXPR) - { - tree lo = TREE_OPERAND (args, 0), hi = TREE_OPERAND (args, 1); - if (TREE_CODE_CLASS (TREE_CODE (func)) == 't') - return build_chill_range_type (func, lo, hi); - else - return build_chill_slice_with_range (func, lo, hi); - } - else if (TREE_CODE (args) != TREE_LIST) - { - error ("syntax error - missing operator, comma, or '('?"); - return error_mark_node; - } - } - - if (TREE_CODE (func) == TYPE_DECL) - { - if (CH_DECL_SIGNAL (func)) - return build_signal_descriptor (func, args); - func = TREE_TYPE (func); - } - - if (TREE_CODE_CLASS (TREE_CODE (func)) == 't' - && args != NULL_TREE && TREE_CHAIN (args) == NULL_TREE) - return build_chill_cast (func, TREE_VALUE (args)); - - if (TREE_CODE (type) == FUNCTION_TYPE - || (TREE_CODE (type) == POINTER_TYPE - && TREE_TYPE (type) != NULL_TREE - && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)) - { - /* Check for a built-in Chill function. */ - if (TREE_CODE (func) == FUNCTION_DECL - && DECL_BUILT_IN (func) - && DECL_FUNCTION_CODE (func) > END_BUILTINS) - { - tree fnname = DECL_NAME (func); - switch ((enum chill_built_in_function)DECL_FUNCTION_CODE (func)) - { - case BUILT_IN_CH_ABS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_abs (TREE_VALUE (args)); - case BUILT_IN_ABSTIME: - if (check_arglist_length (args, 0, 6, fnname) < 0) - return error_mark_node; - return build_chill_abstime (args); - case BUILT_IN_ADDR: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; -#if 0 - return build_chill_addr_expr (TREE_VALUE (args), (char *)0); -#else - return build_chill_arrow_expr (TREE_VALUE (args), 0); -#endif - case BUILT_IN_ALLOCATE_GLOBAL_MEMORY: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_allocate_global_memory_call - (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_ALLOCATE: - if (check_arglist_length (args, 1, 2, fnname) < 0) - return error_mark_node; - return build_chill_allocate (TREE_VALUE (args), - TREE_CHAIN (args) == NULL_TREE ? NULL_TREE : TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_ALLOCATE_MEMORY: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_allocate_memory_call - (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_ASSOCIATE: - if (check_arglist_length (args, 2, 3, fnname) < 0) - return error_mark_node; - return build_chill_associate - (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args)), - TREE_CHAIN (TREE_CHAIN (args))); - case BUILT_IN_ARCCOS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__acos"); - case BUILT_IN_ARCSIN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__asin"); - case BUILT_IN_ARCTAN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__atan"); - case BUILT_IN_CARD: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_card (TREE_VALUE (args)); - case BUILT_IN_CONNECT: - if (check_arglist_length (args, 3, 5, fnname) < 0) - return error_mark_node; - return build_chill_connect - (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args)), - TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))), - TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))); - case BUILT_IN_COPY_NUMBER: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_copy_number (TREE_VALUE (args)); - case BUILT_IN_CH_COS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__cos"); - case BUILT_IN_CREATE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_create (TREE_VALUE (args)); - case BUILT_IN_DAYS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_duration (TREE_VALUE (args), DAYS_MULTIPLIER, - fnname, DAYS_MAX); - case BUILT_IN_CH_DELETE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_delete (TREE_VALUE (args)); - case BUILT_IN_DESCR: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_descr (TREE_VALUE (args)); - case BUILT_IN_DISCONNECT: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_disconnect (TREE_VALUE (args)); - case BUILT_IN_DISSOCIATE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_dissociate (TREE_VALUE (args)); - case BUILT_IN_EOLN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_eoln (TREE_VALUE (args)); - case BUILT_IN_EXISTING: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_existing (TREE_VALUE (args)); - case BUILT_IN_EXP: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__exp"); - case BUILT_IN_GEN_CODE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_gen_code (TREE_VALUE (args)); - case BUILT_IN_GEN_INST: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_gen_inst (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_GEN_PTYPE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_gen_ptype (TREE_VALUE (args)); - case BUILT_IN_GETASSOCIATION: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_getassociation (TREE_VALUE (args)); - case BUILT_IN_GETSTACK: - if (check_arglist_length (args, 1, 2, fnname) < 0) - return error_mark_node; - return build_chill_getstack (TREE_VALUE (args), - TREE_CHAIN (args) == NULL_TREE ? NULL_TREE : TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_GETTEXTACCESS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_gettextaccess (TREE_VALUE (args)); - case BUILT_IN_GETTEXTINDEX: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_gettextindex (TREE_VALUE (args)); - case BUILT_IN_GETTEXTRECORD: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_gettextrecord (TREE_VALUE (args)); - case BUILT_IN_GETUSAGE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_getusage (TREE_VALUE (args)); - case BUILT_IN_HOURS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_duration (TREE_VALUE (args), HOURS_MULTIPLIER, - fnname, HOURS_MAX); - case BUILT_IN_INDEXABLE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_indexable (TREE_VALUE (args)); - case BUILT_IN_INTTIME: - if (check_arglist_length (args, 2, 7, fnname) < 0) - return error_mark_node; - return build_chill_inttime (TREE_VALUE (args), - TREE_CHAIN (args)); - case BUILT_IN_ISASSOCIATED: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_isassociated (TREE_VALUE (args)); - case BUILT_IN_LENGTH: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_length (TREE_VALUE (args)); - case BUILT_IN_LN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__log"); - case BUILT_IN_LOG: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__log10"); - case BUILT_IN_LOWER: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_lower (TREE_VALUE (args)); - case BUILT_IN_MAX: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_max (TREE_VALUE (args)); - case BUILT_IN_MILLISECS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_duration (TREE_VALUE (args), MILLISECS_MULTIPLIER, - fnname, MILLISECS_MAX); - case BUILT_IN_MIN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_min (TREE_VALUE (args)); - case BUILT_IN_MINUTES: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_duration (TREE_VALUE (args), MINUTES_MULTIPLIER, - fnname, MINUTES_MAX); - case BUILT_IN_MODIFY: - if (check_arglist_length (args, 1, -1, fnname) < 0) - return error_mark_node; - return build_chill_modify (TREE_VALUE (args), TREE_CHAIN (args)); - case BUILT_IN_NUM: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_num (TREE_VALUE (args)); - case BUILT_IN_OUTOFFILE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_outoffile (TREE_VALUE (args)); - case BUILT_IN_PRED: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_pred_or_succ (TREE_VALUE (args), MINUS_EXPR); - case BUILT_IN_PROC_TYPE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_proc_type (TREE_VALUE (args)); - case BUILT_IN_QUEUE_LENGTH: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_queue_length (TREE_VALUE (args)); - case BUILT_IN_READABLE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_readable (TREE_VALUE (args)); - case BUILT_IN_READRECORD: - if (check_arglist_length (args, 1, 3, fnname) < 0) - return error_mark_node; - return build_chill_readrecord (TREE_VALUE (args), TREE_CHAIN (args)); - case BUILT_IN_READTEXT: - if (check_arglist_length (args, 2, -1, fnname) < 0) - return error_mark_node; - return build_chill_readtext (TREE_VALUE (args), - TREE_CHAIN (args)); - case BUILT_IN_RETURN_MEMORY: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_return_memory (TREE_VALUE (args)); - case BUILT_IN_SECS: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_duration (TREE_VALUE (args), SECS_MULTIPLIER, - fnname, SECS_MAX); - case BUILT_IN_SEQUENCIBLE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_sequencible (TREE_VALUE (args)); - case BUILT_IN_SETTEXTACCESS: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_chill_settextaccess (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_SETTEXTINDEX: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_chill_settextindex (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_SETTEXTRECORD: - if (check_arglist_length (args, 2, 2, fnname) < 0) - return error_mark_node; - return build_chill_settextrecord (TREE_VALUE (args), - TREE_VALUE (TREE_CHAIN (args))); - case BUILT_IN_CH_SIN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__sin"); - case BUILT_IN_SIZE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_sizeof (TREE_VALUE (args)); - case BUILT_IN_SQRT: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__sqrt"); - case BUILT_IN_SUCC: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_pred_or_succ (TREE_VALUE (args), PLUS_EXPR); - case BUILT_IN_TAN: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_floatcall (TREE_VALUE (args), - IDENTIFIER_POINTER (fnname), - "__tan"); - case BUILT_IN_TERMINATE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_terminate (TREE_VALUE (args)); - case BUILT_IN_UPPER: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_upper (TREE_VALUE (args)); - case BUILT_IN_VARIABLE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_variable (TREE_VALUE (args)); - case BUILT_IN_WRITEABLE: - if (check_arglist_length (args, 1, 1, fnname) < 0) - return error_mark_node; - return build_chill_writeable (TREE_VALUE (args)); - case BUILT_IN_WRITERECORD: - if (check_arglist_length (args, 2, 3, fnname) < 0) - return error_mark_node; - return build_chill_writerecord (TREE_VALUE (args), TREE_CHAIN (args)); - case BUILT_IN_WRITETEXT: - if (check_arglist_length (args, 2, -1, fnname) < 0) - return error_mark_node; - return build_chill_writetext (TREE_VALUE (args), - TREE_CHAIN (args)); - - case BUILT_IN_EXPIRED: - case BUILT_IN_WAIT: - sorry ("unimplemented built-in function `%s'", - IDENTIFIER_POINTER (fnname)); - break; - default: - error ("internal error - bad built-in function `%s'", - IDENTIFIER_POINTER (fnname)); - } - } - return build_chill_function_call (func, args); - } - - if (chill_varying_type_p (TREE_TYPE (func))) - type = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (type))); - - if (CH_STRING_TYPE_P (type)) - { - if (args == NULL_TREE) - { - error ("empty expression in string index"); - return error_mark_node; - } - if (TREE_CHAIN (args) != NULL) - { - error ("only one expression allowed in string index"); - return error_mark_node; - } - if (flag_old_strings) - return build_chill_slice_with_length (func, - TREE_VALUE (args), - integer_one_node); - else if (CH_BOOLS_TYPE_P (type)) - return build_chill_bitref (func, args); - else - return build_chill_array_ref (func, args); - } - - else if (TREE_CODE (type) == ARRAY_TYPE) - return build_chill_array_ref (func, args); - - if (TREE_CODE (func) != ERROR_MARK) - error ("invalid: primval ( untyped_exprlist )"); - return error_mark_node; -} - -/* Given a set stored as one bit per char (in BUFFER[0 .. BIT_SIZE-1]), - return a CONTRUCTOR, of type TYPE (a SET_TYPE). */ -static tree -expand_packed_set (buffer, bit_size, type) - const char *buffer; - int bit_size; - tree type; -{ - /* The ordinal number corresponding to the first stored bit. */ - HOST_WIDE_INT first_bit_no = - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))); - tree list = NULL_TREE; - int i; - - for (i = 0; i < bit_size; i++) - if (buffer[i]) - { - int next_0; - for (next_0 = i + 1; - next_0 < bit_size && buffer[next_0]; next_0++) - ; - if (next_0 == i + 1) - list = tree_cons (NULL_TREE, - build_int_2 (i + first_bit_no, 0), list); - else - { - list = tree_cons (build_int_2 (i + first_bit_no, 0), - build_int_2 (next_0 - 1 + first_bit_no, 0), list); - /* advance i past the range of 1-bits */ - i = next_0; - } - } - list = build (CONSTRUCTOR, type, NULL_TREE, nreverse (list)); - TREE_CONSTANT (list) = 1; - return list; -} - -/* - * fold a set represented as a CONSTRUCTOR list. - * An empty set has a NULL_TREE in its TREE_OPERAND (set, 1) slot. - */ -static tree -fold_set_expr (code, op0, op1) - enum chill_tree_code code; - tree op0, op1; -{ - tree temp; - char *buffer0, *buffer1 = NULL, *bufferr; - int i, size0, size1, first_unused_bit; - - if (! TREE_CONSTANT (op0) || TREE_CODE (op0) != CONSTRUCTOR) - return NULL_TREE; - - if (op1 - && (! TREE_CONSTANT (op1) || TREE_CODE (op1) != CONSTRUCTOR)) - return NULL_TREE; - - size0 = int_size_in_bytes (TREE_TYPE (op0)) * BITS_PER_UNIT; - if (size0 < 0) - { - error ("operand is variable-size bitstring/power-set"); - return error_mark_node; - } - buffer0 = (char*) alloca (size0); - - temp = get_set_constructor_bits (op0, buffer0, size0); - if (temp) - return NULL_TREE; - - if (op0 && op1) - { - size1 = int_size_in_bytes (TREE_TYPE (op1)) * BITS_PER_UNIT; - if (size1 < 0) - { - error ("operand is variable-size bitstring/power-set"); - return error_mark_node; - } - if (size0 != size1) - return NULL_TREE; - buffer1 = (char*) alloca (size1); - temp = get_set_constructor_bits (op1, buffer1, size1); - if (temp) - return NULL_TREE; - } - - bufferr = (char*) alloca (size0); /* result buffer */ - - switch ((int)code) - { - case SET_NOT_EXPR: - case BIT_NOT_EXPR: - for (i = 0; i < size0; i++) - bufferr[i] = 1 & ~buffer0[i]; - goto build_result; - case SET_AND_EXPR: - case BIT_AND_EXPR: - for (i = 0; i < size0; i++) - bufferr[i] = buffer0[i] & buffer1[i]; - goto build_result; - case SET_IOR_EXPR: - case BIT_IOR_EXPR: - for (i = 0; i < size0; i++) - bufferr[i] = buffer0[i] | buffer1[i]; - goto build_result; - case SET_XOR_EXPR: - case BIT_XOR_EXPR: - for (i = 0; i < size0; i++) - bufferr[i] = (buffer0[i] ^ buffer1[i]) & 1; - goto build_result; - case SET_DIFF_EXPR: - case MINUS_EXPR: - for (i = 0; i < size0; i++) - bufferr[i] = buffer0[i] & ~buffer1[i]; - goto build_result; - build_result: - /* mask out unused bits. Same as runtime library does. */ - first_unused_bit = TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (op0)))) - - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (op0)))) + 1; - for (i = first_unused_bit; i < size0 ; i++) - bufferr[i] = 0; - return expand_packed_set (bufferr, size0, TREE_TYPE (op0)); - case EQ_EXPR: - for (i = 0; i < size0; i++) - if (buffer0[i] != buffer1[i]) - return boolean_false_node; - return boolean_true_node; - - case NE_EXPR: - for (i = 0; i < size0; i++) - if (buffer0[i] != buffer1[i]) - return boolean_true_node; - return boolean_false_node; - - default: - return NULL_TREE; - } -} - -/* - * build a set or bit-array expression. Type-checking is - * done elsewhere. - */ -static tree -build_compare_set_expr (code, op0, op1) - enum tree_code code; - tree op0, op1; -{ - tree result_type = NULL_TREE; - const char *fnname; - tree x; - - /* These conversions are needed if -fold-strings. */ - if (TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE) - { - if (CH_BOOLS_ONE_P (TREE_TYPE (op1))) - return build_compare_discrete_expr (code, - op0, - convert (boolean_type_node, op1)); - else - op0 = convert (bitstring_one_type_node, op0); - } - if (TREE_CODE (TREE_TYPE (op1)) == BOOLEAN_TYPE) - { - if (CH_BOOLS_ONE_P (TREE_TYPE (op0))) - return build_compare_discrete_expr (code, - convert (boolean_type_node, op0), - op1); - else - op1 = convert (bitstring_one_type_node, op1); - } - - switch ((int)code) - { - case EQ_EXPR: - { - tree temp = fold_set_expr (EQ_EXPR, op0, op1); - if (temp) - return temp; - fnname = "__eqpowerset"; - goto compare_powerset; - } - break; - - case GE_EXPR: - /* switch operands and fall thru */ - x = op0; - op0 = op1; - op1 = x; - - case LE_EXPR: - fnname = "__lepowerset"; - goto compare_powerset; - - case GT_EXPR: - /* switch operands and fall thru */ - x = op0; - op0 = op1; - op1 = x; - - case LT_EXPR: - fnname = "__ltpowerset"; - goto compare_powerset; - - case NE_EXPR: - return invert_truthvalue (build_compare_set_expr (EQ_EXPR, op0, op1)); - - compare_powerset: - { - tree tsize = powersetlen (op0); - - if (TREE_CODE (TREE_TYPE (op0)) != SET_TYPE) - tsize = fold (build (MULT_EXPR, sizetype, tsize, - size_int (BITS_PER_UNIT))); - - return build_chill_function_call (lookup_name (get_identifier (fnname)), - tree_cons (NULL_TREE, force_addr_of (op0), - tree_cons (NULL_TREE, force_addr_of (op1), - tree_cons (NULL_TREE, tsize, NULL_TREE)))); - } - break; - - default: - if ((int) code >= (int)LAST_AND_UNUSED_TREE_CODE) - { - error ("tree code `%s' unhandled in build_compare_set_expr", - tree_code_name[(int)code]); - return error_mark_node; - } - break; - } - - return build ((enum tree_code)code, result_type, - op0, op1); -} - -/* Convert a varying string (or array) to dynamic non-varying string: - EXP becomes EXP.var_data(0 UP EXP.var_length). */ - -tree -varying_to_slice (exp) - tree exp; -{ - if (!chill_varying_type_p (TREE_TYPE (exp))) - return exp; - else - { tree size, data, data_domain, min; - tree novelty = CH_NOVELTY (TREE_TYPE (exp)); - exp = save_if_needed (exp); - size = build_component_ref (exp, var_length_id); - data = build_component_ref (exp, var_data_id); - TREE_TYPE (data) = copy_novelty (novelty, TREE_TYPE (data)); - data_domain = TYPE_DOMAIN (TREE_TYPE (data)); - if (data_domain != NULL_TREE - && TYPE_MIN_VALUE (data_domain) != NULL_TREE) - min = TYPE_MIN_VALUE (data_domain); - else - min = integer_zero_node; - return build_chill_slice (data, min, size); - } -} - -/* Convert a scalar argument to a string or array type. This is a subroutine - of `build_concat_expr'. */ - -static tree -scalar_to_string (exp) - tree exp; -{ - tree type = TREE_TYPE (exp); - - if (SCALAR_P (type)) - { - int was_const = TREE_CONSTANT (exp); - if (TREE_TYPE (exp) == char_type_node) - exp = convert (string_one_type_node, exp); - else if (TREE_TYPE (exp) == boolean_type_node) - exp = convert (bitstring_one_type_node, exp); - else - exp = convert (build_array_type_for_scalar (type), exp); - TREE_CONSTANT (exp) = was_const; - return exp; - } - return varying_to_slice (exp); -} - -/* FIXME: Generalize this to general arrays (not just strings), - at least for the compiler-generated case of padding fixed-length arrays. */ - -static tree -build_concat_expr (op0, op1) - tree op0, op1; -{ - tree orig_op0 = op0, orig_op1 = op1; - tree type0, type1, size0, size1, res; - - op0 = scalar_to_string (op0); - type0 = TREE_TYPE (op0); - op1 = scalar_to_string (op1); - type1 = TREE_TYPE (op1); - size1 = size_in_bytes (type1); - - /* try to fold constant string literals */ - if (TREE_CODE (op0) == STRING_CST - && (TREE_CODE (op1) == STRING_CST - || TREE_CODE (op1) == UNDEFINED_EXPR) - && TREE_CODE (size1) == INTEGER_CST) - { - int len0 = TREE_STRING_LENGTH (op0); - int len1 = TREE_INT_CST_LOW (size1); - char *result = xmalloc (len0 + len1 + 1); - memcpy (result, TREE_STRING_POINTER (op0), len0); - if (TREE_CODE (op1) == UNDEFINED_EXPR) - memset (&result[len0], '\0', len1); - else - memcpy (&result[len0], TREE_STRING_POINTER (op1), len1); - return build_chill_string (len0 + len1, result); - } - else if (TREE_CODE (type0) == TREE_CODE (type1)) - { - tree result_size; - struct ch_class result_class; - struct ch_class class0; - struct ch_class class1; - - class0 = chill_expr_class (orig_op0); - class1 = chill_expr_class (orig_op1); - - if (TREE_CODE (type0) == SET_TYPE) - { - result_size = fold (build (PLUS_EXPR, integer_type_node, - discrete_count (TYPE_DOMAIN (type0)), - discrete_count (TYPE_DOMAIN (type1)))); - result_class.mode = build_bitstring_type (result_size); - } - else - { - tree max0 = TYPE_MAX_VALUE (type0); - tree max1 = TYPE_MAX_VALUE (type1); - - /* new array's dynamic size (in bytes). */ - size0 = size_in_bytes (type0); - /* size1 was computed above. */ - - result_size = size_binop (PLUS_EXPR, size0, size1); - /* new array's type. */ - result_class.mode = build_string_type (char_type_node, result_size); - - if (max0 || max1) - { - max0 = max0 == 0 ? size0 : convert (sizetype, max0); - max1 = max1 == 0 ? size1 : convert (sizetype, max1); - TYPE_MAX_VALUE (result_class.mode) - = size_binop (PLUS_EXPR, max0, max1); - } - } - - if (class0.kind == CH_VALUE_CLASS || class1.kind == CH_VALUE_CLASS) - { - tree novelty0 = CH_NOVELTY (TREE_TYPE (orig_op0)); - result_class.kind = CH_VALUE_CLASS; - if (class0.kind == CH_VALUE_CLASS && novelty0 != NULL_TREE) - SET_CH_NOVELTY_NONNIL (result_class.mode, novelty0); - else if (class1.kind == CH_VALUE_CLASS) - SET_CH_NOVELTY (result_class.mode, - CH_NOVELTY (TREE_TYPE (orig_op1))); - } - else - result_class.kind = CH_DERIVED_CLASS; - - if (TREE_CODE (result_class.mode) == SET_TYPE - && TREE_CONSTANT (op0) && TREE_CONSTANT (op1) - && TREE_CODE (op0) == CONSTRUCTOR && TREE_CODE (op1) == CONSTRUCTOR) - { - HOST_WIDE_INT size0, size1; char *buffer; - size0 = TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type0))) + 1; - size1 = TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type1))) + 1; - buffer = (char*) alloca (size0 + size1); - if (size0 < 0 || size1 < 0 - || get_set_constructor_bits (op0, buffer, size0) - || get_set_constructor_bits (op1, buffer + size0, size1)) - abort (); - res = expand_packed_set (buffer, size0 + size1, result_class.mode); - } - else - res = build (CONCAT_EXPR, result_class.mode, op0, op1); - return convert_to_class (result_class, res); - } - else - { - error ("incompatible modes in concat expression"); - return error_mark_node; - } -} - -/* - * handle varying and fixed array compare operations - */ -static tree -build_compare_string_expr (code, op0, op1) - enum tree_code code; - tree op0, op1; -{ - if (op0 == NULL_TREE || TREE_CODE (op0) == ERROR_MARK) - return error_mark_node; - if (op1 == NULL_TREE || TREE_CODE (op1) == ERROR_MARK) - return error_mark_node; - - if (tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (op0)), - TYPE_SIZE (TREE_TYPE (op1))) - && ! chill_varying_type_p (TREE_TYPE (op0)) - && ! chill_varying_type_p (TREE_TYPE (op1))) - { - tree size = size_in_bytes (TREE_TYPE (op0)); - tree temp = lookup_name (get_identifier ("memcmp")); - temp = build_chill_function_call (temp, - tree_cons (NULL_TREE, force_addr_of (op0), - tree_cons (NULL_TREE, force_addr_of (op1), - tree_cons (NULL_TREE, size, NULL_TREE)))); - return build_compare_discrete_expr (code, temp, integer_zero_node); - } - - switch ((int)code) - { - case EQ_EXPR: - code = STRING_EQ_EXPR; - break; - case GE_EXPR: - return invert_truthvalue (build_compare_string_expr (LT_EXPR, op0, op1)); - case LE_EXPR: - return invert_truthvalue (build_compare_string_expr (LT_EXPR, op1, op0)); - case GT_EXPR: - return build_compare_string_expr (LT_EXPR, op1, op0); - case LT_EXPR: - code = STRING_LT_EXPR; - break; - case NE_EXPR: - return invert_truthvalue (build_compare_string_expr (EQ_EXPR, op0, op1)); - default: - error ("invalid operation on array of chars"); - return error_mark_node; - } - - return build (code, boolean_type_node, op0, op1); -} - -static tree -compare_records (exp0, exp1) - tree exp0, exp1; -{ - tree type = TREE_TYPE (exp0); - tree field; - int have_variants = 0; - - tree result = boolean_true_node; - - if (TREE_CODE (type) != RECORD_TYPE) - abort (); - - exp0 = save_if_needed (exp0); - exp1 = save_if_needed (exp1); - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - if (DECL_NAME (field) == NULL_TREE) - { - have_variants = 1; - break; - } - } - - /* in case of -fpack we always do a memcmp */ - if (maximum_field_alignment != 0) - { - tree memcmp_func = lookup_name (get_identifier ("memcmp")); - tree arg1 = force_addr_of (exp0); - tree arg2 = force_addr_of (exp1); - tree arg3 = size_in_bytes (type); - tree fcall = build_chill_function_call (memcmp_func, - tree_cons (NULL_TREE, arg1, - tree_cons (NULL_TREE, arg2, - tree_cons (NULL_TREE, arg3, NULL_TREE)))); - - if (have_variants) - warning ("comparison of variant structures is unsafe"); - result = build_chill_binary_op (EQ_EXPR, fcall, integer_zero_node); - return result; - } - - if (have_variants) - { - sorry ("compare with variant records"); - return error_mark_node; - } - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - tree exp0fld = build_component_ref (exp0, DECL_NAME (field)); - tree exp1fld = build_component_ref (exp1, DECL_NAME (field)); - tree eq_flds = build_chill_binary_op (EQ_EXPR, exp0fld, exp1fld); - result = build_chill_binary_op (TRUTH_AND_EXPR, result, eq_flds); - } - return result; -} - -int -compare_int_csts (op, val1, val2) - enum tree_code op; - tree val1, val2; -{ - int result; - tree tmp; - tree type1 = TREE_TYPE (val1); - tree type2 = TREE_TYPE (val2); - switch (op) - { - case GT_EXPR: - case GE_EXPR: - tmp = val1; val1 = val2; val2 = tmp; - tmp = type1; type1 = type2; type2 = tmp; - op = (op == GT_EXPR) ? LT_EXPR : LE_EXPR; - /* ... fall through ... */ - case LT_EXPR: - case LE_EXPR: - if (!TREE_UNSIGNED (type1)) - { - if (!TREE_UNSIGNED (type2)) - result = INT_CST_LT (val1, val2); - else if (TREE_INT_CST_HIGH (val1) < 0) - result = 1; - else - result = INT_CST_LT_UNSIGNED (val1, val2); - } - else - { - if (!TREE_UNSIGNED (type2) && TREE_INT_CST_HIGH (val2) < 0) - result = 0; - else - result = INT_CST_LT_UNSIGNED (val1, val2); - } - if (op == LT_EXPR || result == 1) - break; - /* else fall through ... */ - case NE_EXPR: - case EQ_EXPR: - if (TREE_INT_CST_LOW (val1) == TREE_INT_CST_LOW (val2) - && TREE_INT_CST_HIGH (val1) == TREE_INT_CST_HIGH (val2) - /* They're bitwise equal. - Check for one being negative and the other unsigned. */ - && (TREE_INT_CST_HIGH (val2) >= 0 - || TREE_UNSIGNED (TREE_TYPE (val1)) - == TREE_UNSIGNED (TREE_TYPE (val2)))) - result = 1; - else - result = 0; - if (op == NE_EXPR) - result = !result; - break; - default: - abort(); - } - return result; -} - -/* Build an expression to compare discrete values VAL1 and VAL2. - This does not check that they are discrete, nor that they are - compatible; if you need such checks use build_compare_expr. */ - -tree -build_compare_discrete_expr (op, val1, val2) - enum tree_code op; - tree val1, val2; -{ - tree type1 = TREE_TYPE (val1); - tree type2 = TREE_TYPE (val2); - tree tmp; - - if (TREE_CODE (val1) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) - { - if (compare_int_csts (op, val1, val2)) - return boolean_true_node; - else - return boolean_false_node; - } - - if (TREE_UNSIGNED (type1) != TREE_UNSIGNED (type2)) - { - switch (op) - { - case GT_EXPR: - case GE_EXPR: - tmp = val1; val1 = val2; val2 = tmp; - tmp = type1; type1 = type2; type2 = tmp; - op = (op == GT_EXPR) ? LT_EXPR : LE_EXPR; - /* ... fall through ... */ - case LT_EXPR: - case LE_EXPR: - if (TREE_UNSIGNED (type2)) - { - tmp = build_int_2_wide (0, 0); - TREE_TYPE (tmp) = type1; - val1 = save_expr (val1); - tmp = fold (build (LT_EXPR, boolean_type_node, val1, tmp)); - if (TYPE_PRECISION (type2) < TYPE_PRECISION (type1)) - { - type2 = unsigned_type (type1); - val2 = convert_to_integer (type2, val2); - } - val1 = convert_to_integer (type2, val1); - return fold (build (TRUTH_OR_EXPR, boolean_type_node, - tmp, - fold (build (op, boolean_type_node, - val1, val2)))); - } - unsigned_vs_signed: /* val1 is unsigned, val2 is signed */ - tmp = build_int_2_wide (0, 0); - TREE_TYPE (tmp) = type2; - val2 = save_expr (val2); - tmp = fold (build (GE_EXPR, boolean_type_node, val2, tmp)); - if (TYPE_PRECISION (type1) < TYPE_PRECISION (type2)) - { - type1 = unsigned_type (type2); - val1 = convert_to_integer (type1, val1); - } - val2 = convert_to_integer (type1, val2); - return fold (build (TRUTH_AND_EXPR, boolean_type_node, tmp, - fold (build (op, boolean_type_node, - val1, val2)))); - case EQ_EXPR: - if (TREE_UNSIGNED (val2)) - { - tmp = val1; val1 = val2; val2 = tmp; - tmp = type1; type1 = type2; type2 = tmp; - } - goto unsigned_vs_signed; - case NE_EXPR: - tmp = build_compare_expr (EQ_EXPR, val1, val2); - return build_chill_unary_op (TRUTH_NOT_EXPR, tmp); - default: - abort(); - } - } - if (TYPE_PRECISION (type1) > TYPE_PRECISION (type2)) - val2 = convert (type1, val2); - else if (TYPE_PRECISION (type1) < TYPE_PRECISION (type2)) - val1 = convert (type2, val1); - return fold (build (op, boolean_type_node, val1, val2)); -} - -tree -build_compare_expr (op, val1, val2) - enum tree_code op; - tree val1, val2; -{ - tree tmp; - tree type1, type2; - val1 = check_have_mode (val1, "relational expression"); - val2 = check_have_mode (val2, "relational expression"); - if (val1 == NULL_TREE || TREE_CODE (val1) == ERROR_MARK) - return error_mark_node; - if (val2 == NULL_TREE || TREE_CODE (val2) == ERROR_MARK) - return error_mark_node; - - if (pass == 1) - return build (op, NULL_TREE, val1, val2); - - if (!CH_COMPATIBLE_CLASSES (val1, val2)) - { - error ("incompatible operands to %s", boolean_code_name [op]); - return error_mark_node; - } - - tmp = CH_ROOT_MODE (TREE_TYPE (val1)); - if (tmp != TREE_TYPE (val1)) - val1 = convert (tmp, val1); - tmp = CH_ROOT_MODE (TREE_TYPE (val2)); - if (tmp != TREE_TYPE (val2)) - val2 = convert (tmp, val2); - - type1 = TREE_TYPE (val1); - type2 = TREE_TYPE (val2); - - if (TREE_CODE (type1) == SET_TYPE) - tmp = build_compare_set_expr (op, val1, val2); - - else if (discrete_type_p (type1)) - tmp = build_compare_discrete_expr (op, val1, val2); - - else if (chill_varying_type_p (type1) || chill_varying_type_p (type2) - || (TREE_CODE (type1) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type1)) == CHAR_TYPE) - || (TREE_CODE (type2) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type2)) == CHAR_TYPE) ) - tmp = build_compare_string_expr (op, val1, val2); - - else if ((TREE_CODE (type1) == RECORD_TYPE - || TREE_CODE (type2) == RECORD_TYPE) - && (op == EQ_EXPR || op == NE_EXPR)) - { - /* This is for handling INSTANCEs being compared against NULL. */ - if (val1 == null_pointer_node) - val1 = convert (type2, val1); - if (val2 == null_pointer_node) - val2 = convert (type1, val2); - - tmp = compare_records (val1, val2); - if (op == NE_EXPR) - tmp = build_chill_unary_op (TRUTH_NOT_EXPR, tmp); - } - - else if (TREE_CODE (type1) == REAL_TYPE || TREE_CODE (type2) == REAL_TYPE - || (op == EQ_EXPR || op == NE_EXPR)) - { - tmp = build (op, boolean_type_node, val1, val2); - CH_DERIVED_FLAG (tmp) = 1; /* Optimization to avoid copy_node. */ - tmp = fold (tmp); - } - - else - { - error ("relational operator not allowed for this mode"); - return error_mark_node; - } - - if (!CH_DERIVED_FLAG (tmp)) - { - tmp = copy_node (tmp); - CH_DERIVED_FLAG (tmp) = 1; - } - return tmp; -} - -tree -finish_chill_binary_op (node) - tree node; -{ - tree op0 = check_have_mode (TREE_OPERAND (node, 0), "binary expression"); - tree op1 = check_have_mode (TREE_OPERAND (node, 1), "binary expression"); - tree type0 = TREE_TYPE (op0); - tree type1 = TREE_TYPE (op1); - tree folded; - - if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) - return error_mark_node; - - if (UNSATISFIED (op0) || UNSATISFIED (op1)) - { - UNSATISFIED_FLAG (node) = 1; - return node; - } -#if 0 - /* assure that both operands have a type */ - if (! type0 && type1) - { - op0 = convert (type1, op0); - type0 = TREE_TYPE (op0); - } - if (! type1 && type0) - { - op1 = convert (type0, op1); - type1 = TREE_TYPE (op1); - } -#endif - UNSATISFIED_FLAG (node) = 0; -#if 0 - - { int op0f = TREE_CODE (op0) == FUNCTION_DECL; - int op1f = TREE_CODE (op1) == FUNCTION_DECL; - if (op0f) - op0 = convert (build_pointer_type (TREE_TYPE (op0)), op0); - if (op1f) - op1 = convert (build_pointer_type (TREE_TYPE (op1)), op1); - if ((op0f || op1f) - && code != EQ_EXPR && code != NE_EXPR) - error ("cannot use %s operator on PROC mode variable", - tree_code_name[(int)code]); - } - - if (invalid_left_operand (type0, code)) - { - error ("invalid left operand of %s", tree_code_name[(int)code]); - return error_mark_node; - } - if (invalid_right_operand (code, type1)) - { - error ("invalid right operand of %s", tree_code_name[(int)code]); - return error_mark_node; - } -#endif - - switch (TREE_CODE (node)) - { - case CONCAT_EXPR: - return build_concat_expr (op0, op1); - - case REPLICATE_EXPR: - op0 = fold (op0); - if (!TREE_CONSTANT (op0) || !TREE_CONSTANT (op1)) - { - error ("repetition expression must be constant"); - return error_mark_node; - } - else - return build_chill_repetition_op (op0, op1); - - case FLOOR_MOD_EXPR: - case TRUNC_MOD_EXPR: - if (TREE_CODE (type0) != INTEGER_TYPE) - { - error ("left argument to MOD/REM operator must be integral"); - return error_mark_node; - } - if (TREE_CODE (type1) != INTEGER_TYPE) - { - error ("right argument to MOD/REM operator must be integral"); - return error_mark_node; - } - break; - - case MINUS_EXPR: - if (TREE_CODE (type1) == SET_TYPE) - { - tree temp = fold_set_expr (MINUS_EXPR, op0, op1); - - if (temp) - return temp; - if (TYPE_MODE (type1) == BLKmode) - TREE_SET_CODE (node, SET_DIFF_EXPR); - else - { - op1 = build_chill_unary_op (BIT_NOT_EXPR, op1); - TREE_OPERAND (node, 1) = op1; - TREE_SET_CODE (node, BIT_AND_EXPR); - } - } - break; - - case TRUNC_DIV_EXPR: - if (TREE_CODE (type0) == REAL_TYPE || TREE_CODE (type1) == REAL_TYPE) - TREE_SET_CODE (node, RDIV_EXPR); - break; - - case BIT_AND_EXPR: - if (TYPE_MODE (type1) == BLKmode) - TREE_SET_CODE (node, SET_AND_EXPR); - goto fold_set_binop; - case BIT_IOR_EXPR: - if (TYPE_MODE (type1) == BLKmode) - TREE_SET_CODE (node, SET_IOR_EXPR); - goto fold_set_binop; - case BIT_XOR_EXPR: - if (TYPE_MODE (type1) == BLKmode) - TREE_SET_CODE (node, SET_XOR_EXPR); - goto fold_set_binop; - case SET_AND_EXPR: - case SET_IOR_EXPR: - case SET_XOR_EXPR: - case SET_DIFF_EXPR: - fold_set_binop: - if (TREE_CODE (type0) == SET_TYPE) - { - tree temp = fold_set_expr (TREE_CODE (node), op0, op1); - - if (temp) - return temp; - } - break; - - case SET_IN_EXPR: - if (TREE_CODE (type1) != SET_TYPE || CH_BOOLS_TYPE_P (type1)) - { - error ("right operand of IN is not a powerset"); - return error_mark_node; - } - if (!CH_COMPATIBLE (op0, TYPE_DOMAIN (type1))) - { - error ("left operand of IN incompatible with right operand"); - return error_mark_node; - } - type0 = CH_ROOT_MODE (type0); - if (type0 != TREE_TYPE (op0)) - TREE_OPERAND (node, 0) = op0 = convert (type0, op0); - TREE_TYPE (node) = boolean_type_node; - CH_DERIVED_FLAG (node) = 1; - node = fold (node); - if (!CH_DERIVED_FLAG (node)) - { - node = copy_node (node); - CH_DERIVED_FLAG (node) = 1; - } - return node; - case NE_EXPR: - case EQ_EXPR: - case GE_EXPR: - case GT_EXPR: - case LE_EXPR: - case LT_EXPR: - return build_compare_expr (TREE_CODE (node), op0, op1); - default: - ; - } - - if (!CH_COMPATIBLE_CLASSES (op0, op1)) - { - error ("incompatible operands to %s", tree_code_name[(int) TREE_CODE (node)]); - return error_mark_node; - } - - if (TREE_TYPE (node) == NULL_TREE) - { - struct ch_class class; - class = CH_ROOT_RESULTING_CLASS (op0, op1); - TREE_OPERAND (node, 0) = op0 = convert_to_class (class, op0); - type0 = TREE_TYPE (op0); - TREE_OPERAND (node, 1) = op1 = convert_to_class (class, op1); - type1 = TREE_TYPE (op1); - TREE_TYPE (node) = class.mode; - folded = convert_to_class (class, fold (node)); - } - else - folded = fold (node); -#if 0 - if (folded == node) - TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); -#endif - if (TREE_CODE (node) == TRUNC_DIV_EXPR) - { - if (TREE_CONSTANT (op1)) - { - if (tree_int_cst_equal (op1, integer_zero_node)) - { - error ("division by zero"); - return integer_zero_node; - } - } - else if (range_checking) - { -#if 0 - tree test = - build (EQ_EXPR, boolean_type_node, op1, integer_zero_node); - /* Should this be overflow? */ - folded = check_expression (folded, test, - ridpointers[(int) RID_RANGEFAIL]); -#endif - } - } - return folded; -} - -/* - * This implements the '->' operator, which, like the '&' in C, - * returns a pointer to an object, which has the type of - * pointer-to-that-object. - * - * FORCE is 0 when we're evaluating a user-level syntactic construct, - * and 1 when we're calling from inside the compiler. - */ -tree -build_chill_arrow_expr (ref, force) - tree ref; - int force; -{ - tree addr_type; - tree result; - - if (pass == 1) - { - error ("-> operator not allow in constant expression"); - return error_mark_node; - } - - if (ref == NULL_TREE || TREE_CODE (ref) == ERROR_MARK) - return ref; - - while (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) - ref = convert (TREE_TYPE (TREE_TYPE (ref)), ref); - - if (!force && ! CH_LOCATION_P (ref)) - { - if (TREE_CODE (ref) == STRING_CST) - pedwarn ("taking the address of a string literal is non-standard"); - else if (TREE_CODE (TREE_TYPE (ref)) == FUNCTION_TYPE) - pedwarn ("taking the address of a function is non-standard"); - else - { - error ("ADDR requires a LOCATION argument"); - return error_mark_node; - } - /* FIXME: Should we be sure that ref isn't a - function if we're being pedantic? */ - } - - addr_type = build_pointer_type (TREE_TYPE (ref)); - -#if 0 - /* This transformation makes chill_expr_class return CH_VALUE_CLASS - when it should return CH_REFERENCE_CLASS. That could be fixed, - but we probably don't want this transformation anyway. */ - if (TREE_CODE (ref) == NOP_EXPR) /* RETYPE_EXPR */ - { - tree addr; - while (TREE_CODE (ref) == NOP_EXPR) /* RETYPE_EXPR */ - ref = TREE_OPERAND (ref, 0); - mark_addressable (ref); - addr = build1 (ADDR_EXPR, - build_pointer_type (TREE_TYPE (ref)), ref); - return build1 (NOP_EXPR, /* RETYPE_EXPR */ - addr_type, - addr); - } - else -#endif - { - if (! mark_addressable (ref)) - { - error ("-> expression is not addressable"); - return error_mark_node; - } - result = build1 (ADDR_EXPR, addr_type, ref); - if (staticp (ref) - && ! (TREE_CODE (ref) == FUNCTION_DECL - && DECL_CONTEXT (ref) != 0)) - TREE_CONSTANT (result) = 1; - return result; - } -} - -/* - * This implements the ADDR builtin function, which returns a - * free reference, analogous to the C 'void *'. - */ -tree -build_chill_addr_expr (ref, errormsg) - tree ref; - const char *errormsg; -{ - if (ref == error_mark_node) - return ref; - - if (! CH_LOCATION_P (ref) - && TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE) - { - error ("ADDR parameter must be a LOCATION"); - return error_mark_node; - } - ref = build_chill_arrow_expr (ref, 1); - - if (ref != NULL_TREE && TREE_CODE (ref) != ERROR_MARK) - TREE_TYPE (ref) = ptr_type_node; - else if (errormsg == NULL) - { - error ("possible internal error in build_chill_arrow_expr"); - return error_mark_node; - } - else - { - error ("%s is not addressable", errormsg); - return error_mark_node; - } - return ref; -} - -tree -build_chill_binary_op (code, op0, op1) - enum chill_tree_code code; - tree op0, op1; -{ - register tree result; - - if (op0 == NULL_TREE || TREE_CODE (op0) == ERROR_MARK) - return error_mark_node; - if (op1 == NULL_TREE || TREE_CODE (op1) == ERROR_MARK) - return error_mark_node; - - result = build (code, NULL_TREE, op0, op1); - - if (pass != 1) - result = finish_chill_binary_op (result); - return result; -} - -/* - * process a string repetition phrase '(' COUNT ')' STRING - */ -static tree -string_char_rep (count, string) - int count; - tree string; -{ - int slen, charindx, repcnt; - char ch; - char *temp; - const char *inp; - char *outp; - tree type; - - if (string == NULL_TREE || TREE_CODE (string) == ERROR_MARK) - return error_mark_node; - - type = TREE_TYPE (string); - slen = int_size_in_bytes (type); - temp = xmalloc (slen * count); - inp = &ch; - outp = temp; - if (TREE_CODE (string) == STRING_CST) - inp = TREE_STRING_POINTER (string); - else /* single character */ - ch = (char)TREE_INT_CST_LOW (string); - - /* copy the string/char COUNT times into the output buffer */ - for (outp = temp, repcnt = 0; repcnt < count; repcnt++) - for (charindx = 0; charindx < slen; charindx++) - *outp++ = inp[charindx]; - return build_chill_string (slen * count, temp); -} - -/* Build a bit-string constant containing with the given LENGTH - containing all ones (if VALUE is true), or all zeros (if VALUE is false). */ - -static tree -build_boring_bitstring (length, value) - long length; - int value; -{ - tree result; - tree list; /* Value of CONSTRUCTOR_ELTS in the result. */ - if (value && length > 0) - list = tree_cons (integer_zero_node, size_int (length - 1), NULL_TREE); - else - list = NULL_TREE; - - result = build (CONSTRUCTOR, - build_bitstring_type (size_int (length)), - NULL_TREE, - list); - TREE_CONSTANT (result) = 1; - CH_DERIVED_FLAG (result) = 1; - return result; -} - -/* - * handle a string repetition, with the syntax: - * ( COUNT ) 'STRING' - * COUNT is required to be constant, positive and folded. - */ -tree -build_chill_repetition_op (count_op, string) - tree count_op; - tree string; -{ - int count; - tree type = TREE_TYPE (string); - - if (TREE_CODE (count_op) != INTEGER_CST) - { - error ("repetition count is not an integer constant"); - return error_mark_node; - } - - count = TREE_INT_CST_LOW (count_op); - - if (count < 0) - { - error ("repetition count < 0"); - return error_mark_node; - } - if (! TREE_CONSTANT (string)) - { - error ("repetition value not constant"); - return error_mark_node; - } - - if (TREE_CODE (string) == STRING_CST) - return string_char_rep (count, string); - - switch ((int)TREE_CODE (type)) - { - case BOOLEAN_TYPE: - if (TREE_CODE (string) == INTEGER_CST) - return build_boring_bitstring (count, TREE_INT_CST_LOW (string)); - error ("bitstring repetition of non-constant boolean"); - return error_mark_node; - - case CHAR_TYPE: - return string_char_rep (count, string); - - case SET_TYPE: - { int i, tree_const = 1; - tree new_list = NULL_TREE; - tree vallist; - tree result; - tree domain = TYPE_DOMAIN (type); - tree orig_length; - HOST_WIDE_INT orig_len; - - if (!CH_BOOLS_TYPE_P (type)) /* cannot replicate a powerset */ - break; - - orig_length = discrete_count (domain); - - if (TREE_CODE (string) != CONSTRUCTOR || !TREE_CONSTANT (string) - || TREE_CODE (orig_length) != INTEGER_CST) - { - error ("string repetition operand is non-constant bitstring"); - return error_mark_node; - } - - - orig_len = TREE_INT_CST_LOW (orig_length); - - /* if the set is empty, this is NULL */ - vallist = TREE_OPERAND (string, 1); - - if (vallist == NULL_TREE) /* No bits are set. */ - return build_boring_bitstring (count * orig_len, 0); - else if (TREE_CHAIN (vallist) == NULL_TREE - && (TREE_PURPOSE (vallist) == NULL_TREE - ? (orig_len == 1 - && tree_int_cst_equal (TYPE_MIN_VALUE (domain), - TREE_VALUE (vallist))) - : (tree_int_cst_equal (TYPE_MIN_VALUE (domain), - TREE_PURPOSE (vallist)) - && tree_int_cst_equal (TYPE_MAX_VALUE (domain), - TREE_VALUE (vallist))))) - return build_boring_bitstring (count * orig_len, 1); - - for (i = 0; i < count; i++) - { - tree origin = build_int_2 (i * orig_len, 0); - tree temp; - - /* scan down the given value list, building - new bit-positions */ - for (temp = vallist; temp; temp = TREE_CHAIN (temp)) - { - tree new_value - = fold (build (PLUS_EXPR, TREE_TYPE (origin), - TREE_VALUE (temp))); - tree new_purpose = NULL_TREE; - - if (! TREE_CONSTANT (TREE_VALUE (temp))) - tree_const = 0; - if (TREE_PURPOSE (temp)) - { - new_purpose = fold (build (PLUS_EXPR, TREE_TYPE (origin), - origin, TREE_PURPOSE (temp))); - if (! TREE_CONSTANT (TREE_PURPOSE (temp))) - tree_const = 0; - } - - new_list = tree_cons (new_purpose, - new_value, new_list); - } - } - result = build (CONSTRUCTOR, - build_bitstring_type (size_int (count * orig_len)), - NULL_TREE, nreverse (new_list)); - TREE_CONSTANT (result) = tree_const; - CH_DERIVED_FLAG (result) = CH_DERIVED_FLAG (string); - return result; - } - - default: - error ("non-char, non-bit string repetition"); - return error_mark_node; - } - return error_mark_node; -} - -tree -finish_chill_unary_op (node) - tree node; -{ - enum chill_tree_code code = TREE_CODE (node); - tree op0 = check_have_mode (TREE_OPERAND (node, 0), "unary expression"); - tree type0 = TREE_TYPE (op0); - struct ch_class class; - - if (TREE_CODE (op0) == ERROR_MARK) - return error_mark_node; - /* The expression codes of the data types of the arguments tell us - whether the arguments are integers, floating, pointers, etc. */ - - if (TREE_CODE (type0) == REFERENCE_TYPE) - { - op0 = convert (TREE_TYPE (type0), op0); - type0 = TREE_TYPE (op0); - } - - if (invalid_right_operand (code, type0)) - { - error ("invalid operand of %s", - tree_code_name[(int)code]); - return error_mark_node; - } - switch ((int)TREE_CODE (type0)) - { - case ARRAY_TYPE: - if (TREE_CODE ( TREE_TYPE (type0)) == BOOLEAN_TYPE) - code = SET_NOT_EXPR; - else - { - error ("right operand of %s is not array of boolean", - tree_code_name[(int)code]); - return error_mark_node; - } - break; - case BOOLEAN_TYPE: - switch ((int)code) - { - case BIT_NOT_EXPR: - case TRUTH_NOT_EXPR: - return invert_truthvalue (truthvalue_conversion (op0)); - - default: - error ("%s operator applied to boolean variable", - tree_code_name[(int)code]); - return error_mark_node; - } - break; - - case SET_TYPE: - switch ((int)code) - { - case BIT_NOT_EXPR: - case NEGATE_EXPR: - { - tree temp = fold_set_expr (BIT_NOT_EXPR, op0, NULL_TREE); - - if (temp) - return temp; - - code = SET_NOT_EXPR; - } - break; - - default: - error ("invalid right operand of %s", tree_code_name[(int)code]); - return error_mark_node; - } - - } - - class = chill_expr_class (op0); - if (class.mode) - class.mode = CH_ROOT_MODE (class.mode); - TREE_SET_CODE (node, code); - TREE_OPERAND (node, 0) = op0 = convert_to_class (class, op0); - TREE_TYPE (node) = TREE_TYPE (op0); - - node = convert_to_class (class, fold (node)); - - /* FIXME: should call - * cond_type_range_exception (op0); - */ - return node; -} - -/* op is TRUTH_NOT_EXPR, BIT_NOT_EXPR, or NEGATE_EXPR */ - -tree -build_chill_unary_op (code, op0) - enum chill_tree_code code; - tree op0; -{ - register tree result = NULL_TREE; - - if (op0 == NULL_TREE || TREE_CODE (op0) == ERROR_MARK) - return error_mark_node; - - result = build1 (code, NULL_TREE, op0); - - if (pass != 1) - result = finish_chill_unary_op (result); - return result; -} - -tree -truthvalue_conversion (expr) - tree expr; -{ - if (expr == NULL_TREE || TREE_CODE (expr) == ERROR_MARK) - return error_mark_node; - -#if 0 /* what about a LE_EXPR (integer_type, integer_type ) */ - if (TREE_CODE (TREE_TYPE (expr)) != BOOLEAN_TYPE) - error ("non-boolean mode in conditional expression"); -#endif - - switch ((int)TREE_CODE (expr)) - { - /* It is simpler and generates better code to have only TRUTH_*_EXPR - or comparison expressions as truth values at this level. */ -#if 0 - case COMPONENT_REF: - /* A one-bit unsigned bit-field is already acceptable. */ - if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1))) - && TREE_UNSIGNED (TREE_OPERAND (expr, 1))) - return expr; - break; -#endif - - case EQ_EXPR: - /* It is simpler and generates better code to have only TRUTH_*_EXPR - or comparison expressions as truth values at this level. */ - case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case ERROR_MARK: - return expr; - - case INTEGER_CST: - return integer_zerop (expr) ? boolean_false_node : boolean_true_node; - - case REAL_CST: - return real_zerop (expr) ? boolean_false_node : boolean_true_node; - - case ADDR_EXPR: - if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) - return build (COMPOUND_EXPR, boolean_type_node, - TREE_OPERAND (expr, 0), boolean_true_node); - else - return boolean_true_node; - - case NEGATE_EXPR: - case ABS_EXPR: - case FLOAT_EXPR: - case FFS_EXPR: - /* These don't change whether an object is non-zero or zero. */ - return truthvalue_conversion (TREE_OPERAND (expr, 0)); - - case LROTATE_EXPR: - case RROTATE_EXPR: - /* These don't change whether an object is zero or non-zero, but - we can't ignore them if their second arg has side-effects. */ - if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))) - return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1), - truthvalue_conversion (TREE_OPERAND (expr, 0))); - else - return truthvalue_conversion (TREE_OPERAND (expr, 0)); - - case COND_EXPR: - /* Distribute the conversion into the arms of a COND_EXPR. */ - return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0), - truthvalue_conversion (TREE_OPERAND (expr, 1)), - truthvalue_conversion (TREE_OPERAND (expr, 2)))); - - case CONVERT_EXPR: - /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, - since that affects how `default_conversion' will behave. */ - if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE - || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) - break; - /* fall through... */ - case NOP_EXPR: - /* If this is widening the argument, we can ignore it. */ - if (TYPE_PRECISION (TREE_TYPE (expr)) - >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) - return truthvalue_conversion (TREE_OPERAND (expr, 0)); - break; - - case BIT_XOR_EXPR: - case MINUS_EXPR: - /* These can be changed into a comparison of the two objects. */ - if (TREE_TYPE (TREE_OPERAND (expr, 0)) - == TREE_TYPE (TREE_OPERAND (expr, 1))) - return build_chill_binary_op (NE_EXPR, TREE_OPERAND (expr, 0), - TREE_OPERAND (expr, 1)); - return build_chill_binary_op (NE_EXPR, TREE_OPERAND (expr, 0), - fold (build1 (NOP_EXPR, - TREE_TYPE (TREE_OPERAND (expr, 0)), - TREE_OPERAND (expr, 1)))); - } - - return build_chill_binary_op (NE_EXPR, expr, boolean_false_node); -} - - -/* - * return a folded tree for the powerset's length in bits. If a - * non-set is passed, we assume it's an array or boolean bytes. - */ -tree -powersetlen (powerset) - tree powerset; -{ - if (powerset == NULL_TREE || TREE_CODE (powerset) == ERROR_MARK) - return error_mark_node; - - return discrete_count (TYPE_DOMAIN (TREE_TYPE (powerset))); -} |