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

📄 varasm.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
      /* Align the location counter as required by EXP's data type.  */      align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode);      if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)	align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;      if (align > 1)	ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (align));      /* Output the label itself.  */      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);      /* Output the value of EXP.  */      if (GET_CODE (x) == CONST_DOUBLE)	{	  union real_extract u;	  bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);	  switch (mode)	    {	      /* Perhaps change the following to use		 CONST_DOUBLE_LOW and CONST_DOUBLE_HIGH, rather than u.i.  */	    case DImode:#ifdef ASM_OUTPUT_DOUBLE_INT	      ASM_OUTPUT_DOUBLE_INT (asm_out_file, x);#else /* no ASM_OUTPUT_DOUBLE_INT */#ifndef WORDS_BIG_ENDIAN	      /* Output two ints.  */	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode, u.i[0]));	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode, u.i[1]));#else	      /* Output two ints.  */	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode, u.i[1]));	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode, u.i[0]));#endif /* WORDS_BIG_ENDIAN */#endif /* no ASM_OUTPUT_DOUBLE_INT */	      break;	    case DFmode:	      ASM_OUTPUT_DOUBLE (asm_out_file, u.d);	      break;	    case SFmode:	      ASM_OUTPUT_FLOAT (asm_out_file, u.d);	    }	}      else	switch (mode)	  {	  case SImode:	    ASM_OUTPUT_INT (asm_out_file, x);	    break;	  case HImode:	    ASM_OUTPUT_SHORT (asm_out_file, x);	    break;	  case QImode:	    ASM_OUTPUT_CHAR (asm_out_file, x);	    break;	  }      /* Create a string containing the label name, in LABEL.  */      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);      ++const_labelno;      desc->label = found	= (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));    }  /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */  def = gen_rtx (MEM, mode, gen_rtx (SYMBOL_REF, Pmode, desc->label));  RTX_UNCHANGING_P (def) = 1;  /* Mark the symbol_ref as belonging to this constants pool.  */  CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;  if (GET_CODE (x) == CONST_DOUBLE)    {      if (CONST_DOUBLE_MEM (x) == cc0_rtx)	{	  CONST_DOUBLE_CHAIN (x) = real_constant_chain;	  real_constant_chain = x;	}      CONST_DOUBLE_MEM (x) = def;    }  return def;}/* Find all the constants whose addresses are referenced inside of EXP,   and make sure assembler code with a label has been output for each one.  */voidoutput_addressed_constants (exp)     tree exp;{  switch (TREE_CODE (exp))    {    case ADDR_EXPR:      {	register tree constant = TREE_OPERAND (exp, 0);	while (TREE_CODE (constant) == COMPONENT_REF)	  {	    constant = TREE_OPERAND (constant, 0);	  }	if (TREE_LITERAL (constant))	  /* No need to do anything here	     for addresses of variables or functions.  */	  output_constant_def (constant);      }      break;    case PLUS_EXPR:    case MINUS_EXPR:      output_addressed_constants (TREE_OPERAND (exp, 0));      output_addressed_constants (TREE_OPERAND (exp, 1));      break;    case NOP_EXPR:    case CONVERT_EXPR:      output_addressed_constants (TREE_OPERAND (exp, 0));      break;    case CONSTRUCTOR:      {	register tree link;	for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))	  output_addressed_constants (TREE_VALUE (link));      }      break;    case ERROR_MARK:      break;    default:      if (! TREE_LITERAL (exp))	abort ();    }}/* Output assembler code for constant EXP to FILE, with no label.   This includes the pseudo-op such as ".int" or ".byte", and a newline.   Assumes output_addressed_constants has been done on EXP already.   Generate exactly SIZE bytes of assembler data, padding at the end   with zeros if necessary.  SIZE must always be specified.   SIZE is important for structure constructors,   since trailing members may have been omitted from the constructor.   It is also important for initialization of arrays from string constants   since the full length of the string constant might not be wanted.   It is also needed for initialization of unions, where the initializer's   type is just one member, and that may not be as long as the union.   There a case in which we would fail to output exactly SIZE bytes:   for a structure constructor that wants to produce more than SIZE bytes.   But such constructors will never be generated for any possible input.  */voidoutput_constant (exp, size)     register tree exp;     register int size;{  register enum tree_code code = TREE_CODE (TREE_TYPE (exp));  rtx x;  if (size == 0)    return;  /* Eliminate the NOP_EXPR that makes a cast not be an lvalue.     That way we get the constant (we hope) inside it.  */  if (TREE_CODE (exp) == NOP_EXPR      && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0)))    exp = TREE_OPERAND (exp, 0);  switch (code)    {    case INTEGER_TYPE:    case ENUMERAL_TYPE:    case POINTER_TYPE:    case REFERENCE_TYPE:      /* ??? What about       (int)((float)(int)&foo + 4)    */      while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR)	exp = TREE_OPERAND (exp, 0);#ifndef ASM_OUTPUT_DOUBLE_INT      if (TYPE_MODE (TREE_TYPE (exp)) == DImode)	{	  if (TREE_CODE (exp) == INTEGER_CST)	    {#ifndef WORDS_BIG_ENDIAN	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode,				       TREE_INT_CST_LOW (exp)));	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode,				       TREE_INT_CST_HIGH (exp)));#else	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode,				       TREE_INT_CST_HIGH (exp)));	      ASM_OUTPUT_INT (asm_out_file,			      gen_rtx (CONST_INT, VOIDmode,				       TREE_INT_CST_LOW (exp)));#endif	      size -= 8;	      break;	    }	  else	    error ("8-byte integer constant expression too complicated");	  break;	}#endif /* no ASM_OUTPUT_DOUBLE_INT */      x = expand_expr (exp, 0, VOIDmode, EXPAND_SUM);      if (size == 1)	{	  ASM_OUTPUT_CHAR (asm_out_file, x);	  size -= 1;	}      else if (size == 2)	{	  ASM_OUTPUT_SHORT (asm_out_file, x);	  size -= 2;	}      else if (size == 4)	{	  ASM_OUTPUT_INT (asm_out_file, x);	  size -= 4;	}#ifdef ASM_OUTPUT_DOUBLE_INT      else if (size == 8)	{	  ASM_OUTPUT_DOUBLE_INT (asm_out_file, x);	  size -= 8;	}#endif /* ASM_OUTPUT_DOUBLE_INT */      else	abort ();      break;    case REAL_TYPE:      if (TREE_CODE (exp) != REAL_CST)	error ("initializer for floating value is not a floating constant");      else	{	  REAL_VALUE_TYPE d;	  jmp_buf output_constant_handler;	  d = TREE_REAL_CST (exp);	  if (setjmp (output_constant_handler))	    {	      error ("floating point trap outputting a constant");#ifdef REAL_IS_NOT_DOUBLE	      bzero (&d, sizeof d);	      d = REAL_VALUE_ATOF ("0");#else	      d = 0;#endif	    }	  set_float_handler (output_constant_handler);	  if (size < 4)	    break;	  else if (size < 8)	    {	      ASM_OUTPUT_FLOAT (asm_out_file, d);	      size -= 4;	    }	  else	    {	      ASM_OUTPUT_DOUBLE (asm_out_file, d);	      size -= 8;	    }	  set_float_handler (0);	}      break;    case COMPLEX_TYPE:      output_constant (TREE_REALPART (exp), size / 2);      output_constant (TREE_IMAGPART (exp), size / 2);      size -= (size / 2) * 2;      break;    case ARRAY_TYPE:      if (TREE_CODE (exp) == CONSTRUCTOR)	{	  output_constructor (exp, size);	  return;	}      else if (TREE_CODE (exp) == STRING_CST)	{	  int excess = 0;	  if (size > TREE_STRING_LENGTH (exp))	    {	      excess = size - TREE_STRING_LENGTH (exp);	      size = TREE_STRING_LENGTH (exp);	    }	  assemble_string (TREE_STRING_POINTER (exp), size);	  size = excess;	}      else	abort ();      break;    case RECORD_TYPE:    case UNION_TYPE:      if (TREE_CODE (exp) == CONSTRUCTOR)	output_constructor (exp, size);      else	abort ();      return;    }  if (size > 0)    ASM_OUTPUT_SKIP (asm_out_file, size);}/* Subroutine of output_constant, used for CONSTRUCTORs   (aggregate constants).   Generate at least SIZE bytes, padding if necessary.  */voidoutput_constructor (exp, size)     tree exp;     int size;{  register tree link, field = 0;  /* Number of bytes output or skipped so far.     In other words, current position within the constructor.  */  int total_bytes = 0;  /* Non-zero means BYTE contains part of a byte, to be output.  */  int byte_buffer_in_use = 0;  register int byte;  if (HOST_BITS_PER_INT < BITS_PER_UNIT)    abort ();  if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE      || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)    field = TYPE_FIELDS (TREE_TYPE (exp));  /* As LINK goes through the elements of the constant,     FIELD goes through the structure fields, if the constant is a structure.     But the constant could also be an array.  Then FIELD is zero.  */  for (link = CONSTRUCTOR_ELTS (exp);       link;       link = TREE_CHAIN (link),       field = field ? TREE_CHAIN (field) : 0)    {      tree val = TREE_VALUE (link);      /* Eliminate the NOP_EXPR that makes a cast not be an lvalue.  */      if (TREE_CODE (val) == NOP_EXPR	  && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))	val = TREE_OPERAND (val, 0);      if (field == 0	  || (DECL_MODE (field) != BImode))	{	  register int fieldsize;	  /* An element that is not a bit-field.	     Output any buffered-up bit-fields preceding it.  */	  if (byte_buffer_in_use)	    {	      ASM_OUTPUT_BYTE (asm_out_file, byte);	      total_bytes++;	      byte_buffer_in_use = 0;	    }	  /* Advance to offset of this element.	     Note no alignment needed in an array, since that is guaranteed	     if each element has the proper size.  */	  if (field != 0 && DECL_OFFSET (field) / BITS_PER_UNIT != total_bytes)	    {	      ASM_OUTPUT_SKIP (asm_out_file,			       (DECL_OFFSET (field) / BITS_PER_UNIT				- total_bytes));	      total_bytes = DECL_OFFSET (field) / BITS_PER_UNIT;	    }	  /* Determine size this element should occupy.  */	  if (field)	    {	      if (! TREE_LITERAL (DECL_SIZE (field)))		abort ();	      fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field))		* DECL_SIZE_UNIT (field);	      fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;	    }	  else	    fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));	  /* Output the element's initial value.  */	  output_constant (val, fieldsize);	  /* Count its size.  */	  total_bytes += fieldsize;	}      else if (TREE_CODE (val) != INTEGER_CST)	error ("invalid initial value for member `%s'",	       IDENTIFIER_POINTER (DECL_NAME (field)));      else	{	  /* Element that is a bit-field.  */	  int next_offset = DECL_OFFSET (field);	  int end_offset	    = (next_offset	       + (TREE_INT_CST_LOW (DECL_SIZE (field))		  * DECL_SIZE_UNIT (field)));	  /* If this field does not start in this (or, next) byte,	     skip some bytes.  */	  if (next_offset / BITS_PER_UNIT != total_bytes)	    {	      /* Output remnant of any bit field in previous bytes.  */	      if (byte_buffer_in_use)		{		  ASM_OUTPUT_BYTE (asm_out_file, byte);		  total_bytes++;		  byte_buffer_in_use = 0;		}	      /* If still not at proper byte, advance to there.  */	      if (next_offset / BITS_PER_UNIT != total_bytes)		{		  ASM_OUTPUT_SKIP (asm_out_file,				   next_offset / BITS_PER_UNIT - total_bytes);		  total_bytes = next_offset / BITS_PER_UNIT;		}	    }	  if (! byte_buffer_in_use)	    byte = 0;	  /* We must split the element into pieces that fall within	     separate bytes, and combine each byte with previous or	     following bit-fields.  */	  /* next_offset is the offset n fbits from the begining of	     the structure to the next bit of this element to be processed.	     end_offset is the offset of the first bit past the end of	     this element.  */	  while (next_offset < end_offset)	    {	      int this_time;	      int next_byte = next_offset / BITS_PER_UNIT;	      int next_bit = next_offset % BITS_PER_UNIT;	      /* Advance from byte to byte		 within this element when necessary.  */	      while (next_byte != total_bytes)		{		  ASM_OUTPUT_BYTE (asm_out_file, byte);		  total_bytes++;		  byte = 0;		}	      /* Number of bits we can process at once		 (all part of the same byte).  */	      this_time = MIN (end_offset - next_offset,			       BITS_PER_UNIT - next_bit);#ifdef BYTES_BIG_ENDIAN	      /* On big-endian machine, take the most significant bits		 first (of the bits that are significant)		 and put them into bytes from the most significant end.  */	      byte |= (((TREE_INT_CST_LOW (val)			 >> (end_offset - next_offset - this_time))			& ((1 << this_time) - 1))		       << (BITS_PER_UNIT - this_time - next_bit));#else	      /* On little-endian machines,		 take first the least significant bits of the value		 and pack them starting at the least significant		 bits of the bytes.  */	      byte |= ((TREE_INT_CST_LOW (val)			>> (next_offset - DECL_OFFSET (field)))		       & ((1 << this_time) - 1)) << next_bit;#endif	      next_offset += this_time;	      byte_buffer_in_use = 1;	    }	}    }  if (byte_buffer_in_use)    {      ASM_OUTPUT_BYTE (asm_out_file, byte);      total_bytes++;    }  if (total_bytes < size)    ASM_OUTPUT_SKIP (asm_out_file, size - total_bytes);}

⌨️ 快捷键说明

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