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

📄 cp-class.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (IS_AGGR_TYPE (TREE_TYPE (instance))	  && (TREE_CODE (instance) == RESULT_DECL	      || TREE_CODE (instance) == PARM_DECL	      || TREE_CODE (instance) == VAR_DECL))	vtbl = TYPE_BINFO_VTABLE (basetype);      else	vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), 0);    }  assemble_external (vtbl);  aref = build_array_ref (vtbl, index);  if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)    TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));  *ptr_to_instptr = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),			   *ptr_to_instptr,			   convert (integer_type_node, build_component_ref (aref, delta_name, 0, 0)));  return build_component_ref (aref, pfn_name, 0, 0);}/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,   based on TYPE and other static flags.   Note that anything public is tagged TREE_PUBLIC, whether   it's public in this file or in another one.  */static voidimport_export_vtable (decl, type)  tree decl, type;{  if (write_virtuals >= 2)    {      if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)	{	  TREE_PUBLIC (decl) = 1;	  DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);	}    }  else if (write_virtuals != 0)    {      TREE_PUBLIC (decl) = 1;      if (write_virtuals < 0)	DECL_EXTERNAL (decl) = 1;    }}/* Build a virtual function for type TYPE.   If BINFO is non-NULL, build the vtable starting with the initial   approximation that it is the same as the one which is the head of   the association list.  */static treebuild_vtable (binfo, type)     tree binfo, type;{  tree name = get_vtable_name (type);  tree virtuals, decl;  if (binfo)    {      virtuals = copy_list (BINFO_VIRTUALS (binfo));      decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));    }  else    {      virtuals = NULL_TREE;      decl = build_decl (VAR_DECL, name, void_type_node);    }#ifdef GATHER_STATISTICS  n_vtables += 1;  n_vtable_elems += list_length (virtuals);#endif  /* Set TREE_PUBLIC and TREE_EXTERN as appropriate.  */  import_export_vtable (decl, type);  IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);  /* Initialize the association list for this type, based     on our first approximation.  */  TYPE_BINFO_VTABLE (type) = decl;  TYPE_BINFO_VIRTUALS (type) = virtuals;  TREE_STATIC (decl) = 1;  DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),			   DECL_ALIGN (decl));  if (binfo && write_virtuals >= 0)    DECL_VIRTUAL_P (decl) = 1;  /* Remember which class this vtable is really for.  */  DECL_VPARENT (decl) = type;  DECL_CONTEXT (decl) = type;  binfo = TYPE_BINFO (type);  SET_BINFO_VTABLE_PATH_MARKED (binfo);  SET_BINFO_NEW_VTABLE_MARKED (binfo);  return decl;}/* Give TYPE a new virtual function table which is initialized   with a skeleton-copy of its original initialization.  The only   entry that changes is the `delta' entry, so we can really   share a lot of structure.   FOR_TYPE is the derived type which caused this table to   be needed.   BINFO is the type association which provided TYPE for FOR_TYPE.   The way we update BASE_BINFO's vtable information is just to change the   association information in FOR_TYPE's association list.  */static voidprepare_fresh_vtable (binfo, base_binfo, for_type)     tree binfo, base_binfo, for_type;{  tree basetype = BINFO_TYPE (binfo);  tree orig_decl = BINFO_VTABLE (binfo);  tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);  tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));  tree path;  int result;  /* Remember which class this vtable is really for.  */  DECL_VPARENT (new_decl) = BINFO_TYPE (base_binfo);  DECL_CONTEXT (new_decl) = for_type;  TREE_STATIC (new_decl) = 1;  BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);  DECL_VIRTUAL_P (new_decl) = 1;  DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);  /* Make fresh virtual list, so we can smash it later.  */  BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));  /* Install the value for `headof' if that's what we're doing.  */  if (flag_dossier)    TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo)))      = build_vtable_entry (size_binop (MINUS_EXPR, integer_zero_node, BINFO_OFFSET (binfo)),			    FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo)))));#ifdef GATHER_STATISTICS  n_vtables += 1;  n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));#endif  /* Set TREE_PUBLIC and TREE_EXTERN as appropriate.  */  import_export_vtable (new_decl, for_type);  if (TREE_VIA_VIRTUAL (binfo))    my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),				   CLASSTYPE_VBASECLASSES (current_class_type)),			170);  SET_BINFO_NEW_VTABLE_MARKED (binfo);  SET_BINFO_VTABLE_PATH_MARKED (binfo);  /* Mark all types between FOR_TYPE and TYPE as having been     touched, so that if we change virtual function table entries,     new vtables will be initialized.  We may reach the virtual     baseclass via ambiguous intervening baseclasses.  This     loop makes sure we get through to the actual baseclass we marked.     Also, update the vtable entries to reflect the overrides     of the top-most class (short of the top type).  */  do    {      result = get_base_distance (basetype, for_type, 0, &path);      for_type = path;      while (path)	{	  tree path_binfo = path;	  tree path_type = BINFO_TYPE (path);	  if (TREE_VIA_VIRTUAL (path))	    path_binfo = binfo_member (path_type,				       CLASSTYPE_VBASECLASSES (current_class_type));	  SET_BINFO_VTABLE_PATH_MARKED (path_binfo);	  if (BINFO_INHERITANCE_CHAIN (path)	      && CLASSTYPE_VFIELD (path_type) != NULL_TREE	      && (DECL_NAME (CLASSTYPE_VFIELD (BINFO_TYPE (binfo)))		  == DECL_NAME (CLASSTYPE_VFIELD (path_type)))	      /* This is the baseclass just before the original FOR_TYPE.  */	      && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)	    {	      tree old_virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo));	      tree new_virtuals = TREE_CHAIN (BINFO_VIRTUALS (path_binfo));	      if (flag_dossier)		{		  old_virtuals = TREE_CHAIN (old_virtuals);		  new_virtuals = TREE_CHAIN (new_virtuals);		}	      while (old_virtuals)		{		  TREE_VALUE (old_virtuals) = TREE_VALUE (new_virtuals);		  old_virtuals = TREE_CHAIN (old_virtuals);		  new_virtuals = TREE_CHAIN (new_virtuals);		}	    }	  path = BINFO_INHERITANCE_CHAIN (path);	}    }  while (result == -2);}/* Access the virtual function table entry that logically   contains BASE_FNDECL.  VIRTUALS is the virtual function table's   initializer.  */static treeget_vtable_entry (virtuals, base_fndecl)     tree virtuals, base_fndecl;{  int i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD#ifdef VTABLE_USES_MASK	   && 0#endif	   ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))	      & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))	   : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));#ifdef GATHER_STATISTICS  n_vtable_searches += i;#endif  while (i > 0)    {      virtuals = TREE_CHAIN (virtuals);      i -= 1;    }  return virtuals;}/* Put new entry ENTRY into virtual function table initializer   VIRTUALS.  The virtual function table is for type CONTEXT.   Also update DECL_VINDEX (FNDECL).  */static voidmodify_vtable_entry (old_entry_in_list, new_entry, fndecl, context)     tree old_entry_in_list, new_entry, fndecl, context;{  tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list));  tree vindex;  /* We can't put in the really right offset information     here, since we have not yet laid out the class to     take into account virtual base classes.  */  TREE_VALUE (old_entry_in_list) = new_entry;  vindex = DECL_VINDEX (TREE_OPERAND (base_pfn, 0));  if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)    DECL_VINDEX (fndecl) = vindex;  else    {      if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex))	{	  tree elts = CONSTRUCTOR_ELTS (new_entry);	  tree vfield = CLASSTYPE_VFIELD (context);	  if (! doing_hard_virtuals)	    {	      pending_hard_virtuals		= tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),			     pending_hard_virtuals);	      TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);	      return;	    }#if 0	  my_friendly_abort (3);	  /* Compute the relative offset of vtable we are really looking for.  */	  TREE_VALUE (elts) = size_binop (PLUS_EXPR,					  size_int (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (vfield))/* ??? This may be wrong. */						    / BITS_PER_UNIT),					  TREE_VALUE (elts));	  /* Say what index to use when we use that vtable.  */#ifndef VTABLE_USES_MASK	  vindex = build_int_2 (TREE_INT_CST_LOW (vindex)				& ~((unsigned HOST_WIDE_INT) 1				    << (BITS_PER_WORD -1)), 0);#endif	  TREE_VALUE (TREE_CHAIN (elts)) = vindex;#endif	}    }}/* Modify virtual function tables in lattice topped by T to   place FNDECL in tables which previously held BASE_FNDECL.   PFN is just FNDECL wrapped in an ADDR_EXPR, so that it   is suitable for placement directly into an initializer.   All distinct virtual function tables that this type uses   must be updated.  */static voidmodify_vtable_entries (t, fndecl, base_fndecl, pfn)     tree t;     tree fndecl, base_fndecl, pfn;{  tree base_offset, offset;  tree base_context = DECL_CLASS_CONTEXT (base_fndecl);  tree context = DECL_CLASS_CONTEXT (fndecl);  tree vfield = CLASSTYPE_VFIELD (t);  tree vfields, vbases;  DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);  offset = integer_zero_node;  if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))    {      offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);      if (offset == NULL_TREE)	{	  tree binfo = binfo_value (context, t, 0);	  offset = BINFO_OFFSET (binfo);	}    }  /* For each layer of base class (i.e., the first base class, and each     virtual base class from that one), modify the virtual function table     of the derived class to contain the new virtual function.     A class has as many vfields as it has virtual base classes (total).  */  for (vfields = CLASSTYPE_VFIELDS (t); vfields; vfields = TREE_CHAIN (vfields))    {      int normal = 1;      tree binfo, this_offset;      tree base, path;      /* Find the right base class for this derived class, call it BASE.  */      base = VF_BASETYPE_VALUE (vfields);      if (base != base_context)	{	  /* If BASE_FNDECL is not contained in the vtable accessed by	     the vslot, don't try to modify the vtable.	     	     Virtual functions from virtual baseclasses are not in derived	     virtual function tables.  This is an implementation decision;	     it keeps there from being a combinatorial explosion in the	     number of different vtables which must be maintained.  */	  /* In this case, we need to know whether BASE is derived	     from BASE_CONTEXT in any case, even the case where the	     derivation is ambiguous.  */	  int distance = get_base_distance (base, base_context, 0, 0);	  if (distance < 0 && distance != -2)	    continue;	  /* BASE_FNDECL is defined in a class derived from	     the base class owning this VFIELD.  */	}      /* Get the path starting from the deepest base class CONTEXT	 of T (i.e., first defn of BASE_FNDECL).  */      get_base_distance (base_context, t, 0, &path);      /* Get our best approximation of what to use for constructing	 the virtual function table for T.  */      do	{	  /* Walk from base toward derived, stopping at the	     most derived baseclass that matters.  That baseclass	     is exactly the one which provides the vtable along	     the VFIELD spine, but no more.  */	  if (TREE_VIA_VIRTUAL (path))	    {	      base = path;	      binfo = binfo_member (BINFO_TYPE (base), CLASSTYPE_VBASECLASSES (t));	      break;	    }	  if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE	      || (BINFO_TYPE (BINFO_BASETYPE (BINFO_INHERITANCE_CHAIN (path), 0))		  != BINFO_TYPE (path))	      || BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)	    {	      base = path;	      binfo = base;	      break;	    }	  path = BINFO_INHERITANCE_CHAIN (path);	}      while (1);      /* Find the right offset for the this pointer based on the base	 class we just found.  */      base_offset = BINFO_OFFSET (binfo);      this_offset = size_binop (MINUS_EXPR, offset, base_offset);      /* Make sure we can modify the derived association with immunity.  */      if (TREE_USED (TYPE_BINFO (t)))	TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));      /* We call this case NORMAL iff this virtual function table	 pointer field has its storage reserved in this class.	 This is normally the case without virtual baseclasses	 or off-center multiple baseclasses.  */      normal = (vfield != NULL_TREE		&& VF_BASETYPE_VALUE (vfields) == DECL_FCONTEXT (vfield)		&& (VF_BINFO_VALUE (vfields) == NULL_TREE		    || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));      if (normal && VF_BINFO_VALUE (vfields))	/* Everything looks normal so far...check that we are really	   working from VFIELD's basetype, and not some other appearance	   of that basetype in the lattice.  */	normal = (VF_BINFO_VALUE (vfields)		  == get_binfo (VF_BASETYPE_VALUE (vfields), t, 0));      if (normal)	{	  /* In this case, it is *type*'s vtable we are modifying.	     We start with the approximation that it's vtable is that

⌨️ 快捷键说明

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