dbxout.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,183 行 · 第 1/5 页

C
2,183
字号
		 int_size_in_bytes (type));	if (use_gnu_debug_info_extensions)	  {	    if (n_baseclasses)	      {		have_used_extensions = 1;		fprintf (asmfile, "!%d,", n_baseclasses);		CHARS (8);	      }	  }	for (i = 0; i < n_baseclasses; i++)	  {	    tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);	    if (use_gnu_debug_info_extensions)	      {		have_used_extensions = 1;		putc (TREE_VIA_VIRTUAL (child) ? '1'		      : '0',		      asmfile);		putc (TREE_VIA_PUBLIC (child) ? '2'		      : '0',		      asmfile);		fprintf (asmfile, "%d,",			 TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT);		CHARS (15);		dbxout_type (BINFO_TYPE (child), 0, 0);		putc (';', asmfile);	      }	    else	      {		/* Print out the base class information with fields		   which have the same names at the types they hold.  */		dbxout_type_name (BINFO_TYPE (child));		putc (':', asmfile);		dbxout_type (BINFO_TYPE (child), full, 0);		fprintf (asmfile, ",%d,%d;",			 TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT,			 TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT);		CHARS (20);	      }	  }      }      CHARS (11);      /* Write out the field declarations.  */      dbxout_type_fields (type);      if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)	{	  have_used_extensions = 1;	  dbxout_type_methods (type);	}      putc (';', asmfile);      if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE	  /* Avoid the ~ if we don't really need it--it confuses dbx.  */	  && TYPE_VFIELD (type))	{	  have_used_extensions = 1;	  /* Tell GDB+ that it may keep reading.  */	  putc ('~', asmfile);	  /* We need to write out info about what field this class	     uses as its "main" vtable pointer field, because if this	     field is inherited from a base class, GDB cannot necessarily	     figure out which field it's using in time.  */	  if (TYPE_VFIELD (type))	    {	      putc ('%', asmfile);	      dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0, 0);	    }	  putc (';', asmfile);	  CHARS (3);	}      break;    case ENUMERAL_TYPE:      /* We must use the same test here as we use in the DBX_NO_XREFS case	 above.  We simplify it a bit since an enum will never have a variable	 size.  */      if ((TYPE_NAME (type) != 0	   && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL		 && DECL_IGNORED_P (TYPE_NAME (type)))	   && !full)	  || TYPE_SIZE (type) == 0)	{	  fprintf (asmfile, "xe");	  CHARS (3);	  dbxout_type_name (type);	  typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;	  fprintf (asmfile, ":");	  return;	}#ifdef DBX_OUTPUT_ENUM      DBX_OUTPUT_ENUM (asmfile, type);#else      if (use_gnu_debug_info_extensions	  && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))	fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));      putc ('e', asmfile);      CHARS (1);      for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))	{	  fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem)));	  if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0)	    fprintf (asmfile, "%lu",		     (unsigned long) TREE_INT_CST_LOW (TREE_VALUE (tem)));	  else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1		   && TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)	    fprintf (asmfile, "%ld",		     (long) TREE_INT_CST_LOW (TREE_VALUE (tem)));	  else	    print_int_cst_octal (TREE_VALUE (tem));	  fprintf (asmfile, ",");	  CHARS (20 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem)));	  if (TREE_CHAIN (tem) != 0)	    CONTIN;	}      putc (';', asmfile);      CHARS (1);#endif      break;    case POINTER_TYPE:      putc ('*', asmfile);      CHARS (1);      dbxout_type (TREE_TYPE (type), 0, 0);      break;    case METHOD_TYPE:      if (use_gnu_debug_info_extensions)	{	  have_used_extensions = 1;	  putc ('#', asmfile);	  CHARS (1);	  if (flag_minimal_debug && !show_arg_types)	    {	      /* Normally, just output the return type.		 The argument types are encoded in the method name.  */	      putc ('#', asmfile);	      CHARS (1);	      dbxout_type (TREE_TYPE (type), 0, 0);	      putc (';', asmfile);	      CHARS (1);	    }	  else	    {	      /* When outputting destructors, we need to write		 the argument types out longhand.  */	      dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0);	      putc (',', asmfile);	      CHARS (1);	      dbxout_type (TREE_TYPE (type), 0, 0);	      dbxout_args (TYPE_ARG_TYPES (type));	      putc (';', asmfile);	      CHARS (1);	    }	}      else	{	  /* Treat it as a function type.  */	  dbxout_type (TREE_TYPE (type), 0, 0);	}      break;    case OFFSET_TYPE:      if (use_gnu_debug_info_extensions)	{	  have_used_extensions = 1;	  putc ('@', asmfile);	  CHARS (1);	  dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0);	  putc (',', asmfile);	  CHARS (1);	  dbxout_type (TREE_TYPE (type), 0, 0);	}      else	{	  /* Should print as an int, because it is really	     just an offset.  */	  dbxout_type (integer_type_node, 0, 0);	}      break;    case REFERENCE_TYPE:      if (use_gnu_debug_info_extensions)	have_used_extensions = 1;      putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile);      CHARS (1);      dbxout_type (TREE_TYPE (type), 0, 0);      break;    case FUNCTION_TYPE:      putc ('f', asmfile);      CHARS (1);      dbxout_type (TREE_TYPE (type), 0, 0);      break;    default:      abort ();    }}/* Print the value of integer constant C, in octal,   handling double precision.  */static voidprint_int_cst_octal (c)     tree c;{  unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c);  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c);  int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3));  int width = TYPE_PRECISION (TREE_TYPE (c));  /* GDB wants constants with no extra leading "1" bits, so     we need to remove any sign-extension that might be     present.  */  if (width == HOST_BITS_PER_WIDE_INT * 2)    ;  else if (width > HOST_BITS_PER_WIDE_INT)    high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);  else if (width == HOST_BITS_PER_WIDE_INT)    high = 0;  else    high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);  fprintf (asmfile, "0");  if (excess == 3)    {      print_octal (high, HOST_BITS_PER_WIDE_INT / 3);      print_octal (low, HOST_BITS_PER_WIDE_INT / 3);    }  else    {      unsigned HOST_WIDE_INT beg = high >> excess;      unsigned HOST_WIDE_INT middle	= ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess)	   | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3)));      unsigned HOST_WIDE_INT end	= low & (((unsigned HOST_WIDE_INT) 1		  << (HOST_BITS_PER_WIDE_INT / 3 * 3))		 - 1);      fprintf (asmfile, "%o%01o", beg, middle);      print_octal (end, HOST_BITS_PER_WIDE_INT / 3);    }}static voidprint_octal (value, digits)     unsigned HOST_WIDE_INT value;     int digits;{  int i;  for (i = digits - 1; i >= 0; i--)    fprintf (asmfile, "%01o", ((value >> (3 * i)) & 7));}/* Output the name of type TYPE, with no punctuation.   Such names can be set up either by typedef declarations   or by struct, enum and union tags.  */static voiddbxout_type_name (type)     register tree type;{  tree t;  if (TYPE_NAME (type) == 0)    abort ();  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)    {      t = TYPE_NAME (type);    }  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)    {      t = DECL_NAME (TYPE_NAME (type));    }  else    abort ();  fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));  CHARS (IDENTIFIER_LENGTH (t));}/* Output a .stabs for the symbol defined by DECL,   which must be a ..._DECL node in the normal namespace.   It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.   LOCAL is nonzero if the scope is less than the entire file.  */voiddbxout_symbol (decl, local)     tree decl;     int local;{  tree type = TREE_TYPE (decl);  tree context = NULL_TREE;  /* Cast avoids warning in old compilers.  */  current_sym_code = (STAB_CODE_TYPE) 0;  current_sym_value = 0;  current_sym_addr = 0;  /* Ignore nameless syms, but don't ignore type tags.  */  if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)      || DECL_IGNORED_P (decl))    return;  dbxout_prepare_symbol (decl);  /* The output will always start with the symbol name,     so always count that in the length-output-so-far.  */  if (DECL_NAME (decl) != 0)    current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (decl));  switch (TREE_CODE (decl))    {    case CONST_DECL:      /* Enum values are defined by defining the enum type.  */      break;    case FUNCTION_DECL:      if (DECL_RTL (decl) == 0)	return;      if (DECL_EXTERNAL (decl))	break;      /* Don't mention a nested function under its parent.  */      context = decl_function_context (decl);      if (context == current_function_decl)	break;      if (GET_CODE (DECL_RTL (decl)) != MEM	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)	break;      FORCE_TEXT;      fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),	       TREE_PUBLIC (decl) ? 'F' : 'f');      current_sym_code = N_FUN;      current_sym_addr = XEXP (DECL_RTL (decl), 0);      if (TREE_TYPE (type))	dbxout_type (TREE_TYPE (type), 0, 0);      else	dbxout_type (void_type_node, 0, 0);      /* For a nested function, when that function is compiled,	 mention the containing function name	 as well as (since dbx wants it) our own assembler-name.  */      if (context != 0)	fprintf (asmfile, ",%s,%s",		 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),		 IDENTIFIER_POINTER (DECL_NAME (context)));      dbxout_finish_symbol (decl);      break;    case TYPE_DECL:#if 0      /* This seems all wrong.  Outputting most kinds of types gives no name	 at all.  A true definition gives no name; a cross-ref for a	 structure can give the tag name, but not a type name.	 It seems that no typedef name is defined by outputting a type.  */      /* If this typedef name was defined by outputting the type,	 don't duplicate it.  */      if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED	  && TYPE_NAME (TREE_TYPE (decl)) == decl)	return;#endif      /* Don't output the same typedef twice.         And don't output what language-specific stuff doesn't want output.  */      if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))	return;      FORCE_TEXT;      {	int tag_needed = 1;	int did_output = 0;	if (DECL_NAME (decl))	  {	    /* Nonzero means we must output a tag as well as a typedef.  */	    tag_needed = 0;	    /* Handle the case of a C++ structure or union	       where the TYPE_NAME is a TYPE_DECL	       which gives both a typedef name and a tag.  */	    /* dbx requires the tag first and the typedef second.  */	    if ((TREE_CODE (type) == RECORD_TYPE		 || TREE_CODE (type) == UNION_TYPE		 || TREE_CODE (type) == QUAL_UNION_TYPE)		&& TYPE_NAME (type) == decl		&& !(use_gnu_debug_info_extensions && have_used_extensions)		&& !TREE_ASM_WRITTEN (TYPE_NAME (type))		/* Distinguish the implicit typedefs of C++		   from explicit ones that might be found in C.  */                && DECL_ARTIFICIAL (decl))	      {		tree name = TYPE_NAME (type);		if (TREE_CODE (name) == TYPE_DECL)		  name = DECL_NAME (name);		current_sym_code = DBX_TYPE_DECL_STABS_CODE;		current_sym_value = 0;		current_sym_addr = 0;		current_sym_nchars = 2 + IDENTIFIER_LENGTH (name);		fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP,			 IDENTIFIER_POINTER (name));		dbxout_type (type, 1, 0);		dbxout_finish_symbol (NULL_TREE);	      }	    /* Output typedef name.  */	    fprintf (asmfile, "%s \"%s:", ASM_STABS_OP,		     IDENTIFIER_POINTER (DECL_NAME (decl)));	    /* Short cut way to output a tag also.  */	    if ((TREE_CODE (type) == RECORD_TYPE		 || TREE_CODE (type) == UNION_TYPE		 || TREE_CODE (type) == QUAL_UNION_TYPE)		&& TYPE_NAME (type) == decl		/* Distinguish the implicit typedefs of C++		   from explicit ones that might be found in C.  */                && DECL_ARTIFICIAL (decl))	      {		if (use_gnu_debug_info_extensions && have_used_extensions)		  {

⌨️ 快捷键说明

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