📄 tree.c
字号:
type = copy_node (type); TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0; } TYPE_MAIN_VARIANT (type) = real_main_variant; pop_obstacks (); } return build_type_variant (type, constp, volatilep);}/* Add OFFSET to all base types of T. OFFSET, which is a type offset, is number of bytes. Note that we don't have to worry about having two paths to the same base type, since this type owns its association list. */voidpropagate_binfo_offsets (binfo, offset) tree binfo; tree offset;{ tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (base_binfo)) i += 1; else { int j; tree base_binfos = BINFO_BASETYPES (base_binfo); tree delta; for (j = i+1; j < n_baselinks; j++) if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) { /* The next basetype offset must take into account the space between the classes, not just the size of each class. */ delta = size_binop (MINUS_EXPR, BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), BINFO_OFFSET (base_binfo)); break; }#if 0 if (BINFO_OFFSET_ZEROP (base_binfo)) BINFO_OFFSET (base_binfo) = offset; else BINFO_OFFSET (base_binfo) = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset);#else BINFO_OFFSET (base_binfo) = offset;#endif if (base_binfos) { int k; tree chain = NULL_TREE; /* Now unshare the structure beneath BASE_BINFO. */ for (k = TREE_VEC_LENGTH (base_binfos)-1; k >= 0; k--) { tree base_base_binfo = TREE_VEC_ELT (base_binfos, k); if (! TREE_VIA_VIRTUAL (base_base_binfo)) TREE_VEC_ELT (base_binfos, k) = make_binfo (BINFO_OFFSET (base_base_binfo), base_base_binfo, BINFO_VTABLE (base_base_binfo), BINFO_VIRTUALS (base_base_binfo), chain); chain = TREE_VEC_ELT (base_binfos, k); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Now propagate the offset to the base types. */ propagate_binfo_offsets (base_binfo, offset); } /* Go to our next class that counts for offset propagation. */ i = j; if (i < n_baselinks) offset = size_binop (PLUS_EXPR, offset, delta); } }}/* Compute the actual offsets that our virtual base classes will have *for this type*. This must be performed after the fields are laid out, since virtual baseclasses must lay down at the end of the record. Returns the maximum number of virtual functions any of the virtual baseclasses provide. */intlayout_vbasetypes (rec, max) tree rec; int max;{ /* Get all the virtual base types that this type uses. The TREE_VALUE slot holds the virtual baseclass type. */ tree vbase_types = get_vbase_types (rec);#ifdef STRUCTURE_SIZE_BOUNDARY unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));#else unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));#endif int desired_align; /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using VAR_SIZE. */ register unsigned const_size = 0; register tree var_size = 0; int nonvirtual_const_size; tree nonvirtual_var_size; CLASSTYPE_VBASECLASSES (rec) = vbase_types; if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST) const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec)); else var_size = TYPE_SIZE (rec); nonvirtual_const_size = const_size; nonvirtual_var_size = var_size; while (vbase_types) { tree basetype = BINFO_TYPE (vbase_types); tree offset; desired_align = TYPE_ALIGN (basetype); record_align = MAX (record_align, desired_align); if (const_size == 0) offset = integer_zero_node; else { /* Give each virtual base type the alignment it wants. */ const_size = CEIL (const_size, TYPE_ALIGN (basetype)) * TYPE_ALIGN (basetype); offset = size_int (CEIL (const_size, BITS_PER_UNIT)); } if (CLASSTYPE_VSIZE (basetype) > max) max = CLASSTYPE_VSIZE (basetype); BINFO_OFFSET (vbase_types) = offset; if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST) { /* Every virtual baseclass takes a least a UNIT, so that we can take it's address and get something different for each base. */ const_size += MAX (BITS_PER_UNIT, TREE_INT_CST_LOW (TYPE_SIZE (basetype)) - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); } else if (var_size == 0) var_size = TYPE_SIZE (basetype); else var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype)); vbase_types = TREE_CHAIN (vbase_types); } if (const_size) { /* Because a virtual base might take a single byte above, we have to re-adjust the total size to make sure it it a multiple of the alignment. */ /* Give the whole object the alignment it wants. */ const_size = CEIL (const_size, record_align) * record_align; } /* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN here, as that is for this class, without any virtual base classes. */ TYPE_ALIGN (rec) = record_align; if (const_size != nonvirtual_const_size) { CLASSTYPE_VBASE_SIZE (rec) = size_int (const_size - nonvirtual_const_size); TYPE_SIZE (rec) = size_int (const_size); } /* Now propagate offset information throughout the lattice under the vbase type. */ for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types; vbase_types = TREE_CHAIN (vbase_types)) { tree base_binfos = BINFO_BASETYPES (vbase_types); BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); if (base_binfos) { tree chain = NULL_TREE; int j; /* Now unshare the structure beneath BASE_BINFO. */ for (j = TREE_VEC_LENGTH (base_binfos)-1; j >= 0; j--) { tree base_base_binfo = TREE_VEC_ELT (base_binfos, j); if (! TREE_VIA_VIRTUAL (base_base_binfo)) TREE_VEC_ELT (base_binfos, j) = make_binfo (BINFO_OFFSET (base_base_binfo), base_base_binfo, BINFO_VTABLE (base_base_binfo), BINFO_VIRTUALS (base_base_binfo), chain); chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); BINFO_INHERITANCE_CHAIN (chain) = vbase_types; } propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); } } return max;}/* Lay out the base types of a record type, REC. Tentatively set the size and alignment of REC according to the base types alone. Offsets for immediate nonvirtual baseclasses are also computed here. TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS. Returns list of virtual base classes in a FIELD_DECL chain. */treelayout_basetypes (rec, binfos) tree rec, binfos;{ /* Chain to hold all the new FIELD_DECLs which point at virtual base classes. */ tree vbase_decls = NULL_TREE;#ifdef STRUCTURE_SIZE_BOUNDARY unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));#else unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));#endif /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using VAR_SIZE. And so far, we've been successful. */#if 0 register tree var_size = 0;#endif register unsigned const_size = 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; /* Handle basetypes almost like fields, but record their offsets differently. */ for (i = 0; i < n_baseclasses; i++) { int inc, desired_align, int_vbase_size; register tree base_binfo = TREE_VEC_ELT (binfos, i); register tree basetype = BINFO_TYPE (base_binfo); tree decl, offset; if (TYPE_SIZE (basetype) == 0) {#if 0 /* This error is now reported in xref_tag, thus giving better location information. */ error_with_aggr_type (base_binfo, "base class `%s' has incomplete type"); TREE_VIA_PUBLIC (base_binfo) = 1; TREE_VIA_PROTECTED (base_binfo) = 0; TREE_VIA_VIRTUAL (base_binfo) = 0; /* Should handle this better so that class A; class B: private A { virtual void F(); }; does not dump core when compiled. */ my_friendly_abort (121);#endif continue; } /* All basetypes are recorded in the association list of the derived type. */ if (TREE_VIA_VIRTUAL (base_binfo)) { int j; char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype) + sizeof (VBASE_NAME) + 1); /* The offset for a virtual base class is only used in computing virtual function tables and for initializing virtual base pointers. It is built once `get_vbase_types' is called. */ /* If this basetype can come from another vbase pointer without an additional indirection, we will share that pointer. If an indirection is involved, we make our own pointer. */ for (j = 0; j < n_baseclasses; j++) { tree other_base_binfo = TREE_VEC_ELT (binfos, j); if (! TREE_VIA_VIRTUAL (other_base_binfo) && binfo_member (basetype, CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo)))) goto got_it; } sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); decl = build_lang_decl (FIELD_DECL, get_identifier (name), build_pointer_type (basetype)); /* If you change any of the below, take a look at all the other VFIELD_BASEs and VTABLE_BASEs in the code, and change them too. */ DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE); DECL_VIRTUAL_P (decl) = 1; DECL_FIELD_CONTEXT (decl) = rec; DECL_CLASS_CONTEXT (decl) = rec; DECL_FCONTEXT (decl) = basetype; DECL_SAVED_INSNS (decl) = NULL_RTX; DECL_FIELD_SIZE (decl) = 0; DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node); TREE_CHAIN (decl) = vbase_decls; BINFO_VPTR_FIELD (base_binfo) = decl; vbase_decls = decl; if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), "destructor `%s' non-virtual"); warning ("in inheritance relationship `%s: virtual %s'", TYPE_NAME_STRING (rec), TYPE_NAME_STRING (basetype)); } got_it: /* The space this decl occupies has already been accounted for. */ continue; } if (const_size == 0) offset = integer_zero_node; else { /* Give each base type the alignment it wants. */ const_size = CEIL (const_size, TYPE_ALIGN (basetype)) * TYPE_ALIGN (basetype); offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);#if 0 /* bpk: Disabled this check until someone is willing to claim it as theirs and explain exactly what circumstances warrant the warning. */ if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), "destructor `%s' non-virtual"); warning ("in inheritance relationship `%s:%s %s'", TYPE_NAME_STRING (rec), TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "", TYPE_NAME_STRING (basetype)); }#endif } BINFO_OFFSET (base_binfo) = offset; if (CLASSTYPE_VSIZE (basetype)) { BINFO_VTABLE (base_binfo) = TYPE_BINFO_VTABLE (basetype); BINFO_VIRTUALS (base_binfo) = TYPE_BINFO_VIRTUALS (basetype); } TREE_CHAIN (base_binfo) = TYPE_BINFO (rec); TYPE_BINFO (rec) = base_binfo; /* Add only the amount of storage not present in the virtual baseclasses. */ int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)); if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size) { inc = MAX (record_align, (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) - int_vbase_size)); /* Record must have at least as much alignment as any field. */ desired_align = TYPE_ALIGN (basetype); record_align = MAX (record_align, desired_align); const_size += inc; } } if (const_size) CLASSTYPE_SIZE (rec) = size_int (const_size); else CLASSTYPE_SIZE (rec) = integer_zero_node; CLASSTYPE_ALIGN (rec) = record_align; return vbase_decls;}/* Hashing of lists so that we don't make duplicates. The entry point is `list_hash_canon'. *//* Each hash table slot is a bucket containing a chain of these structures. */struct list_hash{ struct list_hash *next; /* Next structure in the bucket. */ int hashcode; /* Hash code of this list. */ tree list; /* The list recorded here. */};/* Now here is the hash table. When recording a list, it is added to the slot whose index is the hash code mod the table size. Note that the hash table is used for several kinds of lists. While all these live in the same table, they are completely independent, and the hash code is computed differently for each of these. */#define TYPE_HASH_SIZE 59struct list_hash *list_hash_table[TYPE_HASH_SIZE];/* Compute a hash code for a list (chain of TREE_LIST nodes with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the TREE_COMMON slots), by adding the hash codes of the individual entries. */intlist_hash (list) tree list;{ register int hashcode = 0; if (TREE_CHAIN (list)) hashcode += TYPE_HASH (TREE_CHAIN (list)); if (TREE_VALUE (list)) hashcode += TYPE_HASH (TREE_VALUE (list)); else hashcode += 1007; if (TREE_PURPOSE (list)) hashcode += TYPE_HASH (TREE_PURPOSE (list)); else hashcode += 1009; return hashcode;}/* Look in the type hash table for a type isomorphic to TYPE. If one is found, return it. Otherwise return 0. */treelist_hash_lookup (hashcode, list) int hashcode; tree list;{ register struct list_hash *h; for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list) && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list) && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list) && TREE_PURPOSE (h->list) == TREE_PURPOSE (list) && TREE_VALUE (h->list) == TREE_VALUE (list) && TREE_CHAIN (h->list) == TREE_CHAIN (list)) { my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299); return h->list; } return 0;}/* Add an entry to the list-hash-table for a list TYPE whose hash code is HASHCODE. */voidlist_hash_add (hashcode, list) int hashcode; tree list;{ register struct list_hash *h; h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash)); h->hashcode = hashcode; h->list = list; h->next = list_hash_table[hashcode % TYPE_HASH_SIZE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -