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

📄 dwarfout.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;      /* Dynamic bounds may be represented by NOP_EXPR nodes containing	 SAVE_EXPR nodes.  */      case NOP_EXPR:	bound = TREE_OPERAND (bound, 0);	/* ... fall thru... */      case SAVE_EXPR:	{	  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 we are working on a bound for a dynamic dimension in C,	     the dynamic dimension in question had better have a static	     (zero) lower bound and a dynamic *upper* bound.  */	  if (u_or_l != 'u')	    abort ();	  /* 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)	    output_loc_descriptor	      (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));	  ASM_OUTPUT_LABEL (asm_out_file, end_label);	}	break;      default:	abort ();    }}/* 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.  */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.  */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.  */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.  */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 (decl) != FIELD_DECL)    abort ();  type = field_type (decl);  bitpos_tree = DECL_FIELD_BITPOS (decl);  field_size_tree = DECL_SIZE (decl);  /* We cannot yet cope with fields whose positions or sizes are variable,     so for now, when we see such things, we simply return 0.  Someday,     we may be able to handle such cases, but it will be damn difficult.  */  if (TREE_CODE (bitpos_tree) != INTEGER_CST)    return 0;  bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree);  if (TREE_CODE (field_size_tree) != INTEGER_CST)    return 0;  field_size_in_bits = (unsigned) TREE_INT_CST_LOW (field_size_tree);  type_size_in_bits = simple_type_size_in_bits (type);  type_align_in_bits = simple_type_align_in_bits (type);  type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT;  /* Note that the GCC front-end doesn't make any attempt to keep track     of the starting bit offset (relative to the start of the containing     structure type) of the hypothetical "containing object" for a bit-     field.  Thus, when computing the byte offset value for the start of     the "containing object" of a bit-field, we must deduce this infor-     mation on our own.     This can be rather tricky to do in some cases.  For example, handling     the following structure type definition when compiling for an i386/i486     target (which only aligns long long's to 32-bit boundaries) can be very     tricky:		struct S {			int		field1;			long long	field2:31;		};     Fortunately, there is a simple rule-of-thumb which can be used in such     cases.  When compiling for an i386/i486, GCC will allocate 8 bytes for     the structure shown above.  It decides to do this based upon one simple     rule for bit-field allocation.  Quite simply, GCC allocates each "con-     taining object" for each bit-field at the first (i.e. lowest addressed)     legitimate alignment boundary (based upon the required minimum alignment     for the declared type of the field) which it can possibly use, subject     to the condition that there is still enough available space remaining     in the containing object (when allocated at the selected point) to     fully accommodate all of the bits of the bit-field itself.     This simple rule makes it obvious why GCC allocates 8 bytes for each     object of the structure type shown above.  When looking for a place to     allocate the "containing object" for `field2', the compiler simply tries     to allocate a 64-bit "containing object" at each successive 32-bit     boundary (starting at zero) until it finds a place to allocate that 64-     bit field such that at least 31 contiguous (and previously unallocated)     bits remain within that selected 64 bit field.  (As it turns out, for     the example above, the compiler finds that it is OK to allocate the     "containing object" 64-bit field at bit-offset zero within the     structure type.)     Here we attempt to work backwards from the limited set of facts we're     given, and we try to deduce from those facts, where GCC must have     believed that the containing object started (within the structure type).     The value we deduce is then used (by the callers of this routine) to     generate AT_location and AT_bit_offset attributes for fields (both     bit-fields and, in the case of AT_location, regular fields as well).  */  /* Figure out the bit-distance from the start of the structure to the     "deepest" bit of the bit-field.  */  deepest_bitpos = bitpos_int + field_size_in_bits;  /* This is the tricky part.  Use some fancy footwork to deduce where the     lowest addressed bit of the containing object must be.  */  object_offset_in_bits    = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;  /* Compute the offset of the containing object in "alignment units".  */  object_offset_in_align_units = object_offset_in_bits / type_align_in_bits;  /* Compute the offset of the containing object in bytes.  */  object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes;  return object_offset_in_bytes;}/****************************** attributes *********************************//* The following routines are responsible for writing out the various types   of Dwarf attributes (and any following data bytes associated with them).   These routines are listed in order based on the numerical codes of their   associated attributes.  *//* Generate an AT_sibling attribute.  */inline voidsibling_attribute (){  char label[MAX_ARTIFICIAL_LABEL_BYTES];  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_sibling);  sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);  ASM_OUTPUT_DWARF_REF (asm_out_file, label);}/* Output the form of location attributes suitable for whole variables and   whole parameters.  Note that the location attributes for struct fields   are generated by the routine `data_member_location_attribute' below.  */static voidlocation_attribute (rtl)     register rtx rtl;{  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);  sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);  sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);  ASM_OUTPUT_LABEL (asm_out_file, begin_label);  /* Handle a special case.  If we are about to output a location descriptor     for a variable or parameter which has been optimized out of existence,     don't do that.  Instead we output a zero-length location descriptor     value as part of the location attribute.     A variable which has been optimized out of existence will have a     DECL_RTL value which denotes a pseudo-reg.     Currently, in some rare cases, variables can have DECL_RTL values     which look like (MEM (REG pseudo-reg#)).  These cases are due to     bugs elsewhere in the compiler.  We treat such cases     as if the variable(s) in question had been optimized out of existence.     Note that in all cases where we wish to express the fact that a     variable has been optimized out of existence, we do not simply     suppress the generation of the entire location attribute because     the absence of a location attribute in certain kinds of DIEs is     used to indicate something else entirely... i.e. that the DIE     represents an object declaration, but not a definition.  So saith     the PLSIG.  */  if (! is_pseudo_reg (rtl)      && (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))    output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX));  ASM_OUTPUT_LABEL (asm_out_file, end_label);}/* Output the specialized form of location attribute used for data members   of struct and union types.   In the special case of a FIELD_DECL node which represents a bit-field,   the "offset" part of this special location descriptor must indicate the   distance in bytes from the lowest-addressed byte of the containing   struct or union type to the lowest-addressed byte of the "containing   object" for the bit-field.  (See the `field_byte_offset' function above.)   For any given bit-field, the "containing object" is a hypothetical   object (of some integral or enum type) within which the given bit-field   lives.  The type of this hypothetical "containing object" is always the   same as the declared type of the individual bit-field itself (for GCC   anyway... the DWARF spec doesn't actually mandate this).   Note that it is the size (in bytes) of the hypothetical "containing   object" which will be given in the AT_byte_size attribute for this   bit-field.  (See the `byte_size_attribute' function below.)  It is   also used when calculating the value of the AT_bit_offset attribute.   (See the `bit_offset_attribute' function below.)*/static voiddata_member_location_attribute (decl)     register tree decl;{  register unsigned object_offset_in_bytes = field_byte_offset (decl);  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);  sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);  sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);  ASM_OUTPUT_LABEL (asm_out_file, begin_label);  ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, object_offset_in_bytes);  ASM_OUTPUT_DWARF_STACK_O

⌨️ 快捷键说明

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