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

📄 class.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
   Note that the index (DELTA2) in the virtual function table   is always 0.  */static treebuild_vtable_entry (delta, pfn)     tree delta, pfn;{  if (flag_vtable_thunks)    {      HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);      if (idelta && ! DECL_ABSTRACT_VIRTUAL_P (TREE_OPERAND (pfn, 0)))	{	  pfn = build1 (ADDR_EXPR, vtable_entry_type,			make_thunk (pfn, idelta));	  TREE_READONLY (pfn) = 1;	  TREE_CONSTANT (pfn) = 1;	}#ifdef GATHER_STATISTICS      n_vtable_entries += 1;#endif      return pfn;    }  else    {      extern int flag_huge_objects;      tree elems = expr_tree_cons (NULL_TREE, delta,			      expr_tree_cons (NULL_TREE, integer_zero_node,					 build_expr_list (NULL_TREE, pfn)));      tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);      /* DELTA used to be constructed by `size_int' and/or size_binop,	 which caused overflow problems when it was negative.  That should	 be fixed now.  */      if (! int_fits_type_p (delta, delta_type_node))	{	  if (flag_huge_objects)	    sorry ("object size exceeds built-in limit for virtual function table implementation");	  else	    sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");	}            TREE_CONSTANT (entry) = 1;      TREE_STATIC (entry) = 1;      TREE_READONLY (entry) = 1;#ifdef GATHER_STATISTICS      n_vtable_entries += 1;#endif      return entry;    }}/* We want to give the assembler the vtable identifier as well as   the offset to the function pointer.  So we generate   __asm__ __volatile__ (".vtable_entry %c0, %c1"      : : "s"(&class_vtable),          "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */static voidbuild_vtable_entry_ref (basetype, vtbl, idx)     tree basetype, vtbl, idx;{  static char asm_stmt[] = ".vtable_entry %c0, %c1";  tree s, i, i2;  s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);  s = build_tree_list (build_string (1, "s"), s);  i = build_array_ref (vtbl, idx);  if (!flag_vtable_thunks)    i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);  i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));  i2 = build_array_ref (vtbl, build_int_2(0,0));  i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));  i = build_binary_op (MINUS_EXPR, i, i2);  i = build_tree_list (build_string (1, "i"), i);  expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),		       NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0);}/* Given an object INSTANCE, return an expression which yields the   virtual function vtable element corresponding to INDEX.  There are   many special cases for INSTANCE which we take care of here, mainly   to avoid creating extra tree nodes when we don't have to.  */treebuild_vtbl_ref (instance, idx)     tree instance, idx;{  tree vtbl, aref;  tree basetype = TREE_TYPE (instance);  if (TREE_CODE (basetype) == REFERENCE_TYPE)    basetype = TREE_TYPE (basetype);  if (instance == current_class_ref)    vtbl = build_vfield_ref (instance, basetype);  else    {      if (optimize)	{	  /* Try to figure out what a reference refers to, and	     access its virtual function table directly.  */	  tree ref = NULL_TREE;	  if (TREE_CODE (instance) == INDIRECT_REF	      && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)	    ref = TREE_OPERAND (instance, 0);	  else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)	    ref = instance;	  if (ref && TREE_CODE (ref) == VAR_DECL	      && DECL_INITIAL (ref))	    {	      tree init = DECL_INITIAL (ref);	      while (TREE_CODE (init) == NOP_EXPR		     || TREE_CODE (init) == NON_LVALUE_EXPR)		init = TREE_OPERAND (init, 0);	      if (TREE_CODE (init) == ADDR_EXPR)		{		  init = TREE_OPERAND (init, 0);		  if (IS_AGGR_TYPE (TREE_TYPE (init))		      && (TREE_CODE (init) == PARM_DECL			  || TREE_CODE (init) == VAR_DECL))		    instance = init;		}	    }	}      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_vfield_ref (instance, basetype);    }  assemble_external (vtbl);  if (flag_vtable_gc)    build_vtable_entry_ref (basetype, vtbl, idx);  aref = build_array_ref (vtbl, idx);  return aref;}/* Given an object INSTANCE, return an expression which yields the   virtual function corresponding to INDEX.  There are many special   cases for INSTANCE which we take care of here, mainly to avoid   creating extra tree nodes when we don't have to.  */treebuild_vfn_ref (ptr_to_instptr, instance, idx)     tree *ptr_to_instptr, instance;     tree idx;{  tree aref = build_vtbl_ref (instance, idx);  /* When using thunks, there is no extra delta, and we get the pfn     directly.  */  if (flag_vtable_thunks)    return aref;  if (ptr_to_instptr)    {      /* Save the intermediate result in a SAVE_EXPR so we don't have to	 compute each component of the virtual function pointer twice.  */       if (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,		 cp_convert (ptrdiff_type_node,			     build_component_ref (aref, delta_identifier, NULL_TREE, 0)));    }  return build_component_ref (aref, pfn_identifier, NULL_TREE, 0);}/* Return the name of the virtual function table (as an IDENTIFIER_NODE)   for the given TYPE.  */static treeget_vtable_name (type)     tree type;{  tree type_id = build_typename_overload (type);  char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)			       + IDENTIFIER_LENGTH (type_id) + 2);  const char *ptr = IDENTIFIER_POINTER (type_id);  int i;  for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;#if 0  /* We don't take off the numbers; prepare_fresh_vtable uses the     DECL_ASSEMBLER_NAME for the type, which includes the number     in `3foo'.  If we were to pull them off here, we'd end up with     something like `_vt.foo.3bar', instead of a uniform definition.  */  while (ptr[i] >= '0' && ptr[i] <= '9')    i += 1;#endif  sprintf (buf, VTABLE_NAME_FORMAT, ptr+i);  return get_identifier (buf);}/* Return the offset to the main vtable for a given base BINFO.  */treeget_vfield_offset (binfo)     tree binfo;{  tree tmp    = size_binop (FLOOR_DIV_EXPR,		  DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),		  size_int (BITS_PER_UNIT));  tmp = convert (sizetype, tmp);  return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo));}/* Get the offset to the start of the original binfo that we derived   this binfo from.  If we find TYPE first, return the offset only   that far.  The shortened search is useful because the this pointer   on method calling is expected to point to a DECL_CONTEXT (fndecl)   object, and not a baseclass of it.  */static treeget_derived_offset (binfo, type)     tree binfo, type;{  tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));  tree offset2;  int i;  while (BINFO_BASETYPES (binfo)	 && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)    {      tree binfos = BINFO_BASETYPES (binfo);      if (BINFO_TYPE (binfo) == type)	break;      binfo = TREE_VEC_ELT (binfos, i);    }  offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));  return size_binop (MINUS_EXPR, offset1, offset2);}/* Update the rtti info for this class.  */static voidset_rtti_entry (virtuals, offset, type)     tree virtuals, offset, type;{  tree vfn;  if (CLASSTYPE_COM_INTERFACE (type))    return;  if (flag_rtti)    vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn_unused (type));  else    vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);  TREE_CONSTANT (vfn) = 1;  if (! flag_vtable_thunks)    TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);  else    {      tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);      TREE_CONSTANT (voff) = 1;      TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);      /* The second slot is for the tdesc pointer when thunks are used.  */      TREE_VALUE (TREE_CHAIN (virtuals))	= build_vtable_entry (integer_zero_node, vfn);    }}/* 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)    {      tree offset;      virtuals = copy_list (BINFO_VIRTUALS (binfo));      decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));      /* Now do rtti stuff.  */      offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);      offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);      set_rtti_entry (virtuals, offset, type);    }  else    {      virtuals = NULL_TREE;      decl = build_lang_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, 0);  decl = pushdecl_top_level (decl);  SET_IDENTIFIER_GLOBAL_VALUE (name, decl);  /* Initialize the association list for this type, based     on our first approximation.  */  TYPE_BINFO_VTABLE (type) = decl;  TYPE_BINFO_VIRTUALS (type) = virtuals;  DECL_ARTIFICIAL (decl) = 1;  TREE_STATIC (decl) = 1;#ifndef WRITABLE_VTABLES  /* Make them READONLY by default. (mrs) */  TREE_READONLY (decl) = 1;#endif  /* At one time the vtable info was grabbed 2 words at a time.  This     fails on sparc unless you have 8-byte alignment.  (tiemann) */  DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),			   DECL_ALIGN (decl));  DECL_VIRTUAL_P (decl) = 1;  DECL_CONTEXT (decl) = type;  binfo = TYPE_BINFO (type);  SET_BINFO_NEW_VTABLE_MARKED (binfo);  return decl;}extern tree signed_size_zero_node;/* 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 order in which vtables are built (by calling this function) for   an object must remain the same, otherwise a binary incompatibility   can result.  */static voidprepare_fresh_vtable (binfo, for_type)     tree binfo, for_type;{  tree basetype;  tree orig_decl = BINFO_VTABLE (binfo);  tree name;  tree new_decl;  tree offset;  tree path = binfo;  char *buf, *buf2;  char joiner = '_';  int i;#ifdef JOINER  joiner = JOINER;#endif  basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));  buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);  i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;  /* We know that the vtable that we are going to create doesn't exist     yet in the global namespace, and when we finish, it will be     pushed into the global namespace.  In complex MI hierarchies, we     have to loop while the name we are thinking of adding is globally     defined, adding more name components to the vtable name as we     loop, until the name is unique.  This is because in complex MI     cases, we might have the same base more than once.  This means     that the order in which this function is called for vtables must     remain the same, otherwise binary compatibility can be     compromised.  */  while (1)    {      char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type)				    + 1 + i);      char *new_buf2;      sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner,	       buf2);      buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1);      sprintf (buf, VTABLE_NAME_FORMAT, buf1);      name = get_identifier (buf);      /* If this name doesn't clash, then we can use it, otherwise	 we add more to the name until it is unique.  */      if (! IDENTIFIER_GLOBAL_VALUE (name))	break;      /* Set values for next loop through, if the name isn't unique.  */      path = BINFO_INHERITANCE_CHAIN (path);

⌨️ 快捷键说明

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