#include "toplev.h"
#include "ggc.h"
#include "hashtab.h"
+#include "output.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
/* Unique id for next type created. */
static int next_type_uid = 1;
-/* The language-specific function for alias analysis. If NULL, the
- language does not do any special alias analysis. */
-int (*lang_get_alias_set) PARAMS ((tree));
-
/* Here is how primitive or already-canonicalized types' hash
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
static int type_hash_eq PARAMS ((const void*, const void*));
static unsigned int type_hash_hash PARAMS ((const void*));
static void print_type_hash_statistics PARAMS((void));
+static int mark_hash_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
if (code == BIND_EXPR && obstack != &permanent_obstack)
obstack = saveable_obstack;
length = sizeof (struct tree_exp)
- + (tree_code_length[(int) code] - 1) * sizeof (char *);
+ + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *);
break;
case 'c': /* a constant */
#endif
obstack = expression_obstack;
- /* We can't use tree_code_length for INTEGER_CST, since the number of
+ /* We can't use TREE_CODE_LENGTH for INTEGER_CST, since the number of
words is machine-dependent due to varying length of HOST_WIDE_INT,
which might be wider than a pointer (e.g., long long). Similarly
for REAL_CST, since the number of words is machine-dependent due
length = sizeof (struct tree_real_cst);
else
length = sizeof (struct tree_common)
- + tree_code_length[(int) code] * sizeof (char *);
+ + TREE_CODE_LENGTH (code) * sizeof (char *);
break;
case 'x': /* something random, like an identifier. */
kind = x_kind;
#endif
length = sizeof (struct tree_common)
- + tree_code_length[(int) code] * sizeof (char *);
+ + TREE_CODE_LENGTH (code) * sizeof (char *);
/* Identifier nodes are always permanent since they are
unique in a compiler run. */
if (code == IDENTIFIER_NODE) obstack = &permanent_obstack;
case '1': /* a unary arithmetic expression */
case '2': /* a binary arithmetic expression */
length = sizeof (struct tree_exp)
- + (tree_code_length[(int) code] - 1) * sizeof (char *);
+ + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *);
break;
case 'c': /* a constant */
- /* We can't use tree_code_length for INTEGER_CST, since the number of
+ /* We can't use TREE_CODE_LENGTH for INTEGER_CST, since the number of
words is machine-dependent due to varying length of HOST_WIDE_INT,
which might be wider than a pointer (e.g., long long). Similarly
for REAL_CST, since the number of words is machine-dependent due
length = sizeof (struct tree_real_cst);
else
length = (sizeof (struct tree_common)
- + tree_code_length[(int) code] * sizeof (char *));
+ + TREE_CODE_LENGTH (code) * sizeof (char *));
break;
case 'x': /* something random, like an identifier. */
length = sizeof (struct tree_common)
- + tree_code_length[(int) code] * sizeof (char *);
+ + TREE_CODE_LENGTH (code) * sizeof (char *);
if (code == TREE_VEC)
length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
}
break;
}
- if (tree_code_length[(int) IDENTIFIER_NODE] < 0)
+ if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
abort (); /* set_identifier_size hasn't been called. */
/* Not found, create one, add to chain */
tree
build_int_2_wide (low, hi)
- HOST_WIDE_INT low, hi;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT hi;
{
register tree t = make_node (INTEGER_CST);
case FUNCTION_DECL:
/* Nested functions aren't static, since taking their address
involves a trampoline. */
- return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
- && ! DECL_NON_ADDR_CONST_P (arg);
+ return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
+ && ! DECL_NON_ADDR_CONST_P (arg);
case VAR_DECL:
return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
- && ! DECL_NON_ADDR_CONST_P (arg);
+ && ! DECL_NON_ADDR_CONST_P (arg);
case CONSTRUCTOR:
return TREE_STATIC (arg);
+ case LABEL_DECL:
case STRING_CST:
return 1;
case METHOD_CALL_EXPR:
return 3;
default:
- return tree_code_length [(int) code];
+ return TREE_CODE_LENGTH (code);
}
}
break;
case TARGET_EXPR:
+ /* Don't mess with a TARGET_EXPR that hasn't been expanded.
+ It's OK for this to happen if it was part of a subtree that
+ isn't immediately expanded, such as operand 2 of another
+ TARGET_EXPR. */
+ if (TREE_OPERAND (expr, 1))
+ break;
+
TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
TREE_OPERAND (expr, 3) = NULL_TREE;
break;
unsave_expr_1 (expr);
code = TREE_CODE (expr);
- if (code == CALL_EXPR
- && TREE_OPERAND (expr, 1)
- && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
- {
- tree exp = TREE_OPERAND (expr, 1);
- while (exp)
- {
- unsave_expr_now_r (TREE_VALUE (exp));
- exp = TREE_CHAIN (exp);
- }
- }
-
switch (TREE_CODE_CLASS (code))
{
case 'c': /* a constant */
case 't': /* a type node */
- case 'x': /* something random, like an identifier or an ERROR_MARK. */
case 'd': /* A decl node */
case 'b': /* A block node */
break;
+ case 'x': /* miscellaneous: e.g., identifier, TREE_LIST or ERROR_MARK. */
+ if (code == TREE_LIST)
+ {
+ unsave_expr_now_r (TREE_VALUE (expr));
+ unsave_expr_now_r (TREE_CHAIN (expr));
+ }
+ break;
+
case 'e': /* an expression */
case 'r': /* a reference */
case 's': /* an expression with side effects */
unsafe_for_reeval (expr)
tree expr;
{
+ int unsafeness = 0;
enum tree_code code;
- register int i, tmp, unsafeness;
+ int i, tmp;
+ tree exp;
int first_rtl;
if (expr == NULL_TREE)
code = TREE_CODE (expr);
first_rtl = first_rtl_op (code);
- unsafeness = 0;
switch (code)
{
case RTL_EXPR:
return 2;
- case CALL_EXPR:
- if (TREE_OPERAND (expr, 1)
- && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+ case TREE_LIST:
+ for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
{
- tree exp = TREE_OPERAND (expr, 1);
- while (exp)
- {
- tmp = unsafe_for_reeval (TREE_VALUE (exp));
- if (tmp > 1)
- return tmp;
- exp = TREE_CHAIN (exp);
- }
+ tmp = unsafe_for_reeval (TREE_VALUE (exp));
+ unsafeness = MAX (tmp, unsafeness);
}
- return 1;
+
+ return unsafeness;
+
+ case CALL_EXPR:
+ tmp = unsafe_for_reeval (TREE_OPERAND (expr, 1));
+ return MAX (tmp, 1);
case TARGET_EXPR:
unsafeness = 1;
for (i = first_rtl - 1; i >= 0; i--)
{
tmp = unsafe_for_reeval (TREE_OPERAND (expr, i));
- if (tmp > unsafeness)
- unsafeness = tmp;
+ unsafeness = MAX (tmp, unsafeness);
}
+
return unsafeness;
default:
break;
}
- switch (tree_code_length[(int) code])
+ switch (TREE_CODE_LENGTH (code))
{
case 1:
return contains_placeholder_p (TREE_OPERAND (exp, 0));
case '2':
case '<':
case 'e':
- switch (tree_code_length[(int) code])
+ switch (TREE_CODE_LENGTH (code))
{
case 1:
op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
#endif
t = make_node (code);
- length = tree_code_length[(int) code];
+ length = TREE_CODE_LENGTH (code);
TREE_TYPE (t) = tt;
/* Below, we automatically set TREE_SIDE_EFFECTS and TREE_RAISED for
TREE_SET_PERMANENT (t);
TREE_OPERAND (t, 0) = node;
- if (node && first_rtl_op (code) != 0)
- {
- if (TREE_SIDE_EFFECTS (node))
- TREE_SIDE_EFFECTS (t) = 1;
- }
+ if (node && first_rtl_op (code) != 0 && TREE_SIDE_EFFECTS (node))
+ TREE_SIDE_EFFECTS (t) = 1;
switch (code)
{
#endif
t = make_node (code);
- length = tree_code_length[(int) code];
+ length = TREE_CODE_LENGTH (code);
for (i = 0; i < length; i++)
TREE_OPERAND (t, i) = va_arg (p, tree);
expression_obstack = &temp_decl_obstack;
t = make_node (code);
- length = tree_code_length[(int) code];
+ length = TREE_CODE_LENGTH (code);
for (i = 0; i < length; i++)
TREE_OPERAND (t, i) = va_arg (p, tree);
h = (struct type_hash *) permalloc (sizeof (struct type_hash));
h->hash = hashcode;
h->type = type;
- loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, 1);
- *(struct type_hash**)loc = h;
+ loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
+ *(struct type_hash**) loc = h;
}
/* Given TYPE, and HASHCODE its hash code, return the canonical
{
register int prec;
HOST_WIDE_INT h;
- HOST_WIDE_INT l;
+ unsigned HOST_WIDE_INT l;
/* Note that using TYPE_PRECISION here is wrong. We care about the
actual bits, not the (arbitrary) range of the type. */
return 1;
}
+/* Return true if `t' is known to be non-negative. */
+
+int
+tree_expr_nonnegative_p (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_CST:
+ return tree_int_cst_sgn (t) >= 0;
+ case COND_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
+ default:
+ /* We don't know sign of `t', so be safe and return false. */
+ return 0;
+ }
+}
+
/* Compare two constructor-element-type constants. Return 1 if the lists
are known to be equal; otherwise return 0. */
case 'r':
case 's':
cmp = 1;
- for (i = 0; i < tree_code_length[(int) code1]; i++)
+ for (i = 0; i < TREE_CODE_LENGTH (code1); i++)
{
cmp = simple_cst_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
if (cmp <= 0)
}
/* Given a DECL or TYPE, return the scope in which it was declared, or
- NUL_TREE if there is no containing scope. */
+ NULL_TREE if there is no containing scope. */
tree
get_containing_scope (t)
if (TREE_CODE (decl) == SAVE_EXPR)
context = SAVE_EXPR_CONTEXT (decl);
+
/* C++ virtual functions use DECL_CONTEXT for the class of the vtable
where we look up the function at runtime. Such functions always take
a first argument of type 'pointer to real context'.
C++ should really be fixed to use DECL_CONTEXT for the real context,
and use something else for the "virtual context". */
else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VINDEX (decl))
- context = TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+ context
+ = TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
else
context = DECL_CONTEXT (decl);
called. */
addr = TREE_OPERAND (call, 0);
+ STRIP_NOPS (addr);
+
+ /* If this is a readonly function pointer, extract its initial value. */
+ if (DECL_P (addr) && TREE_CODE (addr) != FUNCTION_DECL
+ && TREE_READONLY (addr) && ! TREE_THIS_VOLATILE (addr)
+ && DECL_INITIAL (addr))
+ addr = DECL_INITIAL (addr);
+
/* If the address is just `&f' for some function `f', then we know
that `f' is being called. */
if (TREE_CODE (addr) == ADDR_EXPR
#endif /* NO_DOT_IN_LABEL */
#endif /* NO_DOLLAR_IN_LABEL */
-extern char *first_global_object_name;
-extern char *weak_global_object_name;
-
/* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
clashes in cases where we can't reliably choose a unique name.
const char *type;
{
char *buf;
- register char *p;
+ const char *p;
+ char *q;
if (first_global_object_name)
p = first_global_object_name;
if (! file)
file = input_filename;
- p = (char *) alloca (7 + strlen (name) + strlen (file));
+ q = (char *) alloca (7 + strlen (name) + strlen (file));
- sprintf (p, "%s%s", name, file);
- append_random_chars (p);
+ sprintf (q, "%s%s", name, file);
+ append_random_chars (q);
+ p = q;
}
buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
/* Don't need to pull weird characters out of global names. */
if (p != first_global_object_name)
{
- for (p = buf+11; *p; p++)
- if (! ( ISDIGIT(*p)
-#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */
-#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */
- || *p == '.'
-#endif
-#endif
+ for (q = buf+11; *q; q++)
+ if (! ( ISDIGIT(*q)
#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
- || *p == '$'
+ || *q == '$'
#endif
#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
- || *p == '.'
+ || *q == '.'
#endif
- || ISUPPER(*p)
- || ISLOWER(*p)))
- *p = '_';
+ || ISUPPER(*q)
+ || ISLOWER(*q)))
+ *q = '_';
}
return get_identifier (buf);
#endif /* ENABLE_TREE_CHECKING */
-/* Return the alias set for T, which may be either a type or an
- expression. */
-
-int
-get_alias_set (t)
- tree t;
-{
- if (! flag_strict_aliasing || lang_get_alias_set == 0)
- /* If we're not doing any lanaguage-specific alias analysis, just
- assume everything aliases everything else. */
- return 0;
- else
- return (*lang_get_alias_set) (t);
-}
-
-/* Return a brand-new alias set. */
-
-int
-new_alias_set ()
-{
- static int last_alias_set;
-
- if (flag_strict_aliasing)
- return ++last_alias_set;
- else
- return 0;
-}
\f
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+#endif
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+#endif
}
/* Call this function after calling build_common_tree_nodes and set_sizetype.