/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "ggc.h"
#include "hashtab.h"
#include "output.h"
-#include "defaults.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
"lang_type kinds"
};
-/* Hash table for uniquizing IDENTIFIER_NODEs by name. */
-
-#define MAX_HASH_TABLE 1009
-static tree hash_table[MAX_HASH_TABLE]; /* id hash buckets */
-
-/* 0 while creating built-in identifiers. */
-static int do_identifier_warnings;
-
/* Unique id for next decl created. */
static int next_decl_uid;
/* Unique id for next type created. */
static void print_type_hash_statistics PARAMS((void));
static int mark_hash_entry PARAMS((void **, void *));
static void finish_vector_type PARAMS((tree));
+static int mark_tree_hashtable_entry PARAMS((void **, void *));
/* If non-null, these are language-specific helper functions for
unsave_expr_now. If present, LANG_UNSAVE is called before its
void (*lang_unsave) PARAMS ((tree *));
void (*lang_unsave_expr_now) PARAMS ((tree));
-/* The string used as a placeholder instead of a source file name for
- built-in tree nodes. The variable, which is dynamically allocated,
- should be used; the macro is only used to initialize it. */
-
-static char *built_in_filename;
-#define BUILT_IN_FILENAME ("<built-in>")
+/* If non-null, these are language-specific helper functions for
+ unsafe_for_reeval. Return negative to not handle some tree. */
+int (*lang_unsafe_for_reeval) PARAMS ((tree));
\f
tree global_trees[TI_MAX];
tree integer_types[itk_none];
{
gcc_obstack_init (&permanent_obstack);
- /* Init the hash table of identifiers. */
- bzero ((char *) hash_table, sizeof hash_table);
- ggc_add_tree_root (hash_table, sizeof hash_table / sizeof (tree));
-
/* Initialize the hash table of types. */
type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
long size;
{
char *rval = (char *) obstack_alloc (&permanent_obstack, nelem * size);
- bzero (rval, nelem * size);
+ memset (rval, 0, nelem * size);
return rval;
}
-\f
-/* Init the tables indexed by tree code.
- Note that languages can add to these tables to define their own codes. */
-
-void
-init_tree_codes ()
-{
- built_in_filename
- = ggc_alloc_string (BUILT_IN_FILENAME, sizeof (BUILT_IN_FILENAME));
- ggc_add_string_root (&built_in_filename, 1);
-}
-
/* Compute the number of bytes occupied by 'node'. This routine only
looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH. */
size_t
DECL_IN_SYSTEM_HEADER (t) = in_system_header;
DECL_SOURCE_LINE (t) = lineno;
DECL_SOURCE_FILE (t) =
- (input_filename) ? input_filename : built_in_filename;
+ (input_filename) ? input_filename : "<built-in>";
DECL_UID (t) = next_decl_uid++;
/* Note that we have not yet computed the alias set for this
declaration. */
case 't':
TYPE_UID (t) = next_type_uid++;
- TYPE_ALIGN (t) = 1;
+ TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
TYPE_USER_ALIGN (t) = 0;
TYPE_MAIN_VARIANT (t) = t;
TYPE_ATTRIBUTES (t) = NULL_TREE;
}
\f
/* Return a new node with the same contents as NODE except that its
- TREE_CHAIN is zero and it has a fresh uid. Unlike make_node, this
- function always performs the allocation on the CURRENT_OBSTACK;
- it's up to the caller to pick the right obstack before calling this
- function. */
+ TREE_CHAIN is zero and it has a fresh uid. */
tree
copy_node (node)
}
return head;
}
-\f
-#define HASHBITS 30
-
-/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
- If an identifier with that name has previously been referred to,
- the same node is returned this time. */
-
-tree
-get_identifier (text)
- register const char *text;
-{
- register int hi;
- register int i;
- register tree idp;
- register int len, hash_len;
-
- /* Compute length of text in len. */
- len = strlen (text);
-
- /* Decide how much of that length to hash on */
- hash_len = len;
- if (warn_id_clash && len > id_clash_len)
- hash_len = id_clash_len;
-
- /* Compute hash code */
- hi = hash_len * 613 + (unsigned) text[0];
- for (i = 1; i < hash_len; i += 2)
- hi = ((hi * 613) + (unsigned) (text[i]));
-
- hi &= (1 << HASHBITS) - 1;
- hi %= MAX_HASH_TABLE;
-
- /* Search table for identifier. */
- for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
- if (IDENTIFIER_LENGTH (idp) == len
- && IDENTIFIER_POINTER (idp)[0] == text[0]
- && !bcmp (IDENTIFIER_POINTER (idp), text, len))
- /* Return if found. */
- return idp;
-
- /* Not found; optionally warn about a similar identifier. */
- if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
- for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
- if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
- {
- warning ("`%s' and `%s' identical in first %d characters",
- IDENTIFIER_POINTER (idp), text, id_clash_len);
- break;
- }
-
- if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
- abort (); /* set_identifier_size hasn't been called. */
-
- /* Not found, create one, add to chain */
- idp = make_node (IDENTIFIER_NODE);
- IDENTIFIER_LENGTH (idp) = len;
-#ifdef GATHER_STATISTICS
- id_string_size += len;
-#endif
-
- IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
-
- TREE_CHAIN (idp) = hash_table[hi];
- hash_table[hi] = idp;
- return idp; /* <-- return if created */
-}
-
-/* If an identifier with the name TEXT (a null-terminated string) has
- previously been referred to, return that node; otherwise return
- NULL_TREE. */
-
-tree
-maybe_get_identifier (text)
- register const char *text;
-{
- register int hi;
- register int i;
- register tree idp;
- register int len, hash_len;
- /* Compute length of text in len. */
- len = strlen (text);
-
- /* Decide how much of that length to hash on */
- hash_len = len;
- if (warn_id_clash && len > id_clash_len)
- hash_len = id_clash_len;
-
- /* Compute hash code */
- hi = hash_len * 613 + (unsigned) text[0];
- for (i = 1; i < hash_len; i += 2)
- hi = ((hi * 613) + (unsigned) (text[i]));
-
- hi &= (1 << HASHBITS) - 1;
- hi %= MAX_HASH_TABLE;
-
- /* Search table for identifier. */
- for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
- if (IDENTIFIER_LENGTH (idp) == len
- && IDENTIFIER_POINTER (idp)[0] == text[0]
- && !bcmp (IDENTIFIER_POINTER (idp), text, len))
- return idp; /* <-- return if found */
-
- return NULL_TREE;
-}
-
-/* Enable warnings on similar identifiers (if requested).
- Done after the built-in identifiers are created. */
-
-void
-start_identifier_warnings ()
-{
- do_identifier_warnings = 1;
-}
-
-/* Record the size of an identifier node for the language in use.
- SIZE is the total size in bytes.
- This is called by the language-specific files. This must be
- called before allocating any identifiers. */
-
-void
-set_identifier_size (size)
- int size;
-{
- tree_code_length[(int) IDENTIFIER_NODE]
- = (size - sizeof (struct tree_common)) / sizeof (tree);
-}
\f
/* Return a newly constructed INTEGER_CST node whose constant value
is specified by the two ints LOW and HI.
#ifdef REAL_ARITHMETIC
/* Clear all bits of the real value type so that we can later do
bitwise comparisons to see if two values are the same. */
- bzero ((char *) &d, sizeof d);
+ memset ((char *) &d, 0, sizeof d);
if (! TREE_UNSIGNED (TREE_TYPE (i)))
REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
break;
default:
- /* ??? Add a lang hook if it becomes necessary. */
+ if (lang_unsafe_for_reeval != 0)
+ {
+ tmp = (*lang_unsafe_for_reeval) (expr);
+ if (tmp >= 0)
+ return tmp;
+ }
break;
}
register int length;
register int i;
int fro;
+ int constant;
VA_START (p, tt);
to do this. */
fro = first_rtl_op (code);
+ /* Expressions without side effects may be constant if their
+ arguments are as well. */
+ constant = (TREE_CODE_CLASS (code) == '<'
+ || TREE_CODE_CLASS (code) == '1'
+ || TREE_CODE_CLASS (code) == '2'
+ || TREE_CODE_CLASS (code) == 'c');
+
if (length == 2)
{
/* This is equivalent to the loop below, but faster. */
TREE_SIDE_EFFECTS (t) = 1;
if (!TREE_READONLY (arg0))
TREE_READONLY (t) = 0;
+ if (!TREE_CONSTANT (arg0))
+ constant = 0;
}
if (arg1 && fro > 1)
TREE_SIDE_EFFECTS (t) = 1;
if (!TREE_READONLY (arg1))
TREE_READONLY (t) = 0;
+ if (!TREE_CONSTANT (arg1))
+ constant = 0;
}
}
else if (length == 1)
{
if (TREE_SIDE_EFFECTS (operand))
TREE_SIDE_EFFECTS (t) = 1;
+ if (!TREE_CONSTANT (operand))
+ constant = 0;
}
}
}
va_end (p);
+
+ TREE_CONSTANT (t) = constant;
return t;
}
kind = e_kind;
#endif
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_CLASS (code) == '2'
+ || TREE_CODE_CLASS (code) == '<'
+ || TREE_CODE_LENGTH (code) != 1)
+ abort ();
+#endif /* ENABLE_CHECKING */
+
length = sizeof (struct tree_exp);
t = ggc_alloc_tree (length);
break;
default:
+ if (TREE_CODE_CLASS (code) == '1' && node && TREE_CONSTANT (node))
+ TREE_CONSTANT (t) = 1;
break;
}
return t;
}
-/* Similar to `build_nt', except we build
- on the temp_decl_obstack, regardless. */
-
-tree
-build_parse_node VPARAMS ((enum tree_code code, ...))
-{
-#ifndef ANSI_PROTOTYPES
- enum tree_code code;
-#endif
- va_list p;
- register tree t;
- register int length;
- register int i;
-
- VA_START (p, code);
-
-#ifndef ANSI_PROTOTYPES
- code = va_arg (p, enum tree_code);
-#endif
-
- t = make_node (code);
- length = TREE_CODE_LENGTH (code);
-
- for (i = 0; i < length; i++)
- TREE_OPERAND (t, i) = va_arg (p, tree);
-
- va_end (p);
- return t;
-}
-
#if 0
/* Commented out because this wants to be done very
differently. See cp-lex.c. */
htab_traverse (t, mark_hash_entry, 0);
}
+/* Mark the hashtable slot pointed to by ENTRY (which is really a
+ `tree**') for GC. */
+
+static int
+mark_tree_hashtable_entry (entry, data)
+ void **entry;
+ void *data ATTRIBUTE_UNUSED;
+{
+ ggc_mark_tree ((tree) *entry);
+ return 1;
+}
+
+/* Mark ARG (which is really a htab_t whose slots are trees) for
+ GC. */
+
+void
+mark_tree_hashtable (arg)
+ void *arg;
+{
+ htab_t t = *(htab_t *) arg;
+ htab_traverse (t, mark_tree_hashtable_entry, 0);
+}
+
static void
print_type_hash_statistics ()
{
case STRING_CST:
return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
- && ! bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
TREE_STRING_LENGTH (t1)));
case CONSTRUCTOR:
return t;
}
+/* Build a type that is compatible with t but has no cv quals anywhere
+ in its type, thus
+
+ const char *const *const * -> char ***. */
+
+tree
+build_type_no_quals (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case POINTER_TYPE:
+ return build_pointer_type (build_type_no_quals (TREE_TYPE (t)));
+ case REFERENCE_TYPE:
+ return build_reference_type (build_type_no_quals (TREE_TYPE (t)));
+ default:
+ return TYPE_MAIN_VARIANT (t);
+ }
+}
+
/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
MAXVAL should be the maximum value in the domain
(one less than the length of the array).
tree maxval;
{
register tree itype = make_node (INTEGER_TYPE);
- int no_hash = 0;
TREE_TYPE (itype) = sizetype;
TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
-
- /* If sizetype is unsigned and the upper bound is negative, use a
- lower bound of one and an upper bound of zero. */
- if (TREE_UNSIGNED (sizetype) && TREE_CODE (maxval) == INTEGER_CST
- && tree_int_cst_sgn (maxval) < 0)
- {
- TYPE_MIN_VALUE (itype) = size_one_node;
- TYPE_MAX_VALUE (itype) = size_zero_node;
- no_hash = 1;
- }
- else
- {
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
- }
-
+ TYPE_MIN_VALUE (itype) = size_zero_node;
+ TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
TYPE_MODE (itype) = TYPE_MODE (sizetype);
TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (sizetype);
- if (!no_hash && host_integerp (maxval, 1))
+ if (host_integerp (maxval, 1))
return type_hash_canon (tree_low_cst (maxval, 1), itype);
else
return itype;
/* Since type_for_size always gives an integer type. */
&& TREE_CODE (type) != REAL_TYPE
/* Don't crash if field not laid out yet. */
- && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
+ && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
+ && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
{
unsigned int innerprec
- = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+ = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
type = type_for_size (innerprec, TREE_UNSIGNED (TREE_OPERAND (op, 1)));
TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
}
}
+
return win;
}
\f
int_fits_type_p (c, type)
tree c, type;
{
- if (TREE_UNSIGNED (type))
- return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
- && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c))
- && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
- && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)))
- /* Negative ints never fit unsigned types. */
- && ! (TREE_INT_CST_HIGH (c) < 0
- && ! TREE_UNSIGNED (TREE_TYPE (c))));
+ /* If the bounds of the type are integers, we can check ourselves.
+ Otherwise,. use force_fit_type, which checks against the precision. */
+ if (TYPE_MAX_VALUE (type) != NULL_TREE
+ && TYPE_MIN_VALUE (type) != NULL_TREE
+ && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+ && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
+ {
+ if (TREE_UNSIGNED (type))
+ return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c)
+ && ! INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))
+ /* Negative ints never fit unsigned types. */
+ && ! (TREE_INT_CST_HIGH (c) < 0
+ && ! TREE_UNSIGNED (TREE_TYPE (c))));
+ else
+ return (! INT_CST_LT (TYPE_MAX_VALUE (type), c)
+ && ! INT_CST_LT (c, TYPE_MIN_VALUE (type))
+ /* Unsigned ints with top bit set never fit signed types. */
+ && ! (TREE_INT_CST_HIGH (c) < 0
+ && TREE_UNSIGNED (TREE_TYPE (c))));
+ }
else
- return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
- && INT_CST_LT (TYPE_MAX_VALUE (type), c))
- && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
- && INT_CST_LT (c, TYPE_MIN_VALUE (type)))
- /* Unsigned ints with top bit set never fit signed types. */
- && ! (TREE_INT_CST_HIGH (c) < 0
- && TREE_UNSIGNED (TREE_TYPE (c))));
+ {
+ c = copy_node (c);
+ TREE_TYPE (c) = type;
+ return !force_fit_type (c, 0);
+ }
}
/* Given a DECL or TYPE, return the scope in which it was declared, or
int i;
tree vals;
HOST_WIDE_INT domain_min
- = TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (init))));
+ = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (init))), 0);
tree non_const_bits = NULL_TREE;
+
for (i = 0; i < bit_size; i++)
buffer[i] = 0;
for (vals = TREE_OPERAND (init, 1);
vals != NULL_TREE; vals = TREE_CHAIN (vals))
{
- if (TREE_CODE (TREE_VALUE (vals)) != INTEGER_CST
+ if (!host_integerp (TREE_VALUE (vals), 0)
|| (TREE_PURPOSE (vals) != NULL_TREE
- && TREE_CODE (TREE_PURPOSE (vals)) != INTEGER_CST))
+ && !host_integerp (TREE_PURPOSE (vals), 0)))
non_const_bits
= tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
else if (TREE_PURPOSE (vals) != NULL_TREE)
{
/* Set a range of bits to ones. */
HOST_WIDE_INT lo_index
- = TREE_INT_CST_LOW (TREE_PURPOSE (vals)) - domain_min;
+ = tree_low_cst (TREE_PURPOSE (vals), 0) - domain_min;
HOST_WIDE_INT hi_index
- = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
+ = tree_low_cst (TREE_VALUE (vals), 0) - domain_min;
if (lo_index < 0 || lo_index >= bit_size
|| hi_index < 0 || hi_index >= bit_size)
{
/* Set a single bit to one. */
HOST_WIDE_INT index
- = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
+ = tree_low_cst (TREE_VALUE (vals), 0) - domain_min;
if (index < 0 || index >= bit_size)
{
error ("invalid initializer for bit string");
/* Define these next since types below may used them. */
integer_zero_node = build_int_2 (0, 0);
integer_one_node = build_int_2 (1, 0);
+ integer_minus_one_node = build_int_2 (-1, -1);
size_zero_node = size_int (0);
size_one_node = size_int (1);
TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
layout_type (complex_long_double_type_node);
-#ifdef BUILD_VA_LIST_TYPE
- BUILD_VA_LIST_TYPE (va_list_type_node);
-#else
- va_list_type_node = ptr_type_node;
-#endif
+ {
+ tree t;
+ BUILD_VA_LIST_TYPE (t);
+ va_list_type_node = build_type_copy (t);
+ }
V4SF_type_node = make_node (VECTOR_TYPE);
TREE_TYPE (V4SF_type_node) = float_type_node;