fed3cef0db
* builtins.c (c_strlen): Use size_diffop and return ssizetype value. (expand_builtin_strcpy): Pass correct type to size_binop. (expand_builtin_strcmp): Likewise. Clean up conditional structure. * c-decl.c (init_decl_processing): Don't call set_sizetype twice. (complete_array_type): Don't use size_binop for MAXINDEX. * c-typeck.c (c_sizeof): Use size_one_node and TYPE_SIZE_UNIT. (c_sizeof_nowarn, c_size_in_bytes): Likewise. (c_alignof): Use size_one_node. (build_unary_op): Pass arg of proper type to size_binop. (really_start_incremental_init, push_init_level): Use sizetype for constructor{,_bit,_unfilled}_index. (pop_init_label, output_init_element): Likewise. (output_pending_init_elements, process_init_element): Likewise. * calls.c (compute_argument_block_size): Field VAR is ssizetype. * expr.c (store_expr): Use size_int. (store_constructor): Use proper types for size_binop args. (get_inner_reference, expand_expr, case ARRAY_REF): Likewise. (expand_expr_unaligned): Likewise. (string_contant): Return object of sizetype. * expr.h (SUB_PARM_SIZE): Call size_diffop and pass proper types. (ARGS_SIZE_RTX): Call ARGS_SIZE_TREE. (ARGS_SIZE_TREE): Pass proper types to size_binop. * fold-const.c (int_const_binop): Refine when size_int is called. (fold_convert): Likewise. (size_int_wide): Rework to take KIND as arg, only take low order bits, handle new sizetype_tab datatype, and chain entries in size_table. (size_int_type_wide): New function. (size_binop): Validate types of arguments. (ssize_binop): Deleted. (size_diffop): New function. (extract_muldiv): Only fold division into multiplication for sizetypes. * function.c (assign_parms): Use size_diffop and make sure VAR field is of ssizetype; also pass proper type to size_binop. (locate_and_pad_parm, pad_to_arg_alignment): Likewise. (round_down): Deleted from here. * store-layout.c (sizetype_tab): Now an array. (sizetype_set, early_root_list): New variables. (variable_size): Use size_one_node. (round_up): Pass proper type to size_binop. (round_down): Moved to here and corrected as above. (layout_record): Pass proper arg types to size_binop. (layout_type): Likewise. If sizetype_set is zero, record the type just laid out. (make_unsigned_type): Don't call set_sizetype; (make_signed_type): Likewise; also, call fixup_signed_type. (initialize_sizetypes): New function. (set_sizetype): Make copy of types, set TYPE_IS_SIZETYPE, and set name of bitsizetype to "bit_size_type". Fix up type of sizes of all types made before call. * tm.texi (ROUND_TYPE_SIZE_UNIT): New macro. * tree.c (fix_sizetype): Deleted. (build_common_tree_nodes): Call initialize_sizetypes. (build_common_tree_nodes_2): Don't call fix_sizetype. * tree.h (TYPE_IS_SIZETYPE): New macro. (initialize_sizetype): New declaration. (enum size_type_kind): New type. (struct sizetype_tab): Deleted. (sizetype_tab): Now array; adjust sizetype macros. (size_diffop, size_int_type_wide): New functions. (size_int_wide): Change number of args and type; access macros changed. (ssize_int, sbitsize_int): New macros. * config/i960/i960.h (ROUND_TYPE_SIZE): Use size_int. (ROUND_TYPE_SIZE_UNIT): New macro. * ch/actions.c (chill_convert_for_assignment): Don't use size_binop for things that aren't sizes. (expand_varying_length_assignment): Likewise. * ch/convert.c (digest_array_tuple, convert): Likewise. * ch/typeck.c (build_chill_slice, smash_dummy_type): Likewise. (build_chill_slice_with_range): Likewise. (build_chill_slice_with_length): Likewise. (build_array_from_set): Adjust types for size_binop. * ch/expr.c (build_concat_expr, build_chill_repetition_op): Likewise. (build_chill_sizeof): Use TYPE_SIZE_UNIT. * ch/tree.c (build_string_type): Pass proper type to size_binop. * cp/class.c (dfs_build_vtable_offset_vtbl_entries): Don't use size_binop on things that are not sizes; ssize_binop deleted. Call size_diffop when appropriate. (dfs_build_vcall_offset_vtbl_entries): Likewise. (build_primary_vtable, build_secondary_vtable): Likewise. (dfs_set_offset_for_unshared_vbases, dfs_modify_vtables): Likewise. Variable I is HOST_WIDE_INT. (get_vfield_offset): Pass proper types to size_binop. (size_extra_vtbl_entries, layout_virtual_bases): Likewise. (finish_struct_1): Likewise. (skip_rtti_stuff): Arg N is now pointer to signed. (layout_class_type): Use size_zero_node. * cp/cp-tree.h (skip_rtti_stuff): Arg N is pointer to signed. * cp/cvt.c (cp_convert_to_pointer): Pass proper types to size_binop. * cp/decl.c (complete_arry_type): Pass proper types to size_binop. (xref_basetypes): BINFO_OFFSET is sizetype. * cp/error.c (dump_expr): Don't use size_binop non-sizes. * cp/expr.c (cplus_expand_constant): Pass proper types to size_binop. * cp/init.c (construct_virtual_bases): Fix type error. (build_vec_delete_1): Pass proper type to size_binop and don't fold result. * cp/lex.c (cp_make_lang_type): BINFO_OFFSET is sizetype. * cp/rtti.c (get_base_offset): Pass proper type to size_binop. * cp/search.c (dfs_find_vbases): Fix type error. (expand_upcast_fixups): Arg to skip_rtti_stuff is pointer to signed. (dfs_get_vbase_types): BINFO_OFFSET is sizetype. * cp/tree.c (debug_binfo): Variable N is signed. Use HOST_WIDE_INT_PRINT_DEC. * cp/typeck.c (comptypes): sizetype is same as equivalent integer type. (c_sizeof, c_sizeof_nowarn, expr_sizeof): Use TYPE_SIZE_UNIT, size_one_node and size_zero_node. (c_alignof): Use size_one_node. (build_component_addr): Pass proper types to size_binop. (expand_ptrmemfunc_cst): Don't use size_binop on non-sizes. * f/com.c (ffecom_arrayref_): Convert args to size_binop to proper type. (ffecom_tree_canonize_ptr_): Don't use size_binop for non-sizes. (ffecom_tree_canonize_ref_): Likewise. (type_for_mode): Handle TImode. * f/ste.c (ffeste_io_dofio_, ffeste_io_douio_): Use TYPE_SIZE_UNIT. (ffeste_io_ciclist_): Likewise. * java/expr.c (build_java_ret): Pass proper type to size_binop. From-SVN: r32225
299 lines
8.4 KiB
C
299 lines
8.4 KiB
C
/* Language-dependent node constructors for parse phase of GNU compiler.
|
||
Copyright (C) 1992, 1993, 1994, 1998, 1999, 2000
|
||
Free Software Foundation, Inc.
|
||
|
||
This file is part of GNU CC.
|
||
|
||
GNU CC is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 2, or (at your option)
|
||
any later version.
|
||
|
||
GNU CC is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GNU CC; see the file COPYING. If not, write to
|
||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||
Boston, MA 02111-1307, USA. */
|
||
|
||
#include "config.h"
|
||
#include "system.h"
|
||
#include "obstack.h"
|
||
#include "tree.h"
|
||
#include "ch-tree.h"
|
||
#include "toplev.h"
|
||
|
||
/* Here is how primitive or already-canonicalized types'
|
||
hash codes are made. */
|
||
#define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777)
|
||
|
||
extern struct obstack permanent_obstack;
|
||
/* This is special sentinel used to communicate from build_string_type
|
||
to layout_chill_range_type for the index range of a string. */
|
||
tree string_index_type_dummy;
|
||
|
||
static tree make_powerset_type PARAMS ((tree));
|
||
|
||
/* Build a chill string type.
|
||
For a character string, ELT_TYPE==char_type_node;
|
||
for a bit-string, ELT_TYPE==boolean_type_node. */
|
||
|
||
tree
|
||
build_string_type (elt_type, length)
|
||
tree elt_type;
|
||
tree length;
|
||
{
|
||
register tree t;
|
||
|
||
if (TREE_CODE (elt_type) == ERROR_MARK || TREE_CODE (length) == ERROR_MARK)
|
||
return error_mark_node;
|
||
|
||
/* Allocate the array after the pointer type,
|
||
in case we free it in type_hash_canon. */
|
||
|
||
if (pass > 0 && TREE_CODE (length) == INTEGER_CST
|
||
&& ! tree_int_cst_equal (length, integer_zero_node)
|
||
&& compare_int_csts (LT_EXPR, TYPE_MAX_VALUE (chill_unsigned_type_node),
|
||
length))
|
||
{
|
||
error ("string length > UPPER (UINT)");
|
||
length = integer_one_node;
|
||
}
|
||
|
||
/* Subtract 1 from length to get max index value.
|
||
Note we cannot use size_binop for pass 1 expressions. */
|
||
if (TREE_CODE (length) == INTEGER_CST || pass != 1)
|
||
length = size_binop (MINUS_EXPR, length, size_one_node);
|
||
else
|
||
length = build (MINUS_EXPR, sizetype, length, size_one_node);
|
||
|
||
t = make_node (elt_type == boolean_type_node ? SET_TYPE : ARRAY_TYPE);
|
||
TREE_TYPE (t) = elt_type;
|
||
|
||
MARK_AS_STRING_TYPE (t);
|
||
|
||
TYPE_DOMAIN (t) = build_chill_range_type (string_index_type_dummy,
|
||
integer_zero_node, length);
|
||
if (pass == 1 && TREE_CODE (length) == INTEGER_CST)
|
||
TYPE_DOMAIN (t) = layout_chill_range_type (TYPE_DOMAIN (t), 0);
|
||
|
||
if (pass != 1
|
||
|| (TREE_CODE (length) == INTEGER_CST && TYPE_SIZE (elt_type)))
|
||
{
|
||
if (TREE_CODE (t) == SET_TYPE)
|
||
t = layout_powerset_type (t);
|
||
else
|
||
t = layout_chill_array_type (t);
|
||
}
|
||
return t;
|
||
}
|
||
|
||
static tree
|
||
make_powerset_type (domain)
|
||
tree domain;
|
||
{
|
||
tree t = make_node (SET_TYPE);
|
||
|
||
TREE_TYPE (t) = boolean_type_node;
|
||
TYPE_DOMAIN (t) = domain;
|
||
|
||
return t;
|
||
}
|
||
|
||
/* Used to layout both bitstring and powerset types. */
|
||
|
||
tree
|
||
layout_powerset_type (type)
|
||
tree type;
|
||
{
|
||
tree domain = TYPE_DOMAIN (type);
|
||
|
||
if (! discrete_type_p (domain))
|
||
{
|
||
error ("Can only build a powerset from a discrete mode");
|
||
return error_mark_node;
|
||
}
|
||
|
||
if (TREE_CODE (TYPE_MAX_VALUE (domain)) == ERROR_MARK ||
|
||
TREE_CODE (TYPE_MIN_VALUE (domain)) == ERROR_MARK)
|
||
return error_mark_node;
|
||
|
||
if (TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST
|
||
|| TREE_CODE (TYPE_MIN_VALUE (domain)) != INTEGER_CST)
|
||
{
|
||
if (CH_BOOLS_TYPE_P (type))
|
||
error ("non-constant bitstring size invalid");
|
||
else
|
||
error ("non-constant powerset size invalid");
|
||
return error_mark_node;
|
||
}
|
||
|
||
if (TYPE_SIZE (type) == 0)
|
||
layout_type (type);
|
||
return type;
|
||
}
|
||
|
||
/* Build a SET_TYPE node whose elements are from the set of values
|
||
in TYPE. TYPE must be a discrete mode; we check for that here. */
|
||
tree
|
||
build_powerset_type (type)
|
||
tree type;
|
||
{
|
||
tree t = make_powerset_type (type);
|
||
if (pass != 1)
|
||
t = layout_powerset_type (t);
|
||
return t;
|
||
}
|
||
|
||
tree
|
||
build_bitstring_type (size_in_bits)
|
||
tree size_in_bits;
|
||
{
|
||
return build_string_type (boolean_type_node, size_in_bits);
|
||
}
|
||
|
||
/* Return get_identifier (the concatenations of part1, part2, and part3). */
|
||
|
||
tree
|
||
get_identifier3 (part1, part2, part3)
|
||
const char *part1, *part2, *part3;
|
||
{
|
||
char *buf = (char*)
|
||
alloca (strlen(part1) + strlen(part2) + strlen(part3) + 1);
|
||
sprintf (buf, "%s%s%s", part1, part2, part3);
|
||
return get_identifier (buf);
|
||
}
|
||
|
||
/* Build an ALIAS_DECL for the prefix renamed clause:
|
||
(OLD_PREFIX -> NEW_PREFIX) ! POSTFIX. */
|
||
|
||
tree
|
||
build_alias_decl (old_prefix, new_prefix, postfix)
|
||
tree old_prefix, new_prefix, postfix;
|
||
{
|
||
tree decl = make_node (ALIAS_DECL);
|
||
|
||
const char *postfix_pointer = IDENTIFIER_POINTER (postfix);
|
||
int postfix_length = IDENTIFIER_LENGTH (postfix);
|
||
int old_length = old_prefix ? IDENTIFIER_LENGTH(old_prefix) : 0;
|
||
int new_length = new_prefix ? IDENTIFIER_LENGTH(new_prefix) : 0;
|
||
|
||
char *buf = (char*) alloca (old_length + new_length + postfix_length + 3);
|
||
|
||
/* Convert (OP->NP)!P!ALL to (OP!P->NP!P)!ALL */
|
||
if (postfix_length > 1 && postfix_pointer[postfix_length-1] == '*')
|
||
{
|
||
int chopped_length = postfix_length - 2; /* Without final "!*" */
|
||
if (old_prefix)
|
||
sprintf (buf, "%s!%.*s", IDENTIFIER_POINTER (old_prefix),
|
||
chopped_length, postfix_pointer);
|
||
else
|
||
sprintf (buf, "%.*s", chopped_length, postfix_pointer);
|
||
old_prefix = get_identifier (buf);
|
||
if (new_prefix)
|
||
sprintf (buf, "%s!%.*s", IDENTIFIER_POINTER (new_prefix),
|
||
chopped_length, postfix_pointer);
|
||
else
|
||
sprintf (buf, "%.*s", chopped_length, postfix_pointer);
|
||
new_prefix = get_identifier (buf);
|
||
postfix = ALL_POSTFIX;
|
||
}
|
||
|
||
DECL_OLD_PREFIX (decl) = old_prefix;
|
||
DECL_NEW_PREFIX (decl) = new_prefix;
|
||
DECL_POSTFIX (decl) = postfix;
|
||
|
||
if (DECL_POSTFIX_ALL (decl))
|
||
DECL_NAME (decl) = NULL_TREE;
|
||
else if (new_prefix == NULL_TREE)
|
||
DECL_NAME (decl) = postfix;
|
||
else
|
||
DECL_NAME (decl) = get_identifier3 (IDENTIFIER_POINTER (new_prefix),
|
||
"!", IDENTIFIER_POINTER (postfix));
|
||
|
||
return decl;
|
||
}
|
||
|
||
/* Return the "old name string" of an ALIAS_DECL. */
|
||
|
||
tree
|
||
decl_old_name (decl)
|
||
tree decl;
|
||
{
|
||
|
||
if (DECL_OLD_PREFIX (decl) == NULL_TREE)
|
||
return DECL_POSTFIX (decl);
|
||
return get_identifier3 (IDENTIFIER_POINTER (DECL_OLD_PREFIX (decl)),
|
||
"!", IDENTIFIER_POINTER (DECL_POSTFIX (decl)));
|
||
}
|
||
|
||
/* See if OLD_NAME (an identifier) matches the OLD_PREFIX!POSTFIX
|
||
of ALIAS. If so, return the corresponding NEW_NEW!POSTFIX. */
|
||
|
||
tree
|
||
decl_check_rename (alias, old_name)
|
||
tree alias, old_name;
|
||
{
|
||
const char *old_pointer = IDENTIFIER_POINTER (old_name);
|
||
int old_len = IDENTIFIER_LENGTH (old_name);
|
||
if (DECL_OLD_PREFIX (alias))
|
||
{
|
||
int old_prefix_len = IDENTIFIER_LENGTH (DECL_OLD_PREFIX (alias));
|
||
if (old_prefix_len >= old_len
|
||
|| old_pointer[old_prefix_len] != '!'
|
||
|| strncmp (old_pointer, IDENTIFIER_POINTER (DECL_OLD_PREFIX (alias)), old_prefix_len) != 0)
|
||
return NULL_TREE;
|
||
|
||
/* Skip the old prefix. */
|
||
old_pointer += old_prefix_len + 1; /* Also skip the '!', */
|
||
}
|
||
if (DECL_POSTFIX_ALL (alias)
|
||
|| strcmp (IDENTIFIER_POINTER (DECL_POSTFIX (alias)), old_pointer) == 0)
|
||
{
|
||
if (DECL_NEW_PREFIX (alias))
|
||
return get_identifier3 (IDENTIFIER_POINTER (DECL_NEW_PREFIX (alias)),
|
||
"!", old_pointer);
|
||
else if (old_pointer == IDENTIFIER_POINTER (old_name))
|
||
return old_name;
|
||
else
|
||
return get_identifier (old_pointer);
|
||
}
|
||
else
|
||
return NULL_TREE;
|
||
}
|
||
|
||
/* 'EXIT foo' is treated like 'GOTO EXIT!foo'.
|
||
This function converts LABEL into a labal name for EXIT. */
|
||
|
||
tree
|
||
munge_exit_label (label)
|
||
tree label;
|
||
{
|
||
return get_identifier3 ("EXIT", "!", IDENTIFIER_POINTER (label));
|
||
}
|
||
|
||
/* Make SAVE_EXPRs as needed, but don't turn a location into a non-location. */
|
||
|
||
tree
|
||
save_if_needed (exp)
|
||
tree exp;
|
||
{
|
||
return CH_REFERABLE (exp) ? stabilize_reference (exp) : save_expr (exp);
|
||
}
|
||
|
||
/* Return the number of elements in T, which must be a discrete type. */
|
||
tree
|
||
discrete_count (t)
|
||
tree t;
|
||
{
|
||
tree hi = convert (sizetype, TYPE_MAX_VALUE (t));
|
||
|
||
if (TYPE_MIN_VALUE (t))
|
||
hi = size_binop (MINUS_EXPR, hi, convert (sizetype, TYPE_MIN_VALUE (t)));
|
||
|
||
return size_binop (PLUS_EXPR, hi, integer_one_node);
|
||
}
|