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

📄 sdbout.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    }}/* Call sdbout_symbol on each decl in the chain SYMS.  */static voidsdbout_syms (syms)     tree syms;{  while (syms)    {      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   except at the end of compilation when we really want those symbols   to be output.  In the case of a variable, we do not really output   the variable if LOCAL is 0.  */voidsdbout_symbol (decl, local)     tree decl;     int local;{  int letter = 0;  tree type = TREE_TYPE (decl);  rtx value;  /* If global, first output all types and all     struct, enum and union tags that have been created     and not yet output.  */  if (local == 0)    {      sdbout_tags (gettags ());      sdbout_types (nreverse (get_permanent_types ()));    }#ifdef SDB_NO_FORWARD_REFS  sdbout_one_type (type);#endif  switch (TREE_CODE (decl))    {    case CONST_DECL:      /* Enum values are defined by defining the enum type.  */      return;    case FUNCTION_DECL:      if (TREE_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_NAME (decl)));      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);      break;    case TYPE_DECL:      /* Output typedef name.  */      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 (TREE_EXTERNAL (decl))	return;      /* Don't outpuit a file-scope variable where it is defined.	 At the end of compilation, this function is called once again	 for those variable, but this time with LOCAL nonzero.	 This is because COFF requires all file-scope variables	 to follow all typedefs.  We satisfy this requirement	 by putting all file-scope variables at the end.  */      if (!local)	return;      value = DECL_RTL (decl);      /* Don't mention a variable at all	 if it was completely optimized into nothingness.  */      if (GET_CODE (value) == REG	  && (REGNO (value) < 0	      || REGNO (value) >= FIRST_PSEUDO_REGISTER))	return;      /* Ok, start a symtab entry and output the variable name.  */      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));      if (GET_CODE (value) == MEM	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)	{	  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 (GET_CODE (value) == REG)	{	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (value)));	  PUT_SDB_SCL (C_REG);	}      else if (GET_CODE (value) == SUBREG)	{	  int offset = 0;	  while (GET_CODE (value) == SUBREG)	    {	      offset += SUBREG_WORD (value);	      value = SUBREG_REG (value);	    }	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (value) + offset));	  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)) != FRAME_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.  DBX has no way to represent this	   so all we can do is output the variable as a pointer.  */	{	  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 (INTVAL (XEXP (XEXP (XEXP (value, 0), 0), 1)));	      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)	{	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))).	     We want the value of that CONST_INT.  */	  PUT_SDB_INT_VAL (INTVAL (XEXP (XEXP (value, 0), 1)));	  PUT_SDB_SCL (C_AUTO);	}      else	{	  /* It is something we don't know how to represent for SDB.  */	}      break;    }  PUT_SDB_TYPE (plain_type (type));  PUT_SDB_ENDEF;}/* Given a list of TREE_LIST nodes that point at types,   output those types for SDB.   We must check to include those that have been mentioned already with   only a cross-reference.  */voidsdbout_tags (tags)     tree tags;{  register tree link;  for (link = tags; link; link = TREE_CHAIN (link))    {      register tree type = TREE_VALUE (link);      if (TREE_PURPOSE (link) != 0	  && TYPE_SIZE (type) != 0)	sdbout_one_type (type);    }}/* 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);}static voidsdbout_type (type)     tree type;{  register tree tem;  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))    {#ifdef SDB_NO_FORWARD_REFS      if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)	sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));      else#endif	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;{  text_section ();  switch (TREE_CODE (type))    {    case RECORD_TYPE:    case UNION_TYPE:    case ENUMERAL_TYPE:      type = TYPE_MAIN_VARIANT (type);      /* Don't output a type twice.  */      if (TREE_ASM_WRITTEN (type))	return;      /* Output nothing if type is not yet defined.  */      if (TYPE_SIZE (type) == 0)	return;      TREE_ASM_WRITTEN (type) = 1;#ifdef SDB_NO_FORWARD_REFS      /* Before really doing anything, output types we want to refer to.  */      if (TREE_CODE (type) != ENUMERAL_TYPE)	sdbout_field_types (type);#endif      sdbout_record_type_name (type);      /* Output a structure type.  */      {	int size = int_size_in_bytes (type);	int member_scl;	tree tem;	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));	switch (TREE_CODE (type))	  {	  case UNION_TYPE:	    PUT_SDB_SCL (C_UNTAG);	    PUT_SDB_TYPE (T_UNION);	    member_scl = C_MOU;	    break;	  case RECORD_TYPE:	    PUT_SDB_SCL (C_STRTAG);	    PUT_SDB_TYPE (T_STRUCT);	    member_scl = C_MOS;	    break;	  case ENUMERAL_TYPE:	    PUT_SDB_SCL (C_ENTAG);	    PUT_SDB_TYPE (T_ENUM);	    member_scl = C_MOE;	    break;	  }	PUT_SDB_SIZE (size);	PUT_SDB_ENDEF;	/* output the individual fields */	if (TREE_CODE (type) == ENUMERAL_TYPE)	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))	    {	      PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));	      PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem)));	      PUT_SDB_SCL (C_MOE);	      PUT_SDB_TYPE (T_MOE);	      PUT_SDB_ENDEF;	    }      	else			/* record or union type */	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))	    /* Output the name, type, position (in bits), size (in bits)	       of each field.  */	    /* Omit here the nameless fields that are used to skip bits.  */	    if (DECL_NAME (tem) != 0)	      {		CONTIN;		PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (tem)));		if (TREE_PACKED (tem))		  {		    PUT_SDB_INT_VAL (DECL_OFFSET (tem));		    PUT_SDB_SCL (C_FIELD);		    sdbout_type (TREE_TYPE (tem));		    PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem))				  * DECL_SIZE_UNIT (tem));		  }		else		  {		    PUT_SDB_INT_VAL (DECL_OFFSET (tem) / BITS_PER_UNIT);		    PUT_SDB_SCL (member_scl);		    sdbout_type (TREE_TYPE (tem));		  }		PUT_SDB_ENDEF;	      }	/* output end of a structure,union, or enumeral definition */   	PUT_SDB_PLAIN_DEF ("eos");	PUT_SDB_INT_VAL (size);	PUT_SDB_SCL (C_EOS);	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));	PUT_SDB_SIZE (size);	PUT_SDB_ENDEF;	break;      }    }}/* Output definitions of all parameters, referring when possible to the   place where the parameters were passed rather than the copies used   within the function.     This is done as part of starting the function.   PARMS is a chain of PARM_DECL nodes.  */static voidsdbout_parms (parms1)     tree parms1;{  tree type;  tree parms;  for (parms = parms1; parms; parms = TREE_CHAIN (parms))    {      int current_sym_value = DECL_OFFSET (parms) / BITS_PER_UNIT;      if (DECL_NAME (parms))	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (parms)));      else	PUT_SDB_DEF (gen_fake_label ());      if (GET_CODE (DECL_RTL (parms)) == REG	  && REGNO (DECL_RTL (parms)) >= 0	  && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)	type = DECL_ARG_TYPE (parms);      else	{	  /* This is the case where the parm is passed as an int or double	     and it is converted to a char, short or float and stored back	     in the parmlist.  In this case, describe the parm	     with the variable's declared type, and adjust the address	     if the least significant bytes (which we are using) are not	     the first ones.  */#ifdef BYTES_BIG_ENDIAN	  if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))	    current_sym_value +=	      (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))	       - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif	  if (GET_CODE (DECL_RTL (parms)) == MEM	      && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS	      && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT	      && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))		  == current_sym_value))	    type = TREE_TYPE (parms);	  else	    {	      current_sym_value = DECL_OFFSET (parms) / BITS_PER_UNIT;	      type = DECL_ARG_TYPE (parms);	    }	}           PUT_SDB_INT_VAL (current_sym_value);      PUT_SDB_SCL (C_ARG);      PUT_SDB_TYPE (plain_type (type));      PUT_SDB_ENDEF;    }}/* Output definitions, referring to registers,   of all the parms in PARMS which are stored in registers during the function.   PARMS is a chain of PARM_DECL nodes.   This is done as part of starting the function.  */static voidsdbout_reg_parms (parms)     tree parms;{  while (parms)    {      if (GET_CODE (DECL_RTL (parms)) == REG	  && REGNO (DECL_RTL (parms)) >= 0	  && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)	{	  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (parms)));	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));  	  PUT_SDB_SCL (C_REG);	  PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));	  PUT_SDB_ENDEF;	}      else if (GET_CODE (DECL_RTL (parms)) == MEM	       && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS	       && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT)	{	  int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;	  /* A parm declared char is really passed as an int,	     so it occupies the least significant bytes.	     On a big-endian machine those are not the low-numbered ones.  */#ifdef BYTES_BIG_ENDIAN	  if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))	    offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))		       - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif	  if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset)	    {	      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (parms)));	      	      PUT_SDB_INT_VAL (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)));	      PUT_SDB_SCL (C_AUTO);	      PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));	      PUT_SDB_ENDEF;	    }	}      parms = TREE_CHAIN (parms);    }}/* Describe the beginning of an internal block within a function.   Also output descriptions of variables defined in this block.   N is the number of the block, by order of beginning, counting from 1,   and not counting the outermost (function top-level) block.   The blocks match the LET_STMTS in DECL_INITIAL (current_function_decl),   if the count starts at 0 for the outermost one.  */voidsdbout_begin_block (file, line, n)     FILE *file;     int line;     int n;{  tree decl = current_function_decl;  MAKE_LINE_SAFE (line);  PUT_SDB_BLOCK_START (line - sdb_begin_function_line);  if (n == 1)    {      /* Include the outermost LET_STMT's variables in block 1.  */      next_block_number = 0;      do_block = 0;      sdbout_block (DECL_INITIAL (decl));    }  next_block_number = 0;  do_block = n;  sdbout_block (DECL_INITIAL (decl));}/* Describe the end line-number of an internal block within a function.  */	 voidsdbout_end_block (file, line)     FILE *file;     int line;{  MAKE_LINE_SAFE (line);  PUT_SDB_BLOCK_END (line - sdb_begin_function_line);}/* Output sdb info for the current function name.   Called from assemble_function.  */voidsdbout_mark_begin_function (){  sdbout_symbol (current_function_decl, 0);}/* Called at beginning of function body (after prologue).   Record the function's starting line number, so we can output   relative line numbers for the other lines.   Describe beginning of outermost block.   Also describe the parameter list.  */voidsdbout_begin_function (line)     int line;{  sdb_begin_function_line = line - 1;  PUT_SDB_FUNCTION_START (line);  sdbout_parms (DECL_ARGUMENTS (current_function_decl));  sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));}/* Called at end of function (before epilogue).   Describe end of outermost block.  */voidsdbout_end_function (line)     int line;{  MAKE_LINE_SAFE (line);  PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);  /* Indicate we are between functions, for line-number output.  */  sdb_begin_function_line = -1;}/* Output sdb info for the absolute end of a function.   Called after the epilogue is output.  */voidsdbout_end_epilogue (){  char *name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));  PUT_SDB_EPILOGUE_END (name);}#endif /* SDB_DEBUGGING_INFO */

⌨️ 快捷键说明

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