📄 tree.c
字号:
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;}/* Given TYPE, and HASHCODE its hash code, return the canonical object for an identical list if one already exists. Otherwise, return TYPE, and record it as the canonical object if it is a permanent object. To use this function, first create a list of the sort you want. Then compute its hash code from the fields of the list that make it different from other similar lists. Then call this function and use the value. This function frees the list you pass in if it is a duplicate. *//* Set to 1 to debug without canonicalization. Never set by program. */static int debug_no_list_hash = 0;treelist_hash_canon (hashcode, list) int hashcode; tree list;{ tree t1; if (debug_no_list_hash) return list; t1 = list_hash_lookup (hashcode, list); if (t1 != 0) { obstack_free (&class_obstack, list); return t1; } /* If this is a new list, record it for later reuse. */ list_hash_add (hashcode, list); return list;}treehash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain) int via_public, via_virtual, via_protected; tree purpose, value, chain;{ struct obstack *ambient_obstack = current_obstack; tree t; int hashcode; current_obstack = &class_obstack; t = tree_cons (purpose, value, chain); TREE_VIA_PUBLIC (t) = via_public; TREE_VIA_PROTECTED (t) = via_protected; TREE_VIA_VIRTUAL (t) = via_virtual; hashcode = list_hash (t); t = list_hash_canon (hashcode, t); current_obstack = ambient_obstack; return t;}/* Constructor for hashed lists. */treehash_tree_chain (value, chain) tree value, chain;{ struct obstack *ambient_obstack = current_obstack; tree t; int hashcode; current_obstack = &class_obstack; t = tree_cons (NULL_TREE, value, chain); hashcode = list_hash (t); t = list_hash_canon (hashcode, t); current_obstack = ambient_obstack; return t;}/* Similar, but used for concatenating two lists. */treehash_chainon (list1, list2) tree list1, list2;{ if (list2 == 0) return list1; if (list1 == 0) return list2; if (TREE_CHAIN (list1) == NULL_TREE) return hash_tree_chain (TREE_VALUE (list1), list2); return hash_tree_chain (TREE_VALUE (list1), hash_chainon (TREE_CHAIN (list1), list2));}static treeget_identifier_list (value) tree value;{ tree list = IDENTIFIER_AS_LIST (value); if (list != NULL_TREE && (TREE_CODE (list) != TREE_LIST || TREE_VALUE (list) != value)) list = NULL_TREE; else if (IDENTIFIER_HAS_TYPE_VALUE (value) && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE && IDENTIFIER_TYPE_VALUE (value) == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value))) { tree type = IDENTIFIER_TYPE_VALUE (value); if (TYPE_PTRMEMFUNC_P (type)) list = NULL_TREE; else if (type == current_class_type) /* Don't mess up the constructor name. */ list = tree_cons (NULL_TREE, value, NULL_TREE); else { register tree id; /* This will return the correct thing for regular types, nested types, and templates. Yay! */ if (TYPE_NESTED_NAME (type)) id = TYPE_NESTED_NAME (type); else id = TYPE_IDENTIFIER (type); if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, id, NULL_TREE); list = CLASSTYPE_ID_AS_LIST (type); } } return list;}treeget_decl_list (value) tree value;{ tree list = NULL_TREE; if (TREE_CODE (value) == IDENTIFIER_NODE) list = get_identifier_list (value); else if (TREE_CODE (value) == RECORD_TYPE && TYPE_LANG_SPECIFIC (value)) list = CLASSTYPE_AS_LIST (value); if (list != NULL_TREE) { my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301); return list; } return build_decl_list (NULL_TREE, value);}/* Look in the type hash table for a type isomorphic to `build_tree_list (NULL_TREE, VALUE)'. If one is found, return it. Otherwise return 0. */treelist_hash_lookup_or_cons (value) tree value;{ register int hashcode = TYPE_HASH (value); register struct list_hash *h; struct obstack *ambient_obstack; tree list = NULL_TREE; if (TREE_CODE (value) == IDENTIFIER_NODE) list = get_identifier_list (value); else if (TREE_CODE (value) == TYPE_DECL && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE && TYPE_LANG_SPECIFIC (TREE_TYPE (value))) list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value)); else if (TREE_CODE (value) == RECORD_TYPE && TYPE_LANG_SPECIFIC (value)) list = CLASSTYPE_AS_LIST (value); if (list != NULL_TREE) { my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302); return list; } if (debug_no_list_hash) return hash_tree_chain (value, NULL_TREE); for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && TREE_VIA_VIRTUAL (h->list) == 0 && TREE_VIA_PUBLIC (h->list) == 0 && TREE_VIA_PROTECTED (h->list) == 0 && TREE_PURPOSE (h->list) == 0 && TREE_VALUE (h->list) == value) { my_friendly_assert (TREE_TYPE (h->list) == 0, 303); my_friendly_assert (TREE_CHAIN (h->list) == 0, 304); return h->list; } ambient_obstack = current_obstack; current_obstack = &class_obstack; list = build_tree_list (NULL_TREE, value); list_hash_add (hashcode, list); current_obstack = ambient_obstack; return list;}/* Build an association between TYPE and some parameters: OFFSET is the offset added to `this' to convert it to a pointer of type `TYPE *' BINFO is the base binfo to use, if we are deriving from one. This is necessary, as we want specialized parent binfos from base classes, so that the VTABLE_NAMEs of bases are for the most derived type, instead of of the simple type. VTABLE is the virtual function table with which to initialize sub-objects of type TYPE. VIRTUALS are the virtual functions sitting in VTABLE. CHAIN are more associations we must retain. */treemake_binfo (offset, binfo, vtable, virtuals, chain) tree offset, binfo; tree vtable, virtuals; tree chain;{ tree new_binfo = make_tree_vec (6); tree type; if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else { type = binfo; binfo = TYPE_BINFO (binfo); } TREE_CHAIN (new_binfo) = chain; if (chain) TREE_USED (new_binfo) = TREE_USED (chain); TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type); BINFO_OFFSET (new_binfo) = offset; BINFO_VTABLE (new_binfo) = vtable; BINFO_VIRTUALS (new_binfo) = virtuals; BINFO_VPTR_FIELD (new_binfo) = NULL_TREE; if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE) BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo)); return new_binfo;}/* Return the binfo value for ELEM in TYPE. */treebinfo_value (elem, type) tree elem; tree type;{ if (get_base_distance (elem, type, 0, (tree *)0) == -2) compiler_error ("base class `%s' ambiguous in binfo_value", TYPE_NAME_STRING (elem)); if (elem == type) return TYPE_BINFO (type); if (TREE_CODE (elem) == RECORD_TYPE && TYPE_BINFO (elem) == type) return type; return get_binfo (elem, type, 0);}treereverse_path (path) tree path;{ register tree prev = 0, tmp, next; for (tmp = path; tmp; tmp = next) { next = BINFO_INHERITANCE_CHAIN (tmp); BINFO_INHERITANCE_CHAIN (tmp) = prev; prev = tmp; } return prev;}treevirtual_member (elem, list) tree elem; tree list;{ tree t; tree rval, nval; for (t = list; t; t = TREE_CHAIN (t)) if (elem == BINFO_TYPE (t)) return t; rval = 0; for (t = list; t; t = TREE_CHAIN (t)) { tree binfos = BINFO_BASETYPES (t); int i; if (binfos != NULL_TREE) for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) { nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i))); if (nval) { if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) my_friendly_abort (104); rval = nval; } } } return rval;}voiddebug_binfo (elem) tree elem;{ unsigned HOST_WIDE_INT n; tree virtuals; fprintf (stderr, "type \"%s\"; offset = %d\n", TYPE_NAME_STRING (BINFO_TYPE (elem)), TREE_INT_CST_LOW (BINFO_OFFSET (elem))); fprintf (stderr, "vtable type:\n"); debug_tree (BINFO_TYPE (elem)); if (BINFO_VTABLE (elem)) fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); else fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "virtuals:\n"); virtuals = BINFO_VIRTUALS (elem); n = skip_rtti_stuff (&virtuals); while (virtuals) { tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); fprintf (stderr, "%s [%d =? %d]\n", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); ++n; virtuals = TREE_CHAIN (virtuals); }}/* Return the length of a chain of nodes chained through DECL_CHAIN. We expect a null pointer to mark the end of the chain. This is the Lisp primitive `length'. */intdecl_list_length (t) tree t;{ register tree tail; register int len = 0; my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL || TREE_CODE (t) == TEMPLATE_DECL, 300); for (tail = t; tail; tail = DECL_CHAIN (tail)) len++; return len;}intcount_functions (t) tree t;{ if (TREE_CODE (t) == FUNCTION_DECL) return 1; else if (TREE_CODE (t) == TREE_LIST) return decl_list_length (TREE_VALUE (t)); my_friendly_abort (359); return 0;}/* Like value_member, but for DECL_CHAINs. */treedecl_value_member (elem, list) tree elem, list;{ while (list) { if (elem == list) return list; list = DECL_CHAIN (list); } return NULL_TREE;}intis_overloaded_fn (x) tree x;{ if (TREE_CODE (x) == FUNCTION_DECL) return 1; if (TREE_CODE (x) == TREE_LIST && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL)) return 1; return 0;}intreally_overloaded_fn (x) tree x;{ if (TREE_CODE (x) == TREE_LIST && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL)) return 1; return 0;}treeget_first_fn (from) tree from;{ if (TREE_CODE (from) == FUNCTION_DECL) return from; my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9); return TREE_VALUE (from);}treefnaddr_from_vtable_entry (entry) tree entry;{ if (flag_vtable_thunks) { tree func = entry; if (TREE_CODE (func) == ADDR_EXPR) func = TREE_OPERAND (func, 0); if (TREE_CODE (func) == THUNK_DECL) return DECL_INITIAL (func); else return entry; } else return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));}voidset_fnaddr_from_vtable_entry (entry, value) tree entry, value;{ if (flag_vtable_thunks) abort (); else TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;}treefunction_arg_chain (t) tree t;{ return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));}intpromotes_to_aggr_type (t, code) tree t; enum tree_code code;{ if (TREE_CODE (t) == code) t = TREE_TYPE (t); return IS_AGGR_TYPE (t);}intis_aggr_type_2 (t1, t2) tree t1, t2;{ if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);}/* Give message using types TYPE1 and TYPE2 as arguments. PFN is the function which will print the message; S is the format string for PFN to use. */voidmessage_2_types (pfn, s, type1, type2) void (*pfn) (); char *s; tree type1, type2;{ tree name1 = TYPE_NAME (type1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -