Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-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.
+GCC 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.
+GCC 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. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This file contains the low level primitives for operating on tree nodes,
including allocation, list operations, interning of identifiers,
#include "ggc.h"
#include "hashtab.h"
#include "output.h"
+#include "target.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
e_kind,
c_kind,
id_kind,
- op_id_kind,
perm_list_kind,
temp_list_kind,
vec_kind,
"exprs",
"constants",
"identifiers",
- "op_identifiers",
"perm_tree_lists",
"temp_tree_lists",
"vecs",
/* Unique id for next type created. */
static int next_type_uid = 1;
-/* Here is how primitive or already-canonicalized types' hash
- codes are made. */
-#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
-
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
static void build_real_from_int_cst_1 PARAMS ((PTR));
static void set_type_quals PARAMS ((tree, int));
static void append_random_chars PARAMS ((char *));
-static void mark_type_hash PARAMS ((void *));
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 *));
static void finish_vector_type PARAMS((tree));
+static int type_hash_marked_p PARAMS ((const void *));
+static void type_hash_mark PARAMS ((const void *));
static int mark_tree_hashtable_entry PARAMS((void **, void *));
/* If non-null, these are language-specific helper functions for
/* Initialize the hash table of types. */
type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
- ggc_add_root (&type_hash_table, 1, sizeof type_hash_table, mark_type_hash);
+ ggc_add_deletable_htab (type_hash_table, type_hash_marked_p,
+ type_hash_mark);
ggc_add_tree_root (global_trees, TI_MAX);
ggc_add_tree_root (integer_types, itk_none);
make_node (code)
enum tree_code code;
{
- register tree t;
- register int type = TREE_CODE_CLASS (code);
- register size_t length;
+ tree t;
+ int type = TREE_CODE_CLASS (code);
+ size_t length;
#ifdef GATHER_STATISTICS
- register tree_node_kind kind;
+ tree_node_kind kind;
#endif
struct tree_common ttmp;
case 'x': /* something random, like an identifier. */
if (code == IDENTIFIER_NODE)
kind = id_kind;
- else if (code == OP_IDENTIFIER)
- kind = op_id_kind;
else if (code == TREE_VEC)
kind = vec_kind;
else
DECL_SOURCE_FILE (t) =
(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. */
+
+ /* We have not yet computed the alias set for this declaration. */
DECL_POINTER_ALIAS_SET (t) = -1;
break;
TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
TYPE_USER_ALIGN (t) = 0;
TYPE_MAIN_VARIANT (t) = t;
+
+ /* Default to no attributes for type, but let target change that. */
TYPE_ATTRIBUTES (t) = NULL_TREE;
-#ifdef SET_DEFAULT_TYPE_ATTRIBUTES
- SET_DEFAULT_TYPE_ATTRIBUTES (t);
-#endif
- /* Note that we have not yet computed the alias set for this
- type. */
+ (*targetm.set_default_type_attributes) (t);
+
+ /* We have not yet computed the alias set for this type. */
TYPE_ALIAS_SET (t) = -1;
break;
copy_node (node)
tree node;
{
- register tree t;
- register enum tree_code code = TREE_CODE (node);
- register size_t length;
+ tree t;
+ enum tree_code code = TREE_CODE (node);
+ size_t length;
length = tree_size (node);
t = ggc_alloc_tree (length);
tree list;
{
tree head;
- register tree prev, next;
+ tree prev, next;
if (list == 0)
return 0;
unsigned HOST_WIDE_INT low;
HOST_WIDE_INT hi;
{
- register tree t = make_node (INTEGER_CST);
+ tree t = make_node (INTEGER_CST);
TREE_INT_CST_LOW (t) = low;
TREE_INT_CST_HIGH (t) = hi;
int len;
const char *str;
{
- register tree s = make_node (STRING_CST);
+ tree s = make_node (STRING_CST);
TREE_STRING_LENGTH (s) = len;
TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
tree type;
tree real, imag;
{
- register tree t = make_node (COMPLEX_CST);
+ tree t = make_node (COMPLEX_CST);
TREE_REALPART (t) = real;
TREE_IMAGPART (t) = imag;
make_tree_vec (len)
int len;
{
- register tree t;
- register int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
+ tree t;
+ int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)vec_kind]++;
integer_all_onesp (expr)
tree expr;
{
- register int prec;
- register int uns;
+ int prec;
+ int uns;
STRIP_NOPS (expr);
list_length (t)
tree t;
{
- register tree tail;
- register int len = 0;
+ tree tail;
+ int len = 0;
for (tail = t; tail; tail = TREE_CHAIN (tail))
len++;
if (op1)
{
- register tree t1;
+ tree t1;
#ifdef ENABLE_TREE_CHECKING
- register tree t2;
+ tree t2;
#endif
for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
tree
tree_last (chain)
- register tree chain;
+ tree chain;
{
- register tree next;
+ tree next;
if (chain)
while ((next = TREE_CHAIN (chain)))
chain = next;
nreverse (t)
tree t;
{
- register tree prev = 0, decl, next;
+ tree prev = 0, decl, next;
for (decl = t; decl; decl = next)
{
next = TREE_CHAIN (decl);
build_tree_list (parm, value)
tree parm, value;
{
- register tree t = make_node (TREE_LIST);
+ tree t = make_node (TREE_LIST);
TREE_PURPOSE (t) = parm;
TREE_VALUE (t) = value;
return t;
tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
- register tree node;
+ tree node;
node = ggc_alloc_tree (sizeof (struct tree_list));
#endif
case ARRAY_REF:
+ case ARRAY_RANGE_REF:
if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
return staticp (TREE_OPERAND (arg, 0));
save_expr (expr)
tree expr;
{
- register tree t = fold (expr);
+ tree t = fold (expr);
/* We don't care about whether this can be used as an lvalue in this
context. */
case RTL_EXPR:
return 0;
case WITH_CLEANUP_EXPR:
- /* Should be defined to be 2. */
- return 1;
+ return 2;
case METHOD_CALL_EXPR:
return 3;
default:
contains_placeholder_p (exp)
tree exp;
{
- register enum tree_code code;
+ enum tree_code code;
int result;
if (!exp)
stabilize_reference (ref)
tree ref;
{
- register tree result;
- register enum tree_code code = TREE_CODE (ref);
+ tree result;
+ enum tree_code code = TREE_CODE (ref);
switch (code)
{
stabilize_reference_1 (TREE_OPERAND (ref, 1)));
break;
+ case ARRAY_RANGE_REF:
+ result = build_nt (ARRAY_RANGE_REF,
+ stabilize_reference (TREE_OPERAND (ref, 0)),
+ stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+ break;
+
case COMPOUND_EXPR:
/* We cannot wrap the first expression in a SAVE_EXPR, as then
it wouldn't be ignored. This matters when dealing with
stabilize_reference_1 (e)
tree e;
{
- register tree result;
- register enum tree_code code = TREE_CODE (e);
+ tree result;
+ enum tree_code code = TREE_CODE (e);
/* We cannot ignore const expressions because it might be a reference
to a const array but whose index contains side-effects. But we can
tree
build VPARAMS ((enum tree_code code, tree tt, ...))
{
-#ifndef ANSI_PROTOTYPES
- enum tree_code code;
- tree tt;
-#endif
- va_list p;
- register tree t;
- register int length;
- register int i;
+ tree t;
+ int length;
+ int i;
int fro;
int constant;
- VA_START (p, tt);
-
-#ifndef ANSI_PROTOTYPES
- code = va_arg (p, enum tree_code);
- tt = va_arg (p, tree);
-#endif
+ VA_OPEN (p, tt);
+ VA_FIXEDARG (p, enum tree_code, code);
+ VA_FIXEDARG (p, tree, tt);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
if (length == 2)
{
/* This is equivalent to the loop below, but faster. */
- register tree arg0 = va_arg (p, tree);
- register tree arg1 = va_arg (p, tree);
+ tree arg0 = va_arg (p, tree);
+ tree arg1 = va_arg (p, tree);
TREE_OPERAND (t, 0) = arg0;
TREE_OPERAND (t, 1) = arg1;
}
else if (length == 1)
{
- register tree arg0 = va_arg (p, tree);
+ tree arg0 = va_arg (p, tree);
/* The only one-operand cases we handle here are those with side-effects.
Others are handled with build1. So don't bother checked if the
{
for (i = 0; i < length; i++)
{
- register tree operand = va_arg (p, tree);
+ tree operand = va_arg (p, tree);
TREE_OPERAND (t, i) = operand;
if (operand && fro > i)
}
}
}
- va_end (p);
+ VA_CLOSE (p);
TREE_CONSTANT (t) = constant;
return t;
tree type;
tree node;
{
- register int length;
+ int length;
#ifdef GATHER_STATISTICS
- register tree_node_kind kind;
+ tree_node_kind kind;
#endif
- register tree t;
+ tree t;
#ifdef GATHER_STATISTICS
if (TREE_CODE_CLASS (code) == 'r')
tree
build_nt 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);
+ tree t;
+ int length;
+ int i;
-#ifndef ANSI_PROTOTYPES
- code = va_arg (p, enum tree_code);
-#endif
+ VA_OPEN (p, code);
+ VA_FIXEDARG (p, enum tree_code, code);
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. */
-tree
-build_op_identifier (op1, op2)
- tree op1, op2;
-{
- register tree t = make_node (OP_IDENTIFIER);
- TREE_PURPOSE (t) = op1;
- TREE_VALUE (t) = op2;
+ VA_CLOSE (p);
return t;
}
-#endif
\f
/* Create a DECL_... node of code CODE, name NAME and data type TYPE.
We do NOT enter this node in any sort of symbol table.
enum tree_code code;
tree name, type;
{
- register tree t;
+ tree t;
t = make_node (code);
build_block (vars, tags, subblocks, supercontext, chain)
tree vars, tags ATTRIBUTE_UNUSED, subblocks, supercontext, chain;
{
- register tree block = make_node (BLOCK);
+ tree block = make_node (BLOCK);
BLOCK_VARS (block) = vars;
BLOCK_SUBBLOCKS (block) = subblocks;
{
static const char *last_file = 0;
static tree last_filenode = NULL_TREE;
- register tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
+ tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
EXPR_WFL_NODE (wfl) = node;
EXPR_WFL_SET_LINECOL (wfl, line, col);
return wfl;
}
\f
-/* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
+/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
tree
build_decl_attribute_variant (ddecl, attribute)
tree ddecl, attribute;
{
- DECL_MACHINE_ATTRIBUTES (ddecl) = attribute;
+ DECL_ATTRIBUTES (ddecl) = attribute;
return ddecl;
}
return ttype;
}
-/* Return a 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration DECL
- or type TYPE and 0 otherwise. Validity is determined the configuration
- macros VALID_MACHINE_DECL_ATTRIBUTE and VALID_MACHINE_TYPE_ATTRIBUTE. */
+/* Default value of targetm.comp_type_attributes that always returns 1. */
int
-valid_machine_attribute (attr_name, attr_args, decl, type)
- tree attr_name;
- tree attr_args ATTRIBUTE_UNUSED;
- tree decl ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
-{
- int validated = 0;
-#ifdef VALID_MACHINE_DECL_ATTRIBUTE
- tree decl_attr_list = decl != 0 ? DECL_MACHINE_ATTRIBUTES (decl) : 0;
-#endif
-#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
- tree type_attr_list = TYPE_ATTRIBUTES (type);
-#endif
-
- if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
- abort ();
-
-#ifdef VALID_MACHINE_DECL_ATTRIBUTE
- if (decl != 0
- && VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name,
- attr_args))
- {
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- decl_attr_list);
-
- if (attr != NULL_TREE)
- {
- /* Override existing arguments. Declarations are unique so we can
- modify this in place. */
- TREE_VALUE (attr) = attr_args;
- }
- else
- {
- decl_attr_list = tree_cons (attr_name, attr_args, decl_attr_list);
- decl = build_decl_attribute_variant (decl, decl_attr_list);
- }
-
- validated = 1;
- }
-#endif
-
-#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
- if (validated)
- /* Don't apply the attribute to both the decl and the type. */
- ;
- else if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name,
- attr_args))
- {
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- type_attr_list);
-
- if (attr != NULL_TREE)
- {
- /* Override existing arguments.
- ??? This currently works since attribute arguments are not
- included in `attribute_hash_list'. Something more complicated
- may be needed in the future. */
- TREE_VALUE (attr) = attr_args;
- }
- else
- {
- /* If this is part of a declaration, create a type variant,
- otherwise, this is part of a type definition, so add it
- to the base type. */
- type_attr_list = tree_cons (attr_name, attr_args, type_attr_list);
- if (decl != 0)
- type = build_type_attribute_variant (type, type_attr_list);
- else
- TYPE_ATTRIBUTES (type) = type_attr_list;
- }
-
- if (decl != 0)
- TREE_TYPE (decl) = type;
-
- validated = 1;
- }
+default_comp_type_attributes (type1, type2)
+ tree type1 ATTRIBUTE_UNUSED;
+ tree type2 ATTRIBUTE_UNUSED;
+{
+ return 1;
+}
- /* Handle putting a type attribute on pointer-to-function-type by putting
- the attribute on the function type. */
- else if (POINTER_TYPE_P (type)
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- && VALID_MACHINE_TYPE_ATTRIBUTE (TREE_TYPE (type), type_attr_list,
- attr_name, attr_args))
- {
- tree inner_type = TREE_TYPE (type);
- tree inner_attr_list = TYPE_ATTRIBUTES (inner_type);
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- type_attr_list);
+/* Default version of targetm.set_default_type_attributes that always does
+ nothing. */
- if (attr != NULL_TREE)
- TREE_VALUE (attr) = attr_args;
- else
- {
- inner_attr_list = tree_cons (attr_name, attr_args, inner_attr_list);
- inner_type = build_type_attribute_variant (inner_type,
- inner_attr_list);
- }
+void
+default_set_default_type_attributes (type)
+ tree type ATTRIBUTE_UNUSED;
+{
+}
- if (decl != 0)
- TREE_TYPE (decl) = build_pointer_type (inner_type);
- else
- {
- /* Clear TYPE_POINTER_TO for the old inner type, since
- `type' won't be pointing to it anymore. */
- TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
- TREE_TYPE (type) = inner_type;
- }
+/* Default version of targetm.insert_attributes that always does nothing. */
+void
+default_insert_attributes (decl, attr_ptr)
+ tree decl ATTRIBUTE_UNUSED;
+ tree *attr_ptr ATTRIBUTE_UNUSED;
+{
+}
- validated = 1;
- }
-#endif
+/* Default value of targetm.attribute_table that is empty. */
+const struct attribute_spec default_target_attribute_table[] =
+{
+ { NULL, 0, 0, false, false, false, NULL }
+};
- return validated;
+/* Default value of targetm.function_attribute_inlinable_p that always
+ returns false. */
+bool
+default_function_attribute_inlinable_p (fndecl)
+ tree fndecl ATTRIBUTE_UNUSED;
+{
+ /* By default, functions with machine attributes cannot be inlined. */
+ return false;
}
/* Return non-zero if IDENT is a valid name for attribute ATTR,
/* Given an attribute name and a list of attributes, return a pointer to the
attribute's list element if the attribute is part of the list, or NULL_TREE
- if not found. */
+ if not found. If the attribute appears more than once, this only
+ returns the first occurance; the TREE_CHAIN of the return value should
+ be passed back in if further occurances are wanted. */
tree
lookup_attribute (attr_name, list)
tree
merge_attributes (a1, a2)
- register tree a1, a2;
+ tree a1, a2;
{
tree attributes;
else
{
/* Pick the longest list, and hang on the other list. */
- /* ??? For the moment we punt on the issue of attrs with args. */
if (list_length (a1) < list_length (a2))
attributes = a2, a2 = a1;
for (; a2 != 0; a2 = TREE_CHAIN (a2))
- if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
- attributes) == NULL_TREE)
- {
- a1 = copy_node (a2);
- TREE_CHAIN (a1) = attributes;
- attributes = a1;
- }
+ {
+ tree a;
+ for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+ attributes);
+ a != NULL_TREE;
+ a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+ TREE_CHAIN (a)))
+ {
+ if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
+ break;
+ }
+ if (a == NULL_TREE)
+ {
+ a1 = copy_node (a2);
+ TREE_CHAIN (a1) = attributes;
+ attributes = a1;
+ }
+ }
}
}
return attributes;
}
/* Given types T1 and T2, merge their attributes and return
- the result. */
+ the result. */
tree
-merge_machine_type_attributes (t1, t2)
+merge_type_attributes (t1, t2)
tree t1, t2;
{
-#ifdef MERGE_MACHINE_TYPE_ATTRIBUTES
- return MERGE_MACHINE_TYPE_ATTRIBUTES (t1, t2);
-#else
return merge_attributes (TYPE_ATTRIBUTES (t1),
TYPE_ATTRIBUTES (t2));
-#endif
}
/* Given decls OLDDECL and NEWDECL, merge their attributes and return
the result. */
tree
-merge_machine_decl_attributes (olddecl, newdecl)
+merge_decl_attributes (olddecl, newdecl)
tree olddecl, newdecl;
{
-#ifdef MERGE_MACHINE_DECL_ATTRIBUTES
- return MERGE_MACHINE_DECL_ATTRIBUTES (olddecl, newdecl);
-#else
- return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
- DECL_MACHINE_ATTRIBUTES (newdecl));
-#endif
+ return merge_attributes (DECL_ATTRIBUTES (olddecl),
+ DECL_ATTRIBUTES (newdecl));
+}
+
+#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+
+/* Specialization of merge_decl_attributes for various Windows targets.
+
+ This handles the following situation:
+
+ __declspec (dllimport) int foo;
+ int foo;
+
+ The second instance of `foo' nullifies the dllimport. */
+
+tree
+merge_dllimport_decl_attributes (old, new)
+ tree old;
+ tree new;
+{
+ tree a;
+ int delete_dllimport_p;
+
+ old = DECL_ATTRIBUTES (old);
+ new = DECL_ATTRIBUTES (new);
+
+ /* What we need to do here is remove from `old' dllimport if it doesn't
+ appear in `new'. dllimport behaves like extern: if a declaration is
+ marked dllimport and a definition appears later, then the object
+ is not dllimport'd. */
+ if (lookup_attribute ("dllimport", old) != NULL_TREE
+ && lookup_attribute ("dllimport", new) == NULL_TREE)
+ delete_dllimport_p = 1;
+ else
+ delete_dllimport_p = 0;
+
+ a = merge_attributes (old, new);
+
+ if (delete_dllimport_p)
+ {
+ tree prev,t;
+
+ /* Scan the list for dllimport and delete it. */
+ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
+ {
+ if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
+ {
+ if (prev == NULL_TREE)
+ a = TREE_CHAIN (a);
+ else
+ TREE_CHAIN (prev) = TREE_CHAIN (t);
+ break;
+ }
+ }
+ }
+
+ return a;
}
+
+#endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */
\f
/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
of the various TYPE_QUAL values. */
build_type_copy (type)
tree type;
{
- register tree t, m = TYPE_MAIN_VARIANT (type);
+ tree t, m = TYPE_MAIN_VARIANT (type);
t = copy_node (type);
tree list;
{
unsigned int hashcode;
- register tree tail;
+ tree tail;
for (hashcode = 0, tail = list; tail; tail = TREE_CHAIN (tail))
hashcode += TYPE_HASH (TREE_VALUE (tail));
struct type_hash *h;
void **loc;
- h = (struct type_hash *) permalloc (sizeof (struct type_hash));
+ h = (struct type_hash *) ggc_alloc (sizeof (struct type_hash));
h->hash = hashcode;
h->type = type;
loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
if (debug_no_type_hash)
return type;
+ /* See if the type is in the hash table already. If so, return it.
+ Otherwise, add the type. */
t1 = type_hash_lookup (hashcode, type);
if (t1 != 0)
{
#endif
return t1;
}
-
- /* If this is a permanent type, record it for later reuse. */
- type_hash_add (hashcode, type);
-
- return type;
+ else
+ {
+ type_hash_add (hashcode, type);
+ return type;
+ }
}
-/* Callback function for htab_traverse. */
+/* See if the data pointed to by the type hash table is marked. We consider
+ it marked if the type is marked or if a debug type number or symbol
+ table entry has been made for the type. This reduces the amount of
+ debugging output and eliminates that dependency of the debug output on
+ the number of garbage collections. */
static int
-mark_hash_entry (entry, param)
- void **entry;
- void *param ATTRIBUTE_UNUSED;
+type_hash_marked_p (p)
+ const void *p;
{
- struct type_hash *p = *(struct type_hash **) entry;
-
- ggc_mark_tree (p->type);
+ tree type = ((struct type_hash *) p)->type;
- /* Continue scan. */
- return 1;
+ return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type);
}
-/* Mark ARG (which is really a htab_t *) for GC. */
+/* Mark the entry in the type hash table the type it points to is marked.
+ Also mark the type in case we are considering this entry "marked" by
+ virtue of TYPE_SYMTAB_POINTER being set. */
static void
-mark_type_hash (arg)
- void *arg;
+type_hash_mark (p)
+ const void *p;
{
- htab_t t = *(htab_t *) arg;
-
- htab_traverse (t, mark_hash_entry, 0);
+ ggc_mark (p);
+ ggc_mark_tree (((struct type_hash *) p)->type);
}
/* Mark the hashtable slot pointed to by ENTRY (which is really a
tree list;
{
unsigned int hashcode;
- register tree tail;
+ tree tail;
for (hashcode = 0, tail = list; tail; tail = TREE_CHAIN (tail))
/* ??? Do we want to add in TREE_VALUE too? */
attribute_list_contained (l1, l2)
tree l1, l2;
{
- register tree t1, t2;
+ tree t1, t2;
/* First check the obvious, maybe the lists are identical. */
if (l1 == l2)
for (; t2 != 0; t2 = TREE_CHAIN (t2))
{
- tree attr
- = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
+ tree attr;
+ for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
+ attr != NULL_TREE;
+ attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+ TREE_CHAIN (attr)))
+ {
+ if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
+ break;
+ }
if (attr == 0)
return 0;
type_list_equal (l1, l2)
tree l1, l2;
{
- register tree t1, t2;
+ tree t1, t2;
for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if (TREE_VALUE (t1) != TREE_VALUE (t2)
return t1 == t2;
}
+/* Returns the number of arguments to the FUNCTION_TYPE or METHOD_TYPE
+ given by TYPE. If the argument list accepts variable arguments,
+ then this function counts only the ordinary arguments. */
+
+int
+type_num_arguments (type)
+ tree type;
+{
+ int i = 0;
+ tree t;
+
+ for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+ /* If the function does not take a variable number of arguments,
+ the last element in the list will have type `void'. */
+ if (VOID_TYPE_P (TREE_VALUE (t)))
+ break;
+ else
+ ++i;
+
+ return i;
+}
+
/* Nonzero if integer constants T1 and T2
represent the same constant value. */
tree_int_cst_msb (t)
tree t;
{
- register int prec;
+ int prec;
HOST_WIDE_INT h;
unsigned HOST_WIDE_INT l;
simple_cst_equal (t1, t2)
tree t1, t2;
{
- register enum tree_code code1, code2;
+ enum tree_code code1, code2;
int cmp;
int i;
if (cmp <= 0)
return cmp;
- return simple_cst_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
+ return simple_cst_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
case COMPONENT_REF:
if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
build_pointer_type (to_type)
tree to_type;
{
- register tree t = TYPE_POINTER_TO (to_type);
+ tree t = TYPE_POINTER_TO (to_type);
/* First, if we already have a type for pointers to TO_TYPE, use it. */
build_reference_type (to_type)
tree to_type;
{
- register tree t = TYPE_REFERENCE_TO (to_type);
+ tree t = TYPE_REFERENCE_TO (to_type);
/* First, if we already have a type for pointers to TO_TYPE, use it. */
build_index_type (maxval)
tree maxval;
{
- register tree itype = make_node (INTEGER_TYPE);
+ tree itype = make_node (INTEGER_TYPE);
TREE_TYPE (itype) = sizetype;
TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
build_range_type (type, lowval, highval)
tree type, lowval, highval;
{
- register tree itype = make_node (INTEGER_TYPE);
+ tree itype = make_node (INTEGER_TYPE);
TREE_TYPE (itype) = type;
if (type == NULL_TREE)
build_array_type (elt_type, index_type)
tree elt_type, index_type;
{
- register tree t;
+ tree t;
unsigned int hashcode;
if (TREE_CODE (elt_type) == FUNCTION_TYPE)
build_function_type (value_type, arg_types)
tree value_type, arg_types;
{
- register tree t;
+ tree t;
unsigned int hashcode;
if (TREE_CODE (value_type) == FUNCTION_TYPE)
build_method_type (basetype, type)
tree basetype, type;
{
- register tree t;
+ tree t;
unsigned int hashcode;
/* Make a node of the sort we want. */
build_offset_type (basetype, type)
tree basetype, type;
{
- register tree t;
+ tree t;
unsigned int hashcode;
/* Make a node of the sort we want. */
build_complex_type (component_type)
tree component_type;
{
- register tree t;
+ tree t;
unsigned int hashcode;
/* Make a node of the sort we want. */
tree
get_unwidened (op, for_type)
- register tree op;
+ tree op;
tree for_type;
{
/* Set UNS initially if converting OP to FOR_TYPE is a zero-extension. */
- register tree type = TREE_TYPE (op);
- register unsigned final_prec
+ tree type = TREE_TYPE (op);
+ unsigned final_prec
= TYPE_PRECISION (for_type != 0 ? for_type : type);
- register int uns
+ int uns
= (for_type != 0 && for_type != type
&& final_prec > TYPE_PRECISION (type)
&& TREE_UNSIGNED (type));
- register tree win = op;
+ tree win = op;
while (TREE_CODE (op) == NOP_EXPR)
{
- register int bitschange
+ int bitschange
= TYPE_PRECISION (TREE_TYPE (op))
- TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
tree
get_narrower (op, unsignedp_ptr)
- register tree op;
+ tree op;
int *unsignedp_ptr;
{
- register int uns = 0;
+ int uns = 0;
int first = 1;
- register tree win = op;
+ tree win = op;
while (TREE_CODE (op) == NOP_EXPR)
{
- register int bitschange
+ int bitschange
= (TYPE_PRECISION (TREE_TYPE (op))
- TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0))));
static unsigned HOST_WIDE_INT value;
unsigned HOST_WIDE_INT v;
-#ifdef HAVE_GETTIMEOFDAY
- struct timeval tv;
-#endif
+ if (! value)
+ {
+ struct stat st;
- template += strlen (template);
+ /* VALUE should be unique for each file and must
+ not change between compiles since this can cause
+ bootstrap comparison errors. */
-#ifdef HAVE_GETTIMEOFDAY
- /* Get some more or less random data. */
- gettimeofday (&tv, NULL);
- value += ((unsigned HOST_WIDE_INT) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
-#else
- value += getpid ();
-#endif
+ if (stat (main_input_filename, &st) < 0)
+ abort ();
+
+ value = st.st_dev ^ st.st_ino ^ st.st_mtime;
+ }
+
+ template += strlen (template);
v = value;
TREE_TYPE (V8QI_type_node) = intQI_type_node;
TYPE_MODE (V8QI_type_node) = V8QImode;
finish_vector_type (V8QI_type_node);
+
+ V2SF_type_node = make_node (VECTOR_TYPE);
+ TREE_TYPE (V2SF_type_node) = float_type_node;
+ TYPE_MODE (V2SF_type_node) = V2SFmode;
+ finish_vector_type (V2SF_type_node);
}