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

📄 sdbout.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 3 页
字号:
	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);	return 0;      }    case REAL_TYPE:      {	int size = int_size_in_bytes (type) * BITS_PER_UNIT;	if (size == FLOAT_TYPE_SIZE)	  return T_FLOAT;	if (size == DOUBLE_TYPE_SIZE)	  return T_DOUBLE;	return 0;      }    case ARRAY_TYPE:      {	int m;	if (level >= 6)	  return T_VOID;	else	  m = plain_type_1 (TREE_TYPE (type), level+1);	if (sdb_n_dims < SDB_MAX_DIM)	  sdb_dims[sdb_n_dims++]	    = (TYPE_DOMAIN (type)	       ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1	       : 0);	return PUSH_DERIVED_LEVEL (DT_ARY, m);      }    case RECORD_TYPE:    case UNION_TYPE:    case QUAL_UNION_TYPE:    case ENUMERAL_TYPE:      {	char *tag;#ifdef SDB_ALLOW_FORWARD_REFERENCES	sdbout_record_type_name (type);#endif#ifndef SDB_ALLOW_UNKNOWN_REFERENCES	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)#ifdef SDB_ALLOW_FORWARD_REFERENCES	    || TYPE_MODE (type) != VOIDmode#endif	    )#endif	  {	    /* Output the referenced structure tag name	       only if the .def has already been finished.	       At least on 386, the Unix assembler	       cannot handle forward references to tags.  */	    /* But the 88100, it requires them, sigh... */	    /* And the MIPS requires unknown refs as well... */	    tag = KNOWN_TYPE_TAG (type);	    PUT_SDB_TAG (tag);	    /* These 3 lines used to follow the close brace.	       However, a size of 0 without a tag implies a tag of 0,	       so if we don't know a tag, we can't mention the size.  */	    sdb_type_size = int_size_in_bytes (type);	    if (sdb_type_size < 0)	      sdb_type_size = 0;	  }	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION		: T_ENUM);      }    case POINTER_TYPE:    case REFERENCE_TYPE:      {	int m;	if (level >= 6)	  return T_VOID;	else	  m = plain_type_1 (TREE_TYPE (type), level+1);	return PUSH_DERIVED_LEVEL (DT_PTR, m);      }    case FUNCTION_TYPE:    case METHOD_TYPE:      {	int m;	if (level >= 6)	  return T_VOID;	else	  m = plain_type_1 (TREE_TYPE (type), level+1);	return PUSH_DERIVED_LEVEL (DT_FCN, m);      }    default:      return 0;    }}/* Output the symbols defined in block number DO_BLOCK.   Set NEXT_BLOCK_NUMBER to 0 before calling.   This function works by walking the tree structure of blocks,   counting blocks until it finds the desired block.  */static int do_block = 0;static int next_block_number;static voidsdbout_block (block)     register tree block;{  while (block)    {      /* Ignore blocks never expanded or otherwise marked as real.  */      if (TREE_USED (block))	{	  /* When we reach the specified block, output its symbols.  */	  if (next_block_number == do_block)	    {	      sdbout_syms (BLOCK_VARS (block));	    }	  /* If we are past the specified block, stop the scan.  */	  if (next_block_number > do_block)	    return;	  next_block_number++;	  /* Scan the blocks within this block.  */	  sdbout_block (BLOCK_SUBBLOCKS (block));	}      block = BLOCK_CHAIN (block);    }}/* Call sdbout_symbol on each decl in the chain SYMS.  */static voidsdbout_syms (syms)     tree syms;{  while (syms)    {      if (TREE_CODE (syms) != LABEL_DECL)	sdbout_symbol (syms, 1);      syms = TREE_CHAIN (syms);    }}/* Output SDB information for a symbol described by DECL.   LOCAL is nonzero if the symbol is not file-scope.  */voidsdbout_symbol (decl, local)     tree decl;     int local;{  tree type = TREE_TYPE (decl);  tree context = NULL_TREE;  rtx value;  int regno = -1;  char *name;  sdbout_one_type (type);#if 0 /* This loses when functions are marked to be ignored,	 which happens in the C++ front end.  */  if (DECL_IGNORED_P (decl))    return;#endif  switch (TREE_CODE (decl))    {    case CONST_DECL:      /* Enum values are defined by defining the enum type.  */      return;    case FUNCTION_DECL:      /* Don't mention a nested function under its parent.  */      context = decl_function_context (decl);      if (context == current_function_decl)	return;      if (DECL_EXTERNAL (decl))	return;      if (GET_CODE (DECL_RTL (decl)) != MEM	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)	return;      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);      break;    case TYPE_DECL:      /* Done with tagged types.  */      if (DECL_NAME (decl) == 0)	return;      if (DECL_IGNORED_P (decl))	return;      /* Output typedef name.  */      if (template_name_p (DECL_NAME (decl)))	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));      else	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));      PUT_SDB_SCL (C_TPDEF);      break;    case PARM_DECL:      /* Parm decls go in their own separate chains	 and are output by sdbout_reg_parms and sdbout_parms.  */      abort ();    case VAR_DECL:      /* Don't mention a variable that is external.	 Let the file that defines it describe it.  */      if (DECL_EXTERNAL (decl))	return;      /* Ignore __FUNCTION__, etc.  */      if (DECL_IGNORED_P (decl))	return;      /* If there was an error in the declaration, don't dump core	 if there is no RTL associated with the variable doesn't	 exist.  */      if (DECL_RTL (decl) == 0)	return;      DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);#ifdef LEAF_REG_REMAP      if (leaf_function)	leaf_renumber_regs_insn (DECL_RTL (decl));#endif      value = DECL_RTL (decl);      /* Don't mention a variable at all	 if it was completely optimized into nothingness.	 If DECL was from an inline function, then its rtl	 is not identically the rtl that was used in this	 particular compilation.  */      if (GET_CODE (value) == REG)	{	  regno = REGNO (DECL_RTL (decl));	  if (regno >= FIRST_PSEUDO_REGISTER)	    return;	}      else if (GET_CODE (value) == SUBREG)	{	  int offset = 0;	  while (GET_CODE (value) == SUBREG)	    {	      offset += SUBREG_WORD (value);	      value = SUBREG_REG (value);	    }	  if (GET_CODE (value) == REG)	    {	      regno = REGNO (value);	      if (regno >= FIRST_PSEUDO_REGISTER)		return;	      regno += offset;	    }	  alter_subreg (DECL_RTL (decl));	  value = DECL_RTL (decl);	}      /* Don't output anything if an auto variable	 gets RTL that is static.	 GAS version 2.2 can't handle such output.  */      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))	       && ! TREE_STATIC (decl))	return;      /* Emit any structure, union, or enum type that has not been output.	 This occurs for tag-less structs (et al) used to declare variables	 within functions.  */      if (TREE_CODE (type) == ENUMERAL_TYPE	  || TREE_CODE (type) == RECORD_TYPE	  || TREE_CODE (type) == UNION_TYPE	  || TREE_CODE (type) == QUAL_UNION_TYPE)	{	  if (TYPE_SIZE (type) != 0		/* not a forward reference */	      && KNOWN_TYPE_TAG (type) == 0)	/* not yet declared */	    sdbout_one_type (type);	}      /* Defer SDB information for top-level initialized variables! */      if (! local	  && GET_CODE (value) == MEM	  && DECL_INITIAL (decl))	return;      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.	 For now, avoid crashing.  */      if (DECL_NAME (decl) == NULL_TREE)	return;      /* Record the name for, starting a symtab entry.  */      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));      if (GET_CODE (value) == MEM	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)	{	  PUT_SDB_DEF (name);	  if (TREE_PUBLIC (decl))	    {	      PUT_SDB_VAL (XEXP (value, 0));              PUT_SDB_SCL (C_EXT);	    }	  else	    {	      PUT_SDB_VAL (XEXP (value, 0));              PUT_SDB_SCL (C_STAT);	    }	}      else if (regno >= 0)	{	  PUT_SDB_DEF (name);	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));	  PUT_SDB_SCL (C_REG);	}      else if (GET_CODE (value) == MEM	       && (GET_CODE (XEXP (value, 0)) == MEM		   || (GET_CODE (XEXP (value, 0)) == REG		       && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM		       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))	/* If the value is indirect by memory or by a register	   that isn't the frame pointer	   then it means the object is variable-sized and address through	   that register or stack slot.  COFF has no way to represent this	   so all we can do is output the variable as a pointer.  */	{	  PUT_SDB_DEF (name);	  if (GET_CODE (XEXP (value, 0)) == REG)	    {	      PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));	      PUT_SDB_SCL (C_REG);	    }	  else	    {	      /* DECL_RTL looks like (MEM (MEM (PLUS (REG...)		 (CONST_INT...)))).		 We want the value of that CONST_INT.  */	      /* Encore compiler hates a newline in a macro arg, it seems.  */	      PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET			       (XEXP (XEXP (value, 0), 0)));	      PUT_SDB_SCL (C_AUTO);	    }	  type = build_pointer_type (TREE_TYPE (decl));	}      else if (GET_CODE (value) == MEM	       && ((GET_CODE (XEXP (value, 0)) == PLUS		    && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG		    && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)		   /* This is for variables which are at offset zero from		      the frame pointer.  This happens on the Alpha.		      Non-frame pointer registers are excluded above.  */		   || (GET_CODE (XEXP (value, 0)) == REG)))	{	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))	     or (MEM (REG...)).  We want the value of that CONST_INT	     or zero.  */	  PUT_SDB_DEF (name);	  PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));	  PUT_SDB_SCL (C_AUTO);	}      else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST)	{	  /* Handle an obscure case which can arise when optimizing and	     when there are few available registers.  (This is *always*	     the case for i386/i486 targets).  The DECL_RTL looks like	     (MEM (CONST ...)) even though this variable is a local `auto'	     or a local `register' variable.  In effect, what has happened	     is that the reload pass has seen that all assignments and	     references for one such a local variable can be replaced by	     equivalent assignments and references to some static storage	     variable, thereby avoiding the need for a register.  In such	     cases we're forced to lie to debuggers and tell them that	     this variable was itself `static'.  */	  PUT_SDB_DEF (name);	  PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));	  PUT_SDB_SCL (C_STAT);	}      else	{	  /* It is something we don't know how to represent for SDB.  */	  return;	}      break;    }  PUT_SDB_TYPE (plain_type (type));  PUT_SDB_ENDEF;}/* Output SDB information for a top-level initialized variable   that has been delayed.  */voidsdbout_toplevel_data (decl)     tree decl;{  tree type = TREE_TYPE (decl);  if (DECL_IGNORED_P (decl))    return;  if (! (TREE_CODE (decl) == VAR_DECL	 && GET_CODE (DECL_RTL (decl)) == MEM	 && DECL_INITIAL (decl)))    abort ();  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));  PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));  if (TREE_PUBLIC (decl))    {      PUT_SDB_SCL (C_EXT);    }  else    {      PUT_SDB_SCL (C_STAT);    }  PUT_SDB_TYPE (plain_type (type));  PUT_SDB_ENDEF;}#ifdef SDB_ALLOW_FORWARD_REFERENCES/* Machinery to record and output anonymous types. */static tree anonymous_types;static voidsdbout_queue_anonymous_type (type)     tree type;{  anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);}static voidsdbout_dequeue_anonymous_types (){  register tree types, link;  while (anonymous_types)    {      types = nreverse (anonymous_types);      anonymous_types = NULL_TREE;      for (link = types; link; link = TREE_CHAIN (link))	{	  register tree type = TREE_VALUE (link);	  if (type && ! TREE_ASM_WRITTEN (type))	    sdbout_one_type (type);	}    }}#endif/* Given a chain of ..._TYPE nodes, all of which have names,   output definitions of those names, as typedefs.  */voidsdbout_types (types)     register tree types;{  register tree link;  for (link = types; link; link = TREE_CHAIN (link))    sdbout_one_type (link);#ifdef SDB_ALLOW_FORWARD_REFERENCES  sdbout_dequeue_anonymous_types ();#endif}static voidsdbout_type (type)     tree type;{  if (type == error_mark_node)    type = integer_type_node;  PUT_SDB_TYPE (plain_type (type));}/* Output types of the fields of type TYPE, if they are structs.   Formerly did not chase through pointer types, since that could be circular.   They must come before TYPE, since forward refs are not allowed.   Now james@bigtex.cactus.org says to try them.  */static voidsdbout_field_types (type)     tree type;{  tree tail;  for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))    if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)      sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));    else      sdbout_one_type (TREE_TYPE (tail));}/* Use this to put out the top level defined record and union types   for later reference.  If this is a struct with a name, then put that   name out.  Other unnamed structs will have .xxfake labels generated so   that they may be referred to later.   The label will be stored in the KNOWN_TYPE_TAG slot of a type.   It may NOT be called recursively.  */static voidsdbout_one_type (type)     tree type;{  if (current_function_decl != NULL_TREE      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)    ; /* Don't change section amid function.  */  else    text_section ();

⌨️ 快捷键说明

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