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

📄 sdbout.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* James said test TREE_ASM_BEING_WRITTEN here.  */	return;      /* Output nothing if type is not yet defined.  */      if (TYPE_SIZE (type) == 0)	return;      TREE_ASM_WRITTEN (type) = 1;#if 1      /* This is reputed to cause trouble with the following case,	 but perhaps checking TYPE_SIZE above will fix it.  */      /* Here is a test case:	struct foo {	  struct badstr *bbb;	} forwardref;	typedef struct intermediate {	  int aaaa;	} intermediate_ref;	typedef struct badstr {	  int ccccc;	} badtype;   */#if 0      TREE_ASM_BEING_WRITTEN (type) = 1;#endif      /* This change, which ought to make better output,	 used to make the COFF assembler unhappy.	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */      /* Before really doing anything, output types we want to refer to.  */      /* Note that in version 1 the following two lines	 are not used if forward references are in use.  */      if (TREE_CODE (type) != ENUMERAL_TYPE)	sdbout_field_types (type);#if 0      TREE_ASM_WRITTEN (type) = 1;#endif#endif      /* Output a structure type.  */      {	int size = int_size_in_bytes (type);	int member_scl;	tree tem;	int i, n_baseclasses = 0;	/* Record the type tag, but not in its permanent place just yet.  */	sdbout_record_type_name (type);	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;	/* Print out the base class information with fields	   named after the types they hold.  */	if (TYPE_BINFO (type)	    && TYPE_BINFO_BASETYPES (type))	  n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));	for (i = 0; i < n_baseclasses; i++)	  {	    tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);	    tree child_type = BINFO_TYPE (child);	    tree child_type_name;	    if (TYPE_NAME (child_type) == 0)	      continue;	    if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)	      child_type_name = TYPE_NAME (child_type);	    else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)	      child_type_name = DECL_NAME (TYPE_NAME (child_type));	    else	      continue;	    CONTIN;	    PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));	    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));	    PUT_SDB_SCL (member_scl);	    sdbout_type (BINFO_TYPE (child));	    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.	       Also omit fields with variable size or position.	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */	    if (TREE_CODE (tem) == FIELD_DECL		&& DECL_NAME (tem) != 0		&& TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST		&& TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)	      {		CONTIN;		PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (tem)));		if (DECL_BIT_FIELD_TYPE (tem))		  {		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));		    PUT_SDB_SCL (C_FIELD);		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));		    PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));		  }		else		  {		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (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;      }    }}/* The following two functions output definitions of function parameters.   Each parameter gets a definition locating it in the parameter list.   Each parameter that is a register variable gets a second definition   locating it in the register.   Printing or argument lists in gdb uses the definitions that   locate in the parameter list.  But reference to the variable in   expressions uses preferentially the definition as a register.  *//* Output definitions, referring to storage in the parmlist,   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */static voidsdbout_parms (parms)     tree parms;{  for (; parms; parms = TREE_CHAIN (parms))    if (DECL_NAME (parms))      {	int current_sym_value = 0;	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));	if (name == 0 || *name == 0)	  name = gen_fake_label ();	/* Perform any necessary register eliminations on the parameter's rtl,	   so that the debugging output will be accurate.  */	DECL_INCOMING_RTL (parms) =	  eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);	DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);	if (PARM_PASSED_IN_MEMORY (parms))	  {	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);	    tree type;	    /* ??? Here we assume that the parm address is indexed	       off the frame pointer or arg pointer.	       If that is not true, we produce meaningless results,	       but do not crash.  */	    if (GET_CODE (addr) == PLUS		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)	      current_sym_value = INTVAL (XEXP (addr, 1));	    else	      current_sym_value = 0;	    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	      {		int original_sym_value = current_sym_value;		/* 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.  */#if 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 = original_sym_value;		    type = DECL_ARG_TYPE (parms);		  }	      }	    PUT_SDB_DEF (name);	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));	    PUT_SDB_SCL (C_ARG);	    PUT_SDB_TYPE (plain_type (type));	    PUT_SDB_ENDEF;	  }	else if (GET_CODE (DECL_RTL (parms)) == REG)	  {	    rtx best_rtl;	    /* Parm passed in registers and lives in registers or nowhere.  */	    /* If parm lives in a register, use that register;	       pretend the parm was passed there.  It would be more consistent	       to describe the register where the parm was passed,	       but in practice that register usually holds something else.  */	    if (REGNO (DECL_RTL (parms)) >= 0		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)	      best_rtl = DECL_RTL (parms);	    /* If the parm lives nowhere,	       use the register where it was passed.  */	    else	      best_rtl = DECL_INCOMING_RTL (parms);	    PUT_SDB_DEF (name);	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));	    PUT_SDB_SCL (C_REGPARM);	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));	    PUT_SDB_ENDEF;	  }	else if (GET_CODE (DECL_RTL (parms)) == MEM		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)	  {	    /* Parm was passed in registers but lives on the stack.  */	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),	       in which case we want the value of that CONST_INT,	       or (MEM (REG ...)) or (MEM (MEM ...)),	       in which case we use a value of zero.  */	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)	      current_sym_value = 0;	    else	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));	    /* Again, this assumes the offset is based on the arg pointer.  */	    PUT_SDB_DEF (name);	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,						  XEXP (DECL_RTL (parms), 0)));	    PUT_SDB_SCL (C_ARG);	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));	    PUT_SDB_ENDEF;	  }      }}/* Output definitions for the places where parms live during the function,   when different from where they were passed, when the parms were passed   in memory.   It is not useful to do this for parms passed in registers   that live during the function in different registers, because it is   impossible to look in the passed register for the passed value,   so we use the within-the-function register to begin with.   PARMS is a chain of PARM_DECL nodes.  */static voidsdbout_reg_parms (parms)     tree parms;{  for (; parms; parms = TREE_CHAIN (parms))    if (DECL_NAME (parms))      {	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));	/* Report parms that live in registers during the function	   but were passed in memory.  */	if (GET_CODE (DECL_RTL (parms)) == REG	    && REGNO (DECL_RTL (parms)) >= 0	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER	    && PARM_PASSED_IN_MEMORY (parms))	  {	    if (name == 0 || *name == 0)	      name = gen_fake_label ();	    PUT_SDB_DEF (name);	    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;	  }	/* Report parms that live in memory but not where they were passed.  */	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		 && PARM_PASSED_IN_MEMORY (parms)		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))	  {#if 0 /* ??? It is not clear yet what should replace this.  */	    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.  */#if BYTES_BIG_ENDIAN	    if (offset != -1 && 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) {...}#endif	      {		if (name == 0 || *name == 0)		  name = gen_fake_label ();		PUT_SDB_DEF (name);		PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET				 (XEXP (DECL_RTL (parms), 0)));		PUT_SDB_SCL (C_AUTO);		PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));		PUT_SDB_ENDEF;	      }	  }      }}/* 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 BLOCKs 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 BLOCK's variables in block 1.  */      next_block_number = 0;      do_block = 0;      sdbout_block (DECL_INITIAL (decl));    }  /* If -g1, suppress all the internal symbols of functions     except for arguments.  */  if (debug_info_level != DINFO_LEVEL_TERSE)    {      next_block_number = 0;      do_block = n;      sdbout_block (DECL_INITIAL (decl));    }#ifdef SDB_ALLOW_FORWARD_REFERENCES  sdbout_dequeue_anonymous_types ();#endif}/* 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_start_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;{#ifdef SDB_ALLOW_FORWARD_REFERENCES  sdbout_dequeue_anonymous_types ();#endif  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_ASSEMBLER_NAME (current_function_decl));  PUT_SDB_EPILOGUE_END (name);}/* Output sdb info for the given label.  Called only if LABEL_NAME (insn)   is present.  */voidsdbout_label (insn)     register rtx insn;{  PUT_SDB_DEF (LABEL_NAME (insn));  PUT_SDB_VAL (insn);  PUT_SDB_SCL (C_LABEL);  PUT_SDB_TYPE (T_NULL);  PUT_SDB_ENDEF;}#endif /* SDB_DEBUGGING_INFO */

⌨️ 快捷键说明

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