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

📄 dwarfout.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   UID number.	*/static voidequate_decl_number_to_die_number (decl)     register tree decl;{  /* In the case where we are generating a DIE for some ..._DECL node     which represents either some inline function declaration or some     entity declared within an inline function declaration/definition,     setup a symbolic name for the current DIE so that we have a name     for this DIE that we can easily refer to later on within     AT_abstract_origin attributes.  */  char decl_label[MAX_ARTIFICIAL_LABEL_BYTES];  char die_label[MAX_ARTIFICIAL_LABEL_BYTES];  sprintf (decl_label, DECL_NAME_FMT, DECL_UID (decl));  sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);  ASM_OUTPUT_DEF (asm_out_file, decl_label, die_label);}/* Given a pointer to some ..._TYPE tree node, generate an assembly language   equate directive which will associate a symbolic name with the current DIE.   The name used is an artificial label generated from the TYPE_UID number   associated with the given type node.  The name it gets equated to is the   symbolic label that we (previously) output at the start of the DIE that   we are currently generating.   Calling this function while generating some "type related" form of DIE   makes it easy to later refer to the DIE which represents the given type   simply by re-generating the alternative name from the ..._TYPE node's   UID number.	*/static inline voidequate_type_number_to_die_number (type)     register tree type;{  char type_label[MAX_ARTIFICIAL_LABEL_BYTES];  char die_label[MAX_ARTIFICIAL_LABEL_BYTES];  /* We are generating a DIE to represent the main variant of this type     (i.e the type without any const or volatile qualifiers) so in order     to get the equate to come out right, we need to get the main variant     itself here.  */  type = type_main_variant (type);  sprintf (type_label, TYPE_NAME_FMT, TYPE_UID (type));  sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);  ASM_OUTPUT_DEF (asm_out_file, type_label, die_label);}static voidoutput_reg_number (rtl)     register rtx rtl;{  register unsigned regno = REGNO (rtl);  if (regno >= FIRST_PSEUDO_REGISTER)    {      warning_with_decl (dwarf_last_decl, "internal regno botch: regno = %d\n",			 regno);      regno = 0;    }  fprintf (asm_out_file, "\t%s\t0x%x",	   UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));  if (flag_debug_asm)    {      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);      PRINT_REG (rtl, 0, asm_out_file);    }  fputc ('\n', asm_out_file);}/* The following routine is a nice and simple transducer.  It converts the   RTL for a variable or parameter (resident in memory) into an equivalent   Dwarf representation of a mechanism for getting the address of that same   variable onto the top of a hypothetical "address evaluation" stack.   When creating memory location descriptors, we are effectively trans-   forming the RTL for a memory-resident object into its Dwarf postfix   expression equivalent.  This routine just recursively descends an   RTL tree, turning it into Dwarf postfix code as it goes.  */static voidoutput_mem_loc_descriptor (rtl)      register rtx rtl;{  /* Note that for a dynamically sized array, the location we will     generate a description of here will be the lowest numbered location     which is actually within the array.  That's *not* necessarily the     same as the zeroth element of the array.  */  switch (GET_CODE (rtl))    {      case SUBREG:	/* The case of a subreg may arise when we have a local (register)	   variable or a formal (register) parameter which doesn't quite	   fill up an entire register.	For now, just assume that it is	   legitimate to make the Dwarf info refer to the whole register	   which contains the given subreg.  */	rtl = XEXP (rtl, 0);	/* Drop thru.  */      case REG:	/* Whenever a register number forms a part of the description of	   the method for calculating the (dynamic) address of a memory	   resident object, DWARF rules require the register number to	   be referred to as a "base register".  This distinction is not	   based in any way upon what category of register the hardware	   believes the given register belongs to.  This is strictly	   DWARF terminology we're dealing with here.	   Note that in cases where the location of a memory-resident data	   object could be expressed as:		    OP_ADD (OP_BASEREG (basereg), OP_CONST (0))	   the actual DWARF location descriptor that we generate may just	   be OP_BASEREG (basereg).  This may look deceptively like the	   object in question was allocated to a register (rather than	   in memory) so DWARF consumers need to be aware of the subtle	   distinction between OP_REG and OP_BASEREG.  */	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG);	output_reg_number (rtl);	break;      case MEM:	output_mem_loc_descriptor (XEXP (rtl, 0));	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_DEREF4);	break;      case CONST:      case SYMBOL_REF:	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADDR);	ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, rtl);	break;      case PLUS:	output_mem_loc_descriptor (XEXP (rtl, 0));	output_mem_loc_descriptor (XEXP (rtl, 1));	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD);	break;      case CONST_INT:	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);	ASM_OUTPUT_DWARF_DATA4 (asm_out_file, INTVAL (rtl));	break;      case MULT:	/* If a pseudo-reg is optimized away, it is possible for it to	   be replaced with a MEM containing a multiply.  Use a GNU extension	   to describe it.  */	output_mem_loc_descriptor (XEXP (rtl, 0));	output_mem_loc_descriptor (XEXP (rtl, 1));	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_MULT);	break;      default:	abort ();    }}/* Output a proper Dwarf location descriptor for a variable or parameter   which is either allocated in a register or in a memory location.  For   a register, we just generate an OP_REG and the register number.  For a   memory location we provide a Dwarf postfix expression describing how to   generate the (dynamic) address of the object onto the address stack.  */static voidoutput_loc_descriptor (rtl)     register rtx rtl;{  switch (GET_CODE (rtl))    {    case SUBREG:	/* The case of a subreg may arise when we have a local (register)	   variable or a formal (register) parameter which doesn't quite	   fill up an entire register.	For now, just assume that it is	   legitimate to make the Dwarf info refer to the whole register	   which contains the given subreg.  */	rtl = XEXP (rtl, 0);	/* Drop thru.  */    case REG:	ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG);	output_reg_number (rtl);	break;    case MEM:      output_mem_loc_descriptor (XEXP (rtl, 0));      break;    default:      abort ();		/* Should never happen */    }}/* Given a tree node describing an array bound (either lower or upper)   output a representation for that bound.  */static voidoutput_bound_representation (bound, dim_num, u_or_l)     register tree bound;     register unsigned dim_num; /* For multi-dimensional arrays.  */     register char u_or_l;	/* Designates upper or lower bound.  */{  switch (TREE_CODE (bound))    {    case ERROR_MARK:      return;      /* All fixed-bounds are represented by INTEGER_CST nodes.	 */    case INTEGER_CST:      ASM_OUTPUT_DWARF_DATA4 (asm_out_file,			      (unsigned) TREE_INT_CST_LOW (bound));      break;    default:      /* Dynamic bounds may be represented by NOP_EXPR nodes containing	 SAVE_EXPR nodes, in which case we can do something, or as	 an expression, which we cannot represent.  */      {	char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];	char end_label[MAX_ARTIFICIAL_LABEL_BYTES];	sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,		 current_dienum, dim_num, u_or_l);	sprintf (end_label, BOUND_END_LABEL_FMT,		 current_dienum, dim_num, u_or_l);	ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);	ASM_OUTPUT_LABEL (asm_out_file, begin_label);	/* If optimization is turned on, the SAVE_EXPRs that describe	   how to access the upper bound values are essentially bogus.	   They only describe (at best) how to get at these values at	   the points in the generated code right after they have just	   been computed.  Worse yet, in the typical case, the upper	   bound values will not even *be* computed in the optimized	   code, so these SAVE_EXPRs are entirely bogus.	   In order to compensate for this fact, we check here to see	   if optimization is enabled, and if so, we effectively create	   an empty location description for the (unknown and unknowable)	   upper bound.	   This should not cause too much trouble for existing (stupid?)	   debuggers because they have to deal with empty upper bounds	   location descriptions anyway in order to be able to deal with	   incomplete array types.	   Of course an intelligent debugger (GDB?) should be able to	   comprehend that a missing upper bound specification in a	   array type used for a storage class `auto' local array variable	   indicates that the upper bound is both unknown (at compile-	   time) and unknowable (at run-time) due to optimization. */	if (! optimize)	  {	    while (TREE_CODE (bound) == NOP_EXPR		   || TREE_CODE (bound) == CONVERT_EXPR)	      bound = TREE_OPERAND (bound, 0);	    if (TREE_CODE (bound) == SAVE_EXPR)	      output_loc_descriptor		(eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX, 0));	  }	ASM_OUTPUT_LABEL (asm_out_file, end_label);      }      break;    }}/* Recursive function to output a sequence of value/name pairs for   enumeration constants in reversed order.  This is called from   enumeration_type_die.  */static voidoutput_enumeral_list (link)     register tree link;{  if (link)    {      output_enumeral_list (TREE_CHAIN (link));      ASM_OUTPUT_DWARF_DATA4 (asm_out_file,			      (unsigned) TREE_INT_CST_LOW (TREE_VALUE (link)));      ASM_OUTPUT_DWARF_STRING (asm_out_file,			       IDENTIFIER_POINTER (TREE_PURPOSE (link)));    }}/* Given an unsigned value, round it up to the lowest multiple of `boundary'   which is not less than the value itself.  */static inline unsignedceiling (value, boundary)     register unsigned value;     register unsigned boundary;{  return (((value + boundary - 1) / boundary) * boundary);}/* Given a pointer to what is assumed to be a FIELD_DECL node, return a   pointer to the declared type for the relevant field variable, or return   `integer_type_node' if the given node turns out to be an ERROR_MARK node.  */static inline treefield_type (decl)     register tree decl;{  register tree type;  if (TREE_CODE (decl) == ERROR_MARK)    return integer_type_node;  type = DECL_BIT_FIELD_TYPE (decl);  if (type == NULL)    type = TREE_TYPE (decl);  return type;}/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE   node, return the alignment in bits for the type, or else return   BITS_PER_WORD if the node actually turns out to be an ERROR_MARK node.  */static inline unsignedsimple_type_align_in_bits (type)     register tree type;{  return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;}/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE   node, return the size in bits for the type if it is a constant, or   else return the alignment for the type if the type's size is not   constant, or else return BITS_PER_WORD if the type actually turns out   to be an ERROR_MARK node.  */static inline unsignedsimple_type_size_in_bits (type)     register tree type;{  if (TREE_CODE (type) == ERROR_MARK)    return BITS_PER_WORD;  else    {      register tree type_size_tree = TYPE_SIZE (type);      if (TREE_CODE (type_size_tree) != INTEGER_CST)	return TYPE_ALIGN (type);      return (unsigned) TREE_INT_CST_LOW (type_size_tree);    }}/* Given a pointer to what is assumed to be a FIELD_DECL node, compute and   return the byte offset of the lowest addressed byte of the "containing   object" for the given FIELD_DECL, or return 0 if we are unable to deter-   mine what that offset is, either because the argument turns out to be a   pointer to an ERROR_MARK node, or because the offset is actually variable.   (We can't handle the latter case just yet.)  */static unsignedfield_byte_offset (decl)     register tree decl;{  register unsigned type_align_in_bytes;  register unsigned type_align_in_bits;  register unsigned type_size_in_bits;  register unsigned object_offset_in_align_units;  register unsigned object_offset_in_bits;  register unsigned object_offset_in_bytes;  register tree type;  register tree bitpos_tree;  register tree field_size_tree;  register unsigned bitpos_int;  register unsigned deepest_bitpos;  register unsigned field_size_in_bits;  if (TREE_CODE (decl) == ERROR_MARK)    return 0;  if (TREE_CODE (dec

⌨️ 快捷键说明

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