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

📄 expr.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
      emit_library_call (bzero_libfunc, 0,			 VOIDmode, 2,			 XEXP (object, 0), Pmode,				 convert_to_mode (TYPE_MODE (sizetype),					  size, TREE_UNSIGNED (sizetype)),			 TYPE_MODE (sizetype));#endif    }  else    emit_move_insn (object, const0_rtx);}/* Generate code to copy Y into X.   Both Y and X must have the same mode, except that   Y can be a constant with VOIDmode.   This mode cannot be BLKmode; use emit_block_move for that.   Return the last instruction emitted.  */rtxemit_move_insn (x, y)     rtx x, y;{  enum machine_mode mode = GET_MODE (x);  x = protect_from_queue (x, 1);  y = protect_from_queue (y, 0);  if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))    abort ();  if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))    y = force_const_mem (mode, y);  /* If X or Y are memory references, verify that their addresses are valid     for the machine.  */  if (GET_CODE (x) == MEM      && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))	   && ! push_operand (x, GET_MODE (x)))	  || (flag_force_addr	      && CONSTANT_ADDRESS_P (XEXP (x, 0)))))    x = change_address (x, VOIDmode, XEXP (x, 0));  if (GET_CODE (y) == MEM      && (! memory_address_p (GET_MODE (y), XEXP (y, 0))	  || (flag_force_addr	      && CONSTANT_ADDRESS_P (XEXP (y, 0)))))    y = change_address (y, VOIDmode, XEXP (y, 0));  if (mode == BLKmode)    abort ();  return emit_move_insn_1 (x, y);}/* Low level part of emit_move_insn.   Called just like emit_move_insn, but assumes X and Y   are basically valid.  */rtxemit_move_insn_1 (x, y)     rtx x, y;{  enum machine_mode mode = GET_MODE (x);  enum machine_mode submode;  enum mode_class class = GET_MODE_CLASS (mode);  int i;  if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)    return      emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));  /* Expand complex moves by moving real part and imag part, if possible.  */  else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)	   && BLKmode != (submode = mode_for_size ((GET_MODE_UNIT_SIZE (mode)						    * BITS_PER_UNIT),						   (class == MODE_COMPLEX_INT						    ? MODE_INT : MODE_FLOAT),						   0))	   && (mov_optab->handlers[(int) submode].insn_code	       != CODE_FOR_nothing))    {      /* Don't split destination if it is a stack push.  */      int stack = push_operand (x, GET_MODE (x));      rtx insns;      /* If this is a stack, push the highpart first, so it	 will be in the argument order.	 In that case, change_address is used only to convert	 the mode, not to change the address.  */      if (stack)	{	  /* Note that the real part always precedes the imag part in memory	     regardless of machine's endianness.  */#ifdef STACK_GROWS_DOWNWARD	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_rtx (MEM, submode, (XEXP (x, 0))),		      gen_imagpart (submode, y)));	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_rtx (MEM, submode, (XEXP (x, 0))),		      gen_realpart (submode, y)));#else	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_rtx (MEM, submode, (XEXP (x, 0))),		      gen_realpart (submode, y)));	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_rtx (MEM, submode, (XEXP (x, 0))),		      gen_imagpart (submode, y)));#endif	}      else	{	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_realpart (submode, x), gen_realpart (submode, y)));	  emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)		     (gen_imagpart (submode, x), gen_imagpart (submode, y)));	}      return get_last_insn ();    }  /* This will handle any multi-word mode that lacks a move_insn pattern.     However, you will get better code if you define such patterns,     even if they must turn into multiple assembler instructions.  */  else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)    {      rtx last_insn = 0;      rtx insns;      #ifdef PUSH_ROUNDING      /* If X is a push on the stack, do the push now and replace	 X with a reference to the stack pointer.  */      if (push_operand (x, GET_MODE (x)))	{	  anti_adjust_stack (GEN_INT (GET_MODE_SIZE (GET_MODE (x))));	  x = change_address (x, VOIDmode, stack_pointer_rtx);	}#endif			           /* Show the output dies here.  */      emit_insn (gen_rtx (CLOBBER, VOIDmode, x));      for (i = 0;	   i < (GET_MODE_SIZE (mode)  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;	   i++)	{	  rtx xpart = operand_subword (x, i, 1, mode);	  rtx ypart = operand_subword (y, i, 1, mode);	  /* If we can't get a part of Y, put Y into memory if it is a	     constant.  Otherwise, force it into a register.  If we still	     can't get a part of Y, abort.  */	  if (ypart == 0 && CONSTANT_P (y))	    {	      y = force_const_mem (mode, y);	      ypart = operand_subword (y, i, 1, mode);	    }	  else if (ypart == 0)	    ypart = operand_subword_force (y, i, mode);	  if (xpart == 0 || ypart == 0)	    abort ();	  last_insn = emit_move_insn (xpart, ypart);	}      return last_insn;    }  else    abort ();}/* Pushing data onto the stack.  *//* Push a block of length SIZE (perhaps variable)   and return an rtx to address the beginning of the block.   Note that it is not possible for the value returned to be a QUEUED.   The value may be virtual_outgoing_args_rtx.   EXTRA is the number of bytes of padding to push in addition to SIZE.   BELOW nonzero means this padding comes at low addresses;   otherwise, the padding comes at high addresses.  */rtxpush_block (size, extra, below)     rtx size;     int extra, below;{  register rtx temp;  size = convert_modes (Pmode, ptr_mode, size, 1);  if (CONSTANT_P (size))    anti_adjust_stack (plus_constant (size, extra));  else if (GET_CODE (size) == REG && extra == 0)    anti_adjust_stack (size);  else    {      rtx temp = copy_to_mode_reg (Pmode, size);      if (extra != 0)	temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),			     temp, 0, OPTAB_LIB_WIDEN);      anti_adjust_stack (temp);    }#ifdef STACK_GROWS_DOWNWARD  temp = virtual_outgoing_args_rtx;  if (extra != 0 && below)    temp = plus_constant (temp, extra);#else  if (GET_CODE (size) == CONST_INT)    temp = plus_constant (virtual_outgoing_args_rtx,			  - INTVAL (size) - (below ? 0 : extra));  else if (extra != 0 && !below)    temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,		    negate_rtx (Pmode, plus_constant (size, extra)));  else    temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,		    negate_rtx (Pmode, size));#endif  return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);}rtxgen_push_operand (){  return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);}/* Generate code to push X onto the stack, assuming it has mode MODE and   type TYPE.   MODE is redundant except when X is a CONST_INT (since they don't   carry mode info).   SIZE is an rtx for the size of data to be copied (in bytes),   needed only if X is BLKmode.   ALIGN (in bytes) is maximum alignment we can assume.   If PARTIAL and REG are both nonzero, then copy that many of the first   words of X into registers starting with REG, and push the rest of X.   The amount of space pushed is decreased by PARTIAL words,   rounded *down* to a multiple of PARM_BOUNDARY.   REG must be a hard register in this case.   If REG is zero but PARTIAL is not, take any all others actions for an   argument partially in registers, but do not actually load any   registers.   EXTRA is the amount in bytes of extra space to leave next to this arg.   This is ignored if an argument block has already been allocated.   On a machine that lacks real push insns, ARGS_ADDR is the address of   the bottom of the argument block for this call.  We use indexing off there   to store the arg.  On machines with push insns, ARGS_ADDR is 0 when a   argument block has not been preallocated.   ARGS_SO_FAR is the size of args previously pushed for this call.  */voidemit_push_insn (x, mode, type, size, align, partial, reg, extra,		args_addr, args_so_far)     register rtx x;     enum machine_mode mode;     tree type;     rtx size;     int align;     int partial;     rtx reg;     int extra;     rtx args_addr;     rtx args_so_far;{  rtx xinner;  enum direction stack_direction#ifdef STACK_GROWS_DOWNWARD    = downward;#else    = upward;#endif  /* Decide where to pad the argument: `downward' for below,     `upward' for above, or `none' for don't pad it.     Default is below for small data on big-endian machines; else above.  */  enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);  /* Invert direction if stack is post-update.  */  if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC)    if (where_pad != none)      where_pad = (where_pad == downward ? upward : downward);  xinner = x = protect_from_queue (x, 0);  if (mode == BLKmode)    {      /* Copy a block into the stack, entirely or partially.  */      register rtx temp;      int used = partial * UNITS_PER_WORD;      int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);      int skip;            if (size == 0)	abort ();      used -= offset;      /* USED is now the # of bytes we need not copy to the stack	 because registers will take care of them.  */      if (partial != 0)	xinner = change_address (xinner, BLKmode,				 plus_constant (XEXP (xinner, 0), used));      /* If the partial register-part of the arg counts in its stack size,	 skip the part of stack space corresponding to the registers.	 Otherwise, start copying to the beginning of the stack space,	 by setting SKIP to 0.  */#ifndef REG_PARM_STACK_SPACE      skip = 0;#else      skip = used;#endif#ifdef PUSH_ROUNDING      /* Do it with several push insns if that doesn't take lots of insns	 and if there is no difficulty with push insns that skip bytes	 on the stack for alignment purposes.  */      if (args_addr == 0	  && GET_CODE (size) == CONST_INT	  && skip == 0	  && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)	      < MOVE_RATIO)	  /* Here we avoid the case of a structure whose weak alignment	     forces many pushes of a small amount of data,	     and such small pushes do rounding that causes trouble.  */	  && ((! SLOW_UNALIGNED_ACCESS)	      || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT	      || PUSH_ROUNDING (align) == align)	  && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))	{	  /* Push padding now if padding above and stack grows down,	     or if padding below and stack grows up.	     But if space already allocated, this has already been done.  */	  if (extra && args_addr == 0	      && where_pad != none && where_pad != stack_direction)	    anti_adjust_stack (GEN_INT (extra));	  move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,			  INTVAL (size) - used, align);	}      else#endif /* PUSH_ROUNDING */	{	  /* Otherwise make space on the stack and copy the data	     to the address of that space.  */	  /* Deduct words put into registers from the size we must copy.  */	  if (partial != 0)	    {	      if (GET_CODE (size) == CONST_INT)		size = GEN_INT (INTVAL (size) - used);	      else		size = expand_binop (GET_MODE (size), sub_optab, size,				     GEN_INT (used), NULL_RTX, 0,				     OPTAB_LIB_WIDEN);	    }	  /* Get the address of the stack space.	     In this case, we do not deal with EXTRA separately.	     A single stack adjust will do.  */	  if (! args_addr)	    {	      temp = push_block (size, extra, where_pad == downward);	      extra = 0;	    }	  else if (GET_CODE (args_so_far) == CONST_INT)	    temp = memory_address (BLKmode,				   plus_constant (args_addr,						  skip + INTVAL (args_so_far)));	  else	    temp = memory_address (BLKmode,				   plus_constant (gen_rtx (PLUS, Pmode,							   args_addr, args_so_far),						  skip));	  /* TEMP is the address of the block.  Copy the data there.  */	  if (GET_CODE (size) == CONST_INT	      && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)		  < MOVE_RATIO))	    {	      move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,			      INTVAL (size), align);	      goto ret;	    }	  /* Try the most limited insn first, because there's no point	     including more than one in the machine description unless	     the more limited one has some advantage.  */#ifdef HAVE_movstrqi	  if (HAVE_movstrqi	      && GET_CODE (size) == CONST_INT	      && ((unsigned) INTVAL (size)		  < (1 << (GET_MODE_BITSIZE (QImode) - 1))))	    {	      rtx pat = gen_movstrqi (gen_rtx (MEM, BLKmode, temp),				      xinner, size, GEN_INT (align));	      if (pat != 0)		{		  emit_insn (pat);		  goto ret;		}	    }#endif#ifdef HAVE_movstrhi	  if (HAVE_movstrhi	      && GET_CODE (size) == CONST_INT	      && ((unsigned) INTVAL (size)		  < (1 << (GET_MODE_BITSIZE (HImode) - 1))))	    {	      rtx pat = gen_movstrhi (gen_rtx (MEM, BLKmode, temp),				      xinner, size, GEN_INT (align));	      if (pat != 0)		{		  emit_insn (pat);		  goto ret;		}	    }#endif#ifdef HAVE_movstrsi	  if (HAVE_movstrsi)	    {	      rtx pat = gen_movstrsi (gen_rtx (MEM, BLKmode, temp),				      xinner, size, GEN_INT (align));	      if (pat != 0)		{		  emit_insn (pat);		  goto ret;		}	    }#endif#ifdef HAVE_movstrdi	  if (HAVE_movstrdi)	    {	      rtx pat = gen_movstrdi (gen_rtx (MEM, BLKmode, temp),				      xinner, size, GEN_INT (align));	      if (pat != 0)		{		  emit_insn (pat);		  goto ret;		}	    }#endif#ifndef ACCUMULATE_OUTGOING_ARGS	  /* If the source is referenced relative to the stack pointer,	     copy it to another register to stabilize it.  We do not need	     to do this if we know that we won't be changing sp.  */	  if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)	      ||

⌨️ 快捷键说明

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