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

📄 explow.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
{  return copy_to_mode_reg (Pmode, x);}/* Like copy_to_reg but always give the new register mode MODE   in case X is a constant.  */rtxcopy_to_mode_reg (mode, x)     enum machine_mode mode;     rtx x;{  register rtx temp = gen_reg_rtx (mode);    /* If not an operand, must be an address with PLUS and MULT so     do the computation.  */   if (! general_operand (x, VOIDmode))    x = force_operand (x, temp);  if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)    abort ();  if (x != temp)    emit_move_insn (temp, x);  return temp;}/* Load X into a register if it is not already one.   Use mode MODE for the register.   X should be valid for mode MODE, but it may be a constant which   is valid for all integer modes; that's why caller must specify MODE.   The caller must not alter the value in the register we return,   since we mark it as a "constant" register.  */rtxforce_reg (mode, x)     enum machine_mode mode;     rtx x;{  register rtx temp, insn;  if (GET_CODE (x) == REG)    return x;  temp = gen_reg_rtx (mode);  insn = emit_move_insn (temp, x);  /* Let optimizers know that TEMP's value never changes     and that X can be substituted for it.  */  if (CONSTANT_P (x))    {      rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);      if (note)	XEXP (note, 0) = x;      else	REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, x, REG_NOTES (insn));    }  return temp;}/* If X is a memory ref, copy its contents to a new temp reg and return   that reg.  Otherwise, return X.  */rtxforce_not_mem (x)     rtx x;{  register rtx temp;  if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)    return x;  temp = gen_reg_rtx (GET_MODE (x));  emit_move_insn (temp, x);  return temp;}/* Copy X to TARGET (if it's nonzero and a reg)   or to a new temp reg and return that reg.   MODE is the mode to use for X in case it is a constant.  */rtxcopy_to_suggested_reg (x, target, mode)     rtx x, target;     enum machine_mode mode;{  register rtx temp;  if (target && GET_CODE (target) == REG)    temp = target;  else    temp = gen_reg_rtx (mode);  emit_move_insn (temp, x);  return temp;}/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).   This pops when ADJUST is positive.  ADJUST need not be constant.  */voidadjust_stack (adjust)     rtx adjust;{  rtx temp;  adjust = protect_from_queue (adjust, 0);  if (adjust == const0_rtx)    return;  temp = expand_binop (Pmode,#ifdef STACK_GROWS_DOWNWARD		       add_optab,#else		       sub_optab,#endif		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,		       OPTAB_LIB_WIDEN);  if (temp != stack_pointer_rtx)    emit_move_insn (stack_pointer_rtx, temp);}/* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).   This pushes when ADJUST is positive.  ADJUST need not be constant.  */voidanti_adjust_stack (adjust)     rtx adjust;{  rtx temp;  adjust = protect_from_queue (adjust, 0);  if (adjust == const0_rtx)    return;  temp = expand_binop (Pmode,#ifdef STACK_GROWS_DOWNWARD		       sub_optab,#else		       add_optab,#endif		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,		       OPTAB_LIB_WIDEN);  if (temp != stack_pointer_rtx)    emit_move_insn (stack_pointer_rtx, temp);}/* Round the size of a block to be pushed up to the boundary required   by this machine.  SIZE is the desired size, which need not be constant.  */rtxround_push (size)     rtx size;{#ifdef STACK_BOUNDARY  int align = STACK_BOUNDARY / BITS_PER_UNIT;  if (align == 1)    return size;  if (GET_CODE (size) == CONST_INT)    {      int new = (INTVAL (size) + align - 1) / align * align;      if (INTVAL (size) != new)	size = GEN_INT (new);    }  else    {      size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, GEN_INT (align),			    NULL_RTX, 1);      size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);    }#endif /* STACK_BOUNDARY */  return size;}/* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer   to a previously-created save area.  If no save area has been allocated,   this function will allocate one.  If a save area is specified, it   must be of the proper mode.   The insns are emitted after insn AFTER, if nonzero, otherwise the insns   are emitted at the current position.  */voidemit_stack_save (save_level, psave, after)     enum save_level save_level;     rtx *psave;     rtx after;{  rtx sa = *psave;  /* The default is that we use a move insn and save in a Pmode object.  */  rtx (*fcn) () = gen_move_insn;  enum machine_mode mode = Pmode;  /* See if this machine has anything special to do for this kind of save.  */  switch (save_level)    {#ifdef HAVE_save_stack_block    case SAVE_BLOCK:      if (HAVE_save_stack_block)	{	  fcn = gen_save_stack_block;	  mode = insn_operand_mode[CODE_FOR_save_stack_block][0];	}      break;#endif#ifdef HAVE_save_stack_function    case SAVE_FUNCTION:      if (HAVE_save_stack_function)	{	  fcn = gen_save_stack_function;	  mode = insn_operand_mode[CODE_FOR_save_stack_function][0];	}      break;#endif#ifdef HAVE_save_stack_nonlocal    case SAVE_NONLOCAL:      if (HAVE_save_stack_nonlocal)	{	  fcn = gen_save_stack_nonlocal;	  mode = insn_operand_mode[CODE_FOR_save_stack_nonlocal][0];	}      break;#endif    }  /* If there is no save area and we have to allocate one, do so.  Otherwise     verify the save area is the proper mode.  */  if (sa == 0)    {      if (mode != VOIDmode)	{	  if (save_level == SAVE_NONLOCAL)	    *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);	  else	    *psave = sa = gen_reg_rtx (mode);	}    }  else    {      if (mode == VOIDmode || GET_MODE (sa) != mode)	abort ();    }  if (sa != 0)    sa = validize_mem (sa);  if (after)    {      rtx seq;      start_sequence ();      emit_insn (fcn (sa, stack_pointer_rtx));      seq = gen_sequence ();      end_sequence ();      emit_insn_after (seq, after);    }  else    emit_insn (fcn (sa, stack_pointer_rtx));}/* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save   area made by emit_stack_save.  If it is zero, we have nothing to do.    Put any emitted insns after insn AFTER, if nonzero, otherwise at    current position.  */voidemit_stack_restore (save_level, sa, after)     enum save_level save_level;     rtx after;     rtx sa;{  /* The default is that we use a move insn.  */  rtx (*fcn) () = gen_move_insn;  /* See if this machine has anything special to do for this kind of save.  */  switch (save_level)    {#ifdef HAVE_restore_stack_block    case SAVE_BLOCK:      if (HAVE_restore_stack_block)	fcn = gen_restore_stack_block;      break;#endif#ifdef HAVE_restore_stack_function    case SAVE_FUNCTION:      if (HAVE_restore_stack_function)	fcn = gen_restore_stack_function;      break;#endif#ifdef HAVE_restore_stack_nonlocal    case SAVE_NONLOCAL:      if (HAVE_restore_stack_nonlocal)	fcn = gen_restore_stack_nonlocal;      break;#endif    }  if (sa != 0)    sa = validize_mem (sa);  if (after)    {      rtx seq;      start_sequence ();      emit_insn (fcn (stack_pointer_rtx, sa));      seq = gen_sequence ();      end_sequence ();      emit_insn_after (seq, after);    }  else    emit_insn (fcn (stack_pointer_rtx, sa));}/* Return an rtx representing the address of an area of memory dynamically   pushed on the stack.  This region of memory is always aligned to   a multiple of BIGGEST_ALIGNMENT.   Any required stack pointer alignment is preserved.   SIZE is an rtx representing the size of the area.   TARGET is a place in which the address can be placed.   KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */rtxallocate_dynamic_stack_space (size, target, known_align)     rtx size;     rtx target;     int known_align;{  /* Ensure the size is in the proper mode.  */  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)    size = convert_to_mode (Pmode, size, 1);  /* We will need to ensure that the address we return is aligned to     BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't     always know its final value at this point in the compilation (it      might depend on the size of the outgoing parameter lists, for     example), so we must align the value to be returned in that case.     (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if     STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).     We must also do an alignment operation on the returned value if     the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.     If we have to align, we must leave space in SIZE for the hole     that might result from the alignment operation.  */#if defined (STACK_DYNAMIC_OFFSET) || defined(STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS)#define MUST_ALIGN#endif#if ! defined (MUST_ALIGN) && (!defined(STACK_BOUNDARY) || STACK_BOUNDARY < BIGGEST_ALIGNMENT)#define MUST_ALIGN#endif#ifdef MUST_ALIGN#if 0 /* It turns out we must always make extra space, if MUST_ALIGN	 because we must always round the address up at the end,	 because we don't know whether the dynamic offset	 will mess up the desired alignment.  */  /* If we have to round the address up regardless of known_align,     make extra space regardless, also.  */  if (known_align % BIGGEST_ALIGNMENT != 0)#endif    {      if (GET_CODE (size) == CONST_INT)	size = GEN_INT (INTVAL (size)			+ (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1));      else	size = expand_binop (Pmode, add_optab, size,			     GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),			     NULL_RTX, 1, OPTAB_LIB_WIDEN);    }#endif#ifdef SETJMP_VIA_SAVE_AREA  /* If setjmp restores regs from a save area in the stack frame,     avoid clobbering the reg save area.  Note that the offset of     virtual_incoming_args_rtx includes the preallocated stack args space.     It would be no problem to clobber that, but it's on the wrong side     of the old save area.  */  {    rtx dynamic_offset      = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,		      stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);    size = expand_binop (Pmode, add_optab, size, dynamic_offset,			 NULL_RTX, 1, OPTAB_LIB_WIDEN);  }#endif /* SETJMP_VIA_SAVE_AREA */  /* Round the size to a multiple of the required stack alignment.     Since the stack if presumed to be rounded before this allocation,     this will maintain the required alignment.     If the stack grows downward, we could save an insn by subtracting     SIZE from the stack pointer and then aligning the stack pointer.     The problem with this is that the stack pointer may be unaligned     between the execution of the subtraction and alignment insns and     some machines do not allow this.  Even on those that do, some     signal handlers malfunction if a signal should occur between those     insns.  Since this is an extremely rare event, we have no reliable     way of knowing which systems have this problem.  So we avoid even     momentarily mis-aligning the stack.  */#ifdef STACK_BOUNDARY  /* If we added a variable amount to SIZE,     we can no longer assume it is aligned.  */#if !defined (SETJMP_VIA_SAVE_AREA) && !defined (MUST_ALIGN)  if (known_align % STACK_BOUNDARY != 0)#endif    size = round_push (size);#endif  do_pending_stack_adjust ();  /* Don't use a TARGET that isn't a pseudo.  */  if (target == 0 || GET_CODE (target) != REG      || REGNO (target) < FIRST_PSEUDO_REGISTER)    target = gen_reg_rtx (Pmode);  mark_reg_pointer (target);#ifndef STACK_GROWS_DOWNWARD  emit_move_insn (target, virtual_stack_dynamic_rtx);#endif  /* Perform the required allocation from the stack.  Some systems do     this differently than simply incrementing/decrementing from the     stack pointer.  */#ifdef HAVE_allocate_stack  if (HAVE_allocate_stack)    {      enum machine_mode mode	= insn_operand_mode[(int) CODE_FOR_allocate_stack][0];      if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]	  && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])		(size, mode)))	size = copy_to_mode_reg (mode, size);      emit_insn (gen_allocate_stack (size));    }  else#endif    anti_adjust_stack (size);#ifdef STACK_GROWS_DOWNWARD  emit_move_insn (target, virtual_stack_dynamic_rtx);#endif#ifdef MUST_ALIGN#if 0  /* Even if we know the stack pointer has enough alignment,	  there's no way to tell whether virtual_stack_dynamic_rtx shares that	  alignment, so we still need to round the address up.  */  if (known_align % BIGGEST_ALIGNMENT != 0)#endif    {      target = expand_divmod (0, CEIL_DIV_EXPR, Pmode, target,			      GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),			      NULL_RTX, 1);      target = expand_mult (Pmode, target,			    GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),			    NULL_RTX, 1);    }#endif    /* Some systems require a particular insn to refer to the stack     to make the pages exist.  */#ifdef HAVE_probe  if (HAVE_probe)    emit_insn (gen_probe ());#endif  return target;}/* Return an rtx representing the register or memory location   in which a scalar value of data type VALTYPE   was returned by a function call to function FUNC.   FUNC is a FUNCTION_DECL node if the precise function is known,   otherwise 0.  */rtxhard_function_value (valtype, func)     tree valtype;     tree func;{  return FUNCTION_VALUE (valtype, func);}/* Return an rtx representing the register or memory location   in which a scalar value of mode MODE was returned by a library call.  */rtxhard_libcall_value (mode)     enum machine_mode mode;{  return LIBCALL_VALUE (mode);}

⌨️ 快捷键说明

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