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

📄 integrate.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  register RTX_CODE code;  register enum machine_mode mode;  register char *format_ptr;  int regno;  if (orig == 0)    return 0;  code = GET_CODE (orig);  mode = GET_MODE (orig);  switch (code)    {    case REG:      /* If a frame-pointer register shows up, then we	 must `fix' the reference.  If the stack pointer	 register shows up, it must be part of stack-adjustments	 (*not* because we eliminated the frame pointer!).	 Small hard registers are returned as-is.  Pseudo-registers	 go through their `reg_map'.  */      regno = REGNO (orig);      if (regno < FIRST_PSEUDO_REGISTER)	{	  /* Some hard registers are also mapped,	     but others are not translated.  */	  if (reg_map[regno] != 0)	    return reg_map[regno];	  if (REG_FUNCTION_VALUE_P (orig))	    {	      /* This is a reference to the function return value.  If		 the function doesn't have a return value, error.		 If it does, it may not be the same mode as `inline_target'		 because SUBREG is not required for hard regs.		 If not, adjust mode of inline_target to fit the context.  */	      if (inline_target == 0)		abort ();	      if (mode == GET_MODE (inline_target))		return inline_target;	      return gen_rtx (SUBREG, mode, inline_target, 0);	    }	  if (regno == FRAME_POINTER_REGNUM)	    return plus_constant (orig, fp_delta);	  return orig;	}      if (reg_map[regno] == NULL)	{	  reg_map[regno] = gen_reg_rtx (mode);	  REG_USERVAR_P (reg_map[regno]) = REG_USERVAR_P (orig);	}      return reg_map[regno];    case SUBREG:      copy = copy_rtx_and_substitute (SUBREG_REG (orig));      /* SUBREG is ordinary, but don't make nested SUBREGs.  */      if (GET_CODE (copy) == SUBREG)	return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy),			SUBREG_WORD (orig) + SUBREG_WORD (copy));      return gen_rtx (SUBREG, GET_MODE (orig), copy,		      SUBREG_WORD (orig));    case CODE_LABEL:      return label_map[CODE_LABEL_NUMBER (orig)];    case LABEL_REF:      copy = rtx_alloc (LABEL_REF);      PUT_MODE (copy, mode);      XEXP (copy, 0) = label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))];      return copy;    case PC:    case CC0:    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:      return orig;    case ASM_OPERANDS:      /* If a single asm insn contains multiple output operands	 then it contains multiple ASM_OPERANDS rtx's that share operand 3.	 We must make sure that the copied insn continues to share it.  */      if (orig_asm_operands_vector == XVEC (orig, 3))	{	  copy = rtx_alloc (ASM_OPERANDS);	  XSTR (copy, 0) = XSTR (orig, 0);	  XSTR (copy, 1) = XSTR (orig, 1);	  XINT (copy, 2) = XINT (orig, 2);	  XVEC (copy, 3) = copy_asm_operands_vector;	  XVEC (copy, 4) = copy_asm_constraints_vector;	  XSTR (copy, 5) = XSTR (orig, 5);	  XINT (copy, 6) = XINT (orig, 6);	  return copy;	}      break;    case CALL:      /* This is given special treatment because the first	 operand of a CALL is a (MEM ...) which may get	 forced into a register for cse.  This is undesirable	 if function-address cse isn't wanted or if we won't do cse.  */#ifndef NO_FUNCTION_CSE      if (! (optimize && ! flag_no_function_cse))#endif	return gen_rtx (CALL, GET_MODE (orig),			gen_rtx (MEM, GET_MODE (XEXP (orig, 0)),				 copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0))),			copy_rtx_and_substitute (XEXP (orig, 1)));      break;    case PLUS:      /* Note:  the PLUS case is not nearly as careful as the MEM	 case in terms of preserving addresses.  The reason for this	 is that it is expected that if a PLUS_EXPR turns out not	 to be a legitimate address, reload can fix that up, without	 doing major damage.  However, a MEM rtx must preside	 over a legitimate address.  The MEM case has lots of hair	 to deal with what happens when it sits on a PLUS...  */      /* Take care of the easy case quickly.  */      if (XEXP (orig, 0) == frame_pointer_rtx	  || XEXP (orig, 1) == frame_pointer_rtx	  || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM	      && (XEXP (orig, 0) == arg_pointer_rtx		  || XEXP (orig, 1) == arg_pointer_rtx)))	{	  rtx reg;	  if (XEXP (orig, 0) == frame_pointer_rtx	      || XEXP (orig, 0) == arg_pointer_rtx)	    reg = XEXP (orig, 0), copy = XEXP (orig, 1);	  else	    reg = XEXP (orig, 1), copy = XEXP (orig, 0);	  if (GET_CODE (copy) == CONST_INT)	    {	      int c = INTVAL (copy);	      if (reg == arg_pointer_rtx && c >= first_parm_offset		  && (c / UNITS_PER_WORD) < parm_map_size)		{		  copy = access_parm_map (c, VOIDmode);		  if (GET_CODE (copy) != MEM)		    /* Should not happen, because a parm we need to address		       should not be living in a register.		       (expand_inline_function copied it to a stack slot.)  */		    abort ();		  return XEXP (copy, 0);		}	      return gen_rtx (PLUS, mode,			      frame_pointer_rtx,			      gen_rtx (CONST_INT, SImode,				       c + fp_delta));	    }	  copy = copy_rtx_and_substitute (copy);	  temp = force_reg (mode, gen_rtx (PLUS, mode, frame_pointer_rtx, copy));	  return plus_constant (temp, fp_delta);	}      else if (frame_pointer_sum_p (orig))	{	  /* If we have a complex sum which has a frame pointer	     in it, and it was a legitimate address, then	     keep it that way.  */	  if (memory_address_p (mode, orig))	    {	      if (GET_CODE (XEXP (orig, 0)) == CONST_INT)		{		  copy = copy_rtx_and_substitute (XEXP (orig, 1));		  temp = plus_constant (copy, INTVAL (XEXP (orig, 0)));		}	      else if (GET_CODE (XEXP (orig, 1)) == CONST_INT)		{		  copy = copy_rtx_and_substitute (XEXP (orig, 0));		  temp = plus_constant (copy, INTVAL (XEXP (orig, 1)));		}	      else		{		  temp = gen_rtx (PLUS, GET_MODE (orig),				  copy_rtx_and_substitute (XEXP (orig, 0)),				  copy_rtx_and_substitute (XEXP (orig, 1)));		}	      temp = memory_address (mode, temp);	    }	  else	    temp = gen_rtx (PLUS, GET_MODE (orig),			    copy_rtx_and_substitute (XEXP (orig, 0)),			    copy_rtx_and_substitute (XEXP (orig, 1)));	}      else	temp = gen_rtx (PLUS, GET_MODE (orig),			copy_rtx_and_substitute (XEXP (orig, 0)),			copy_rtx_and_substitute (XEXP (orig, 1)));      return temp;    case MEM:      /* Take care of easiest case here.  */      copy = XEXP (orig, 0);      if (copy == frame_pointer_rtx || copy == arg_pointer_rtx)	return gen_rtx (MEM, mode,			plus_constant (frame_pointer_rtx, fp_delta));      /* Allow a pushing-address even if that is not valid as an	 ordinary memory address.  It indicates we are inlining a special	 push-insn.  These must be copied; otherwise unshare_all_rtl	 might clobber them to point at temporary rtl of this function.  */#ifdef STACK_GROWS_DOWNWARD      if (GET_CODE (copy) == PRE_DEC && XEXP (copy, 0) == stack_pointer_rtx)	return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));#else      if (GET_CODE (copy) == PRE_INC && XEXP (copy, 0) == stack_pointer_rtx)	return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));#endif      /* If this is some other sort of address that isn't generally valid,	 break out all the registers referred to.  */      if (! memory_address_p (mode, copy))	return gen_rtx (MEM, mode, copy_address (copy));      if (GET_CODE (copy) == PLUS)	{	  if (XEXP (copy, 0) == frame_pointer_rtx	      || XEXP (copy, 1) == frame_pointer_rtx	      || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM		  && (XEXP (copy, 0) == arg_pointer_rtx		      || XEXP (copy, 1) == arg_pointer_rtx)))	    {	      rtx reg;	      if (XEXP (copy, 0) == frame_pointer_rtx		  || XEXP (copy, 0) == arg_pointer_rtx)		reg = XEXP (copy, 0), copy = XEXP (copy, 1);	      else		reg = XEXP (copy, 1), copy = XEXP (copy, 0);	      if (GET_CODE (copy) == CONST_INT)		{		  int c = INTVAL (copy);		  if (reg == arg_pointer_rtx && c >= first_parm_offset		      && (c / UNITS_PER_WORD) < parm_map_size)		    return access_parm_map (c, mode);		  temp = gen_rtx (PLUS, Pmode,				  frame_pointer_rtx,				  gen_rtx (CONST_INT, SImode,					   c + fp_delta));		  if (! memory_address_p (Pmode, temp))		    return gen_rtx (MEM, mode, plus_constant (inline_fp_rtx, c));		}	      copy =  copy_rtx_and_substitute (copy);	      temp = gen_rtx (PLUS, Pmode, frame_pointer_rtx, copy);	      temp = plus_constant (temp, fp_delta);	      temp = memory_address (Pmode, temp);	    }	  else if (reg_mentioned_p (frame_pointer_rtx, copy)		   || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM		       && reg_mentioned_p (arg_pointer_rtx, copy)))	    {	      if (GET_CODE (XEXP (copy, 0)) == CONST_INT)		{		  temp = copy_rtx_and_substitute (XEXP (copy, 1));		  temp = plus_constant (temp, INTVAL (XEXP (copy, 0)));		}	      else if (GET_CODE (XEXP (copy, 1)) == CONST_INT)		{		  temp = copy_rtx_and_substitute (XEXP (copy, 0));		  temp = plus_constant (temp, INTVAL (XEXP (copy, 1)));		}	      else		{		  temp = gen_rtx (PLUS, GET_MODE (copy),				  copy_rtx_and_substitute (XEXP (copy, 0)),				  copy_rtx_and_substitute (XEXP (copy, 1)));		}	    }	  else	    {	      if (GET_CODE (XEXP (copy, 1)) == CONST_INT)		temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 0)),				      INTVAL (XEXP (copy, 1)));	      else if (GET_CODE (XEXP (copy, 0)) == CONST_INT)		temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 1)),				      INTVAL (XEXP (copy, 0)));	      else		{		  rtx left = copy_rtx_and_substitute (XEXP (copy, 0));		  rtx right = copy_rtx_and_substitute (XEXP (copy, 1));		  temp = gen_rtx (PLUS, GET_MODE (copy), left, right);		}	    }	}      else	temp = copy_rtx_and_substitute (copy);      /* Avoid change_address if we can, because it copies certain	 valid addresses into registers.  And doing that on a memref	 that appears twice in the insn (with a match_dup) would lose.  */       if (memory_address_p (mode, temp))	{	  rtx new = gen_rtx (MEM, mode, temp);	  MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);	  RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);	  MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);	  return new;	}      /* I think this will never be reached.  And I hope so, because if it	 is reached, that implies it can probably be reached for a memref	 that appears twice in one insn, and that would cause a crash.	 The clean thing to do would be to abort here, see if there is a	 bug, and fix it.  But that would probably cause more errors in the	 short term, and long-term cleanups in GCC version 1 don't matter.  */      return change_address (orig, mode, temp);    case RETURN:      abort ();    }  copy = rtx_alloc (code);  PUT_MODE (copy, mode);  copy->in_struct = orig->in_struct;  copy->volatil = orig->volatil;  copy->unchanging = orig->unchanging;  format_ptr = GET_RTX_FORMAT (GET_CODE (copy));  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)    {      switch (*format_ptr++)	{	case '0':	  break;	case 'e':	  XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i));	  break;	case 'u':	  /* Change any references to old-insns to point to the	     corresponding copied insns.  */	  XEXP (copy, i) = insn_map[INSN_UID (XEXP (orig, i))];	  break;	case 'E':	  XVEC (copy, i) = XVEC (orig, i);	  if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)	    {	      XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));	      for (j = 0; j < XVECLEN (copy, i); j++)		XVECEXP (copy, i, j) = copy_rtx_and_substitute (XVECEXP (orig, i, j));	    }	  break;	case 'i':	  XINT (copy, i) = XINT (orig, i);	  break;	case 's':	  XSTR (copy, i) = XSTR (orig, i);	  break;	default:	  abort ();	}    }  if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)    {      orig_asm_operands_vector = XVEC (orig, 3);      copy_asm_operands_vector = XVEC (copy, 3);      copy_asm_constraints_vector = XVEC (copy, 4);    }  return copy;}/* Get the value corresponding to an address relative to the arg pointer   at index RELADDRESS.  MODE is the machine mode of the reference.   MODE is used only when the value is a REG.   Pass VOIDmode for MODE when the mode is not known;   in such cases, you should make sure the value is a MEM.  */static rtxaccess_parm_map (reladdress, mode)     int reladdress;     enum machine_mode mode;{  /* Index in parm_map.  */  int index = reladdress / UNITS_PER_WORD;  /* Offset of the data being referenced     from the beginning of the value for that parm.  */  int offset = reladdress % UNITS_PER_WORD;  rtx copy;  /* If we are referring to the middle of a multiword parm,     find the beginning of that parm.     OFFSET gets the offset of the reference from     the beginning of the parm.  */  while (parm_map[index] == 0)    {      index--;      if (index < first_parm_offset / UNITS_PER_WORD)	/* If this abort happens, it means we need	   to handle "decrementing" INDEX back far	   enough to start looking among the reg parms	   instead of the stack parms.  What a mess!  */	abort ();      offset += UNITS_PER_WORD;    }  copy = parm_map[index];#ifdef BYTES_BIG_ENDIAN  /* Subtract from OFFSET the offset of where     the actual parm value would start.  */  if (GET_MODE_SIZE (GET_MODE (copy)) < UNITS_PER_WORD)

⌨️ 快捷键说明

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