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

📄 emit-rtl.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  rt_val = rtvec_alloc (n);	/* Allocate an rtvec...			*/  for (i = 0; i < n; i++)    rt_val->elem[i].rtx = *argp++;  return rt_val;}rtvecgen_rtvec_vv (n, argp)     int n;     rtunion *argp;{  register int i;  register rtvec rt_val;  if (n == 0)    return NULL_RTVEC;		/* Don't allocate an empty rtvec...	*/  rt_val = rtvec_alloc (n);	/* Allocate an rtvec...			*/  for (i = 0; i < n; i++)    rt_val->elem[i].rtx = (argp++)->rtx;  return rt_val;}/* Generate a REG rtx for a new pseudo register of mode MODE.   This pseudo is assigned the next sequential register number.  */rtxgen_reg_rtx (mode)     enum machine_mode mode;{  register rtx val;  /* Don't let anything called by or after reload create new registers     (actually, registers can't be created after flow, but this is a good     approximation).  */  if (reload_in_progress || reload_completed)    abort ();  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)    {      /* For complex modes, don't make a single pseudo.	 Instead, make a CONCAT of two pseudos.	 This allows noncontiguous allocation of the real and imaginary parts,	 which makes much better code.  Besides, allocating DCmode	 pseudos overstrains reload on some machines like the 386.  */      rtx realpart, imagpart;      int size = GET_MODE_UNIT_SIZE (mode);      enum machine_mode partmode	= mode_for_size (size * BITS_PER_UNIT,			 (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT			  ? MODE_FLOAT : MODE_INT),			 0);      realpart = gen_reg_rtx (partmode);      imagpart = gen_reg_rtx (partmode);      return gen_rtx (CONCAT, mode, realpart, imagpart);    }  /* Make sure regno_pointer_flag and regno_reg_rtx are large     enough to have an element for this pseudo reg number.  */  if (reg_rtx_no == regno_pointer_flag_length)    {      rtx *new1;      char *new =	(char *) savealloc (regno_pointer_flag_length * 2);      bcopy (regno_pointer_flag, new, regno_pointer_flag_length);      bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);      regno_pointer_flag = new;      new = (char *) savealloc (regno_pointer_flag_length * 2);      bcopy (regno_pointer_align, new, regno_pointer_flag_length);      bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);      regno_pointer_align = new;      new1 = (rtx *) savealloc (regno_pointer_flag_length * 2 * sizeof (rtx));      bcopy ((char *) regno_reg_rtx, (char *) new1,	     regno_pointer_flag_length * sizeof (rtx));      bzero ((char *) &new1[regno_pointer_flag_length],	     regno_pointer_flag_length * sizeof (rtx));      regno_reg_rtx = new1;      regno_pointer_flag_length *= 2;    }  val = gen_rtx (REG, mode, reg_rtx_no);  regno_reg_rtx[reg_rtx_no++] = val;  return val;}/* Identify REG (which may be a CONCAT) as a user register.  */voidmark_user_reg (reg)     rtx reg;{  if (GET_CODE (reg) == CONCAT)    {      REG_USERVAR_P (XEXP (reg, 0)) = 1;      REG_USERVAR_P (XEXP (reg, 1)) = 1;    }  else if (GET_CODE (reg) == REG)    REG_USERVAR_P (reg) = 1;  else    abort ();}/* Identify REG as a probable pointer register and show its alignment   as ALIGN, if nonzero.  */voidmark_reg_pointer (reg, align)     rtx reg;     int align;{  REGNO_POINTER_FLAG (REGNO (reg)) = 1;  if (align)    REGNO_POINTER_ALIGN (REGNO (reg)) = align;}/* Return 1 plus largest pseudo reg number used in the current function.  */intmax_reg_num (){  return reg_rtx_no;}/* Return 1 + the largest label number used so far in the current function.  */intmax_label_num (){  if (last_label_num && label_num == base_label_num)    return last_label_num;  return label_num;}/* Return first label number used in this function (if any were used).  */intget_first_label_num (){  return first_label_num;}/* Return a value representing some low-order bits of X, where the number   of low-order bits is given by MODE.  Note that no conversion is done   between floating-point and fixed-point values, rather, the bit    representation is returned.   This function handles the cases in common between gen_lowpart, below,   and two variants in cse.c and combine.c.  These are the cases that can   be safely handled at all points in the compilation.   If this is not a case we can handle, return 0.  */rtxgen_lowpart_common (mode, x)     enum machine_mode mode;     register rtx x;{  int word = 0;  if (GET_MODE (x) == mode)    return x;  /* MODE must occupy no more words than the mode of X.  */  if (GET_MODE (x) != VOIDmode      && ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD	  > ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))	     / UNITS_PER_WORD)))    return 0;  if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)    word = ((GET_MODE_SIZE (GET_MODE (x))	     - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))	    / UNITS_PER_WORD);  if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)      && (GET_MODE_CLASS (mode) == MODE_INT	  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT))    {      /* If we are getting the low-order part of something that has been	 sign- or zero-extended, we can either just use the object being	 extended or make a narrower extension.  If we want an even smaller	 piece than the size of the object being extended, call ourselves	 recursively.	 This case is used mostly by combine and cse.  */      if (GET_MODE (XEXP (x, 0)) == mode)	return XEXP (x, 0);      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))	return gen_lowpart_common (mode, XEXP (x, 0));      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))	return gen_rtx (GET_CODE (x), mode, XEXP (x, 0));    }  else if (GET_CODE (x) == SUBREG	   && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD	       || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))    return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0	    ? SUBREG_REG (x)	    : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x)));  else if (GET_CODE (x) == REG)    {      /* If the register is not valid for MODE, return 0.  If we don't	 do this, there is no way to fix up the resulting REG later.  	 But we do do this if the current REG is not valid for its	 mode.  This latter is a kludge, but is required due to the	 way that parameters are passed on some machines, most	 notably Sparc.  */      if (REGNO (x) < FIRST_PSEUDO_REGISTER	  && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)	  && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))	return 0;      else if (REGNO (x) < FIRST_PSEUDO_REGISTER	       /* integrate.c can't handle parts of a return value register. */	       && (! REG_FUNCTION_VALUE_P (x)		   || ! rtx_equal_function_value_matters)	       /* We want to keep the stack, frame, and arg pointers		  special.  */	       && x != frame_pointer_rtx#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	       && x != arg_pointer_rtx#endif	       && x != stack_pointer_rtx)	return gen_rtx (REG, mode, REGNO (x) + word);      else	return gen_rtx (SUBREG, mode, x, word);    }  /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits     from the low-order part of the constant.  */  else if ((GET_MODE_CLASS (mode) == MODE_INT	    || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_MODE (x) == VOIDmode	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))    {      /* If MODE is twice the host word size, X is already the desired	 representation.  Otherwise, if MODE is wider than a word, we can't	 do this.  If MODE is exactly a word, return just one CONST_INT.	 If MODE is smaller than a word, clear the bits that don't belong	 in our mode, unless they and our sign bit are all one.  So we get	 either a reasonable negative value or a reasonable unsigned value	 for this mode.  */      if (GET_MODE_BITSIZE (mode) >= 2 * HOST_BITS_PER_WIDE_INT)	return x;      else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)	return 0;      else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)	return (GET_CODE (x) == CONST_INT ? x		: GEN_INT (CONST_DOUBLE_LOW (x)));      else	{	  /* MODE must be narrower than HOST_BITS_PER_INT.  */	  int width = GET_MODE_BITSIZE (mode);	  HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)			       : CONST_DOUBLE_LOW (x));	  if (((val & ((HOST_WIDE_INT) (-1) << (width - 1)))	       != ((HOST_WIDE_INT) (-1) << (width - 1))))	    val &= ((HOST_WIDE_INT) 1 << width) - 1;	  return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x		  : GEN_INT (val));	}    }  /* If X is an integral constant but we want it in floating-point, it     must be the case that we have a union of an integer and a floating-point     value.  If the machine-parameters allow it, simulate that union here     and return the result.  The two-word and single-word cases are      different.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && GET_MODE_CLASS (mode) == MODE_FLOAT	   && GET_MODE_SIZE (mode) == UNITS_PER_WORD	   && GET_CODE (x) == CONST_INT	   && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)#ifdef REAL_ARITHMETIC    {      REAL_VALUE_TYPE r;      HOST_WIDE_INT i;      i = INTVAL (x);      r = REAL_VALUE_FROM_TARGET_SINGLE (i);      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);    }#else    {      union {HOST_WIDE_INT i; float d; } u;      u.i = INTVAL (x);      return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);    }#endif  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && GET_MODE_CLASS (mode) == MODE_FLOAT	   && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)	   && GET_MODE (x) == VOIDmode	   && (sizeof (double) * HOST_BITS_PER_CHAR	       == 2 * HOST_BITS_PER_WIDE_INT))#ifdef REAL_ARITHMETIC    {      REAL_VALUE_TYPE r;      HOST_WIDE_INT i[2];      HOST_WIDE_INT low, high;      if (GET_CODE (x) == CONST_INT)	low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);      else	low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);      /* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the	 target machine.  */      if (WORDS_BIG_ENDIAN)	i[0] = high, i[1] = low;      else	i[0] = low, i[1] = high;      r = REAL_VALUE_FROM_TARGET_DOUBLE (i);      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);    }#else    {      union {HOST_WIDE_INT i[2]; double d; } u;      HOST_WIDE_INT low, high;      if (GET_CODE (x) == CONST_INT)	low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);      else	low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);#ifdef HOST_WORDS_BIG_ENDIAN      u.i[0] = high, u.i[1] = low;#else      u.i[0] = low, u.i[1] = high;#endif      return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);    }#endif  /* We need an extra case for machines where HOST_BITS_PER_WIDE_INT is the     same as sizeof (double), such as the alpha.  We only handle the     REAL_ARITHMETIC case, which is easy.  Testing HOST_BITS_PER_WIDE_INT     is not strictly necessary, but is done to restrict this code to cases     where it is known to work.  */#ifdef REAL_ARITHMETIC  else if (mode == SFmode	   && GET_CODE (x) == CONST_INT	   && GET_MODE_BITSIZE (mode) * 2 == HOST_BITS_PER_WIDE_INT)    {      REAL_VALUE_TYPE r;      HOST_WIDE_INT i;      i = INTVAL (x);      r = REAL_VALUE_FROM_TARGET_SINGLE (i);      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);    }#endif  /* Similarly, if this is converting a floating-point value into a     single-word integer.  Only do this is the host and target parameters are     compatible.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && (GET_MODE_CLASS (mode) == MODE_INT	       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_CODE (x) == CONST_DOUBLE	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT	   && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)    return operand_subword (x, word, 0, GET_MODE (x));  /* Similarly, if this is converting a floating-point value into a     two-word integer, we can do this one word at a time and make an     integer.  Only do this is the host and target parameters are     compatible.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && (GET_MODE_CLASS (mode) == MODE_INT	       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_CODE (x) == CONST_DOUBLE	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT	   && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)    {      rtx lowpart	= operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));      rtx highpart	= operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));      if (lowpart && GET_CODE (lowpart) == CONST_INT	  && highpart && GET_CODE (highpart) == CONST_INT)	return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);    }  /* Otherwise, we can't do this.  */  return 0;}/* Return the real part (which has mode MODE) of a complex value X.   This always comes at the low address in memory.  */rtxgen_realpart (mode, x)     enum machine_mode mode;     register rtx x;{  if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)    return XEXP (x, 0);  else if (WORDS_BIG_ENDIAN)    return gen_highpart (mode, x);  else    return gen_lowpart (mode, x);}/* Return the imaginary part (which has mode MODE) of a complex value X.   This always comes at the high address in memory.  */rtxgen_imagpart (mode, x)     enum machine_mode mode;     register rtx x;{  if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)    return XEXP (x, 1);  else if (WORDS_BIG_ENDIAN)    return gen_lowpart (mode, x);  else    return gen_highpart (mode, x);}/* Return 1 iff X, assumed to be a SUBREG,   refers to the real part of the complex value in its containing reg.   Complex values are always stored with the real part in the first word,   regardless of WORDS_BIG_ENDIAN.  */intsubreg_realpart_p (x)     rtx x;{  if (GET_CODE (x) != SUBREG)    abort ();

⌨️ 快捷键说明

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