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

📄 gc.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Garbage collection primitives for GNU C++.   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.   Contributed by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "tree.h"#include "cp-tree.h"#include "flags.h"#include "output.h"#undef NULL#define NULL 0extern tree define_function ();extern tree build_t_desc_overload ();extern struct obstack *permanent_obstack;/* This is the function decl for the (pseudo-builtin) __gc_protect   function.  Args are (class *value, int index); Returns value.  */tree gc_protect_fndecl;/* This is the function decl for the (pseudo-builtin) __gc_unprotect   function.  Args are (int index); void return.  */tree gc_unprotect_fndecl;/* This is the function decl for the (pseudo-builtin) __gc_push   function.  Args are (int length); void return.  */tree gc_push_fndecl;/* This is the function decl for the (pseudo-builtin) __gc_pop   function.  Args are void; void return.  */tree gc_pop_fndecl;/* Special integers that are used to represent bits in gc-safe objects.  */tree gc_nonobject;tree gc_visible;tree gc_white;tree gc_offwhite;tree gc_grey;tree gc_black;/* in c-common.c */extern tree combine_strings PROTO((tree));/* Predicate that returns non-zero if TYPE needs some kind of   entry for the GC.  Returns zero otherwise.  */inttype_needs_gc_entry (type)     tree type;{  tree ttype = type;  if (! flag_gc || type == error_mark_node)    return 0;  /* Aggregate types need gc entries if any of their members     need gc entries.  */  if (IS_AGGR_TYPE (type))    {      tree binfos;      tree fields = TYPE_FIELDS (type);      int i;      /* We don't care about certain pointers.  Pointers	 to virtual baseclasses are always up front.  We also	 cull out virtual function table pointers because it's	 easy, and it simplifies the logic.*/      while (fields	     && (DECL_NAME (fields) == NULL_TREE		 || VFIELD_NAME_P (DECL_NAME (fields))		 || VBASE_NAME_P (DECL_NAME (fields))		 || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))	fields = TREE_CHAIN (fields);      while (fields)	{	  if (type_needs_gc_entry (TREE_TYPE (fields)))	    return 1;	  fields = TREE_CHAIN (fields);	}      binfos = TYPE_BINFO_BASETYPES (type);      if (binfos)	for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)	  if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))	    return 1;      return 0;    }  while (TREE_CODE (ttype) == ARRAY_TYPE	 && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)    ttype = TREE_TYPE (ttype);  if ((TREE_CODE (ttype) == POINTER_TYPE       || TREE_CODE (ttype) == ARRAY_TYPE       || TREE_CODE (ttype) == REFERENCE_TYPE)      && IS_AGGR_TYPE (TREE_TYPE (ttype))      && CLASSTYPE_RTTI (TREE_TYPE (ttype)))    return 1;  return 0;}/* Predicate that returns non-zero iff FROM is safe from the GC.      If TO is nonzero, it means we know that FROM is being stored   in TO, which make make it safe.  */intvalue_safe_from_gc (to, from)     tree to, from;{  /* First, return non-zero for easy cases: parameters,     static variables.  */  if (TREE_CODE (from) == PARM_DECL      || (TREE_CODE (from) == VAR_DECL	  && TREE_STATIC (from)))    return 1;  /* If something has its address taken, it cannot be     in the heap, so it doesn't need to be protected.  */  if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))    return 1;  /* If we are storing into a static variable, then what     we store will be safe from the gc.  */  if (to && TREE_CODE (to) == VAR_DECL      && TREE_STATIC (to))    return 1;  /* Now recurse on structure of FROM.  */  switch (TREE_CODE (from))    {    case COMPONENT_REF:      /* These guys are special, and safe.  */      if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL	  && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))	      || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))	return 1;      /* fall through...  */    case NOP_EXPR:    case CONVERT_EXPR:    case NON_LVALUE_EXPR:    case WITH_CLEANUP_EXPR:    case SAVE_EXPR:    case PREDECREMENT_EXPR:    case PREINCREMENT_EXPR:    case POSTDECREMENT_EXPR:    case POSTINCREMENT_EXPR:      if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))	return 1;      break;    case VAR_DECL:    case PARM_DECL:      /* We can safely pass these things as parameters to functions.  */      if (to == 0)	return 1;    case ARRAY_REF:    case INDIRECT_REF:    case RESULT_DECL:    case OFFSET_REF:    case CALL_EXPR:    case METHOD_CALL_EXPR:      break;    case COMPOUND_EXPR:    case TARGET_EXPR:      if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))	return 1;      break;    case COND_EXPR:      if (value_safe_from_gc (to, TREE_OPERAND (from, 1))	  && value_safe_from_gc (to, TREE_OPERAND (from, 2)))	return 1;      break;    case PLUS_EXPR:    case MINUS_EXPR:      if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))	   || value_safe_from_gc (to, TREE_OPERAND (from, 0)))	  && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0	      || value_safe_from_gc (to, TREE_OPERAND (from, 1))))	return 1;      break;    case RTL_EXPR:      /* Every time we build an RTL_EXPR in the front-end, we must	 ensure that everything in it is safe from the garbage collector.	 ??? This has only been done for `build_new'.  */      return 1;    default:      my_friendly_abort (41);    }  if (to == 0)    return 0;  /* FROM wasn't safe.  But other properties of TO might make it safe.  */  switch (TREE_CODE (to))    {    case VAR_DECL:    case PARM_DECL:      /* We already culled out static VAR_DECLs above.  */      return 0;    case COMPONENT_REF:      /* These guys are special, and safe.  */      if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL	  && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))	      || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))	return 1;      /* fall through...  */    case NOP_EXPR:    case NON_LVALUE_EXPR:    case WITH_CLEANUP_EXPR:    case SAVE_EXPR:    case PREDECREMENT_EXPR:    case PREINCREMENT_EXPR:    case POSTDECREMENT_EXPR:    case POSTINCREMENT_EXPR:      return value_safe_from_gc (TREE_OPERAND (to, 0), from);    case COMPOUND_EXPR:    case TARGET_EXPR:      return value_safe_from_gc (TREE_OPERAND (to, 1), from);    case COND_EXPR:      return (value_safe_from_gc (TREE_OPERAND (to, 1), from)	      && value_safe_from_gc (TREE_OPERAND (to, 2), from));    case INDIRECT_REF:    case ARRAY_REF:      /* This used to be 0, but our current restricted model	 allows this to be 1.  We'll never get arrays this way.  */      return 1;    default:      my_friendly_abort (42);    }  /* Catch-all case is that TO/FROM is not safe.  */  return 0;}/* Function to build a static GC entry for DECL.  TYPE is DECL's type.   For objects of type `class *', this is just an entry in the   static vector __PTR_LIST__.   For objects of type `class[]', this requires building an entry   in the static vector __ARR_LIST__.   For aggregates, this records all fields of type `class *'   and `class[]' in the respective lists above.  */voidbuild_static_gc_entry (decl, type)     tree decl;     tree type;{  /* Now, figure out what sort of entry to build.  */  if (TREE_CODE (type) == POINTER_TYPE      || TREE_CODE (type) == REFERENCE_TYPE)    assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));  else if (TREE_CODE (type) == RECORD_TYPE)    {      tree ref = get_temp_name (build_reference_type (type), 1);      DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);      TREE_CONSTANT (DECL_INITIAL (ref)) = 1;      cp_finish_decl (ref, DECL_INITIAL (ref), NULL_TREE, 0, 0);    }  else    {      /* Not yet implemented.	 	 Cons up a static variable that holds address and length info	 and add that to ___ARR_LIST__.  */      my_friendly_abort (43);    }}/* Protect FROM from the GC, assuming FROM is going to be   stored into TO.  We handle three cases for TO here:   case 1: TO is a stack variable.   case 2: TO is zero (which means it is a parameter).   case 3: TO is a return value.  */treeprotect_value_from_gc (to, from)     tree to, from;{  if (to == 0)    {      tree cleanup;      to = get_temp_regvar (TREE_TYPE (from), from);      /* Convert from integer to list form since we'll use it twice.  */      DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));      cleanup = build_function_call (gc_unprotect_fndecl,				     DECL_GC_OFFSET (to));      if (! cp_expand_decl_cleanup (to, cleanup))	{	  compiler_error ("cannot unprotect parameter in this scope");	  return error_mark_node;	}    }  /* Should never need to protect a value that's headed for static storage.  */  if (TREE_STATIC (to))    my_friendly_abort (44);  switch (TREE_CODE (to))    {    case COMPONENT_REF:    case INDIRECT_REF:      return protect_value_from_gc (TREE_OPERAND (to, 0), from);    case VAR_DECL:    case PARM_DECL:      {	tree rval;	if (DECL_GC_OFFSET (to) == NULL_TREE)	  {	    /* Because of a cast or a conversion, we might stick	       a value into a variable that would not normally	       have a GC entry.  */	    DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);	  }	if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)	  {	    DECL_GC_OFFSET (to)	      = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));	  }	current_function_obstack_usage = 1;	rval = build_function_call (gc_protect_fndecl,				    tree_cons (NULL_TREE, from,					       DECL_GC_OFFSET (to)));	TREE_TYPE (rval) = TREE_TYPE (from);	return rval;      }    }  /* If we fall through the switch, assume we lost.  */  my_friendly_abort (45);  /* NOTREACHED */  return NULL_TREE;}/* Given the expression EXP of type `class *', return the head   of the object pointed to by EXP.  */treebuild_headof (exp)     tree exp;{  tree type = TREE_TYPE (exp);  tree vptr, offset;  if (TREE_CODE (type) != POINTER_TYPE)    {      error ("`headof' applied to non-pointer type");      return error_mark_node;    }

⌨️ 快捷键说明

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