⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-tree.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		    TREE_VEC_ELT (base_binfos, k)		      = make_binfo (BINFO_OFFSET (base_base_binfo),				    BINFO_TYPE (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);		}	      /* 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  /* 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;      if (const_size == 0)	offset = integer_zero_node;      else	offset = size_int ((const_size + BITS_PER_UNIT - 1) / 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)	const_size += MAX (record_align,			   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 != 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);      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),				BINFO_TYPE (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);	    }	  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.   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.  */  register unsigned const_size = 0;  register tree var_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)	{	  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);	  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_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 (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));	    }	}      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];  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.  */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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -