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

📄 reg-stack.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
					 win);		  IOR_HARD_REG_SET (block_out_reg_set[jump_block],				    block_stack_in[block].reg_set);		  block = jump_block;		  must_restart = 1;		win:		  ;		}	    }	  if (must_restart)	    continue;	}      if (block_drops_in[block])	IOR_HARD_REG_SET (block_out_reg_set[block-1],			  block_stack_in[block].reg_set);      block -= 1;    }  {    /* If any reg is live at the start of the first block of a       function, then we must guarantee that the reg holds some value by       generating our own "load" of that register.  Otherwise a 387 would       fault trying to access an empty register. */    HARD_REG_SET empty_regs;    CLEAR_HARD_REG_SET (empty_regs);    GO_IF_HARD_REG_SUBSET (block_stack_in[0].reg_set, empty_regs,			   no_live_regs);  }  /* Load zero into each live register.  The fact that a register     appears live at the function start does not necessarily imply an error     in the user program: it merely means that we could not determine that     there wasn't such an error, just as -Wunused sometimes gives     "incorrect" warnings.  In those cases, these initializations will do     no harm.     Note that we are inserting virtual register references here:     these insns must be processed by convert_regs later.  Also, these     insns will not be in block_number, so BLOCK_NUM() will fail for them. */  for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--)    if (TEST_HARD_REG_BIT (block_stack_in[0].reg_set, reg))      {	rtx init_rtx;	init_rtx = gen_rtx (SET, VOIDmode, FP_mode_reg[reg][(int) DFmode],			    CONST0_RTX (DFmode));	block_begin[0] = emit_insn_after (init_rtx, first);	PUT_MODE (block_begin[0], QImode);	CLEAR_HARD_REG_BIT (block_stack_in[0].reg_set, reg);      } no_live_regs:  ;}/*****************************************************************************   This section deals with stack register substitution, and forms the second   pass over the RTL. *****************************************************************************//* Replace REG, which is a pointer to a stack reg RTX, with an RTX for   the desired hard REGNO. */static voidreplace_reg (reg, regno)     rtx *reg;     int regno;{  if (regno < FIRST_STACK_REG || regno > LAST_STACK_REG      || ! STACK_REG_P (*reg))    abort ();  if (GET_MODE_CLASS (GET_MODE (*reg)) != MODE_FLOAT)    abort ();  *reg = FP_mode_reg[regno][(int) GET_MODE (*reg)];}/* Remove a note of type NOTE, which must be found, for register   number REGNO from INSN.  Remove only one such note. */static voidremove_regno_note (insn, note, regno)     rtx insn;     enum reg_note note;     int regno;{  register rtx *note_link, this;  note_link = &REG_NOTES(insn);  for (this = *note_link; this; this = XEXP (this, 1))    if (REG_NOTE_KIND (this) == note	&& REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno)      {	*note_link = XEXP (this, 1);	return;      }    else      note_link = &XEXP (this, 1);  abort ();}/* Find the hard register number of virtual register REG in REGSTACK.   The hard register number is relative to the top of the stack.  -1 is   returned if the register is not found. */static intget_hard_regnum (regstack, reg)     stack regstack;     rtx reg;{  int i;  if (! STACK_REG_P (reg))    abort ();  for (i = regstack->top; i >= 0; i--)    if (regstack->reg[i] == REGNO (reg))      break;  return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;}/* Delete INSN from the RTL.  Mark the insn, but don't remove it from   the chain of insns.  Doing so could confuse block_begin and block_end   if this were the only insn in the block. */static voiddelete_insn_for_stacker (insn)     rtx insn;{  PUT_CODE (insn, NOTE);  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;  NOTE_SOURCE_FILE (insn) = 0;  INSN_DELETED_P (insn) = 1;}/* Emit an insn to pop virtual register REG before or after INSN.   REGSTACK is the stack state after INSN and is updated to reflect this   pop.  WHEN is either emit_insn_before or emit_insn_after.  A pop insn   is represented as a SET whose destination is the register to be popped   and source is the top of stack.  A death note for the top of stack   cases the movdf pattern to pop. */static rtxemit_pop_insn (insn, regstack, reg, when)     rtx insn;     stack regstack;     rtx reg;     rtx (*when)();{  rtx pop_insn, pop_rtx;  int hard_regno;  hard_regno = get_hard_regnum (regstack, reg);  if (hard_regno < FIRST_STACK_REG)    abort ();  pop_rtx = gen_rtx (SET, VOIDmode, FP_mode_reg[hard_regno][(int) DFmode],		     FP_mode_reg[FIRST_STACK_REG][(int) DFmode]);  pop_insn = (*when) (pop_rtx, insn);  PUT_MODE (pop_insn, VOIDmode);  REG_NOTES (pop_insn) = gen_rtx (EXPR_LIST, REG_DEAD,				  FP_mode_reg[FIRST_STACK_REG][(int) DFmode],				  REG_NOTES (pop_insn));  regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]    = regstack->reg[regstack->top];  regstack->top -= 1;  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (reg));  return pop_insn;}/* Emit an insn before or after INSN to swap virtual register REG with the   top of stack.  WHEN should be `emit_insn_before' or `emit_insn_before'   REGSTACK is the stack state before the swap, and is updated to reflect   the swap.  A swap insn is represented as a PARALLEL of two patterns:   each pattern moves one reg to the other.   If REG is already at the top of the stack, no insn is emitted. */static voidemit_hard_swap_insn (insn, regstack, hard_regno, when)     rtx insn;     stack regstack;     int hard_regno;     rtx (*when)();{  rtx gen_swapdf();  rtx swap_rtx, swap_insn;  int tmp, other;  if (hard_regno == FIRST_STACK_REG)    return;  swap_rtx = gen_swapdf (FP_mode_reg[hard_regno][(int) DFmode],			 FP_mode_reg[FIRST_STACK_REG][(int) DFmode]);  swap_insn = (*when) (swap_rtx, insn);  PUT_MODE (swap_insn, VOIDmode);  other = regstack->top - (hard_regno - FIRST_STACK_REG);  tmp = regstack->reg[other];  regstack->reg[other] = regstack->reg[regstack->top];  regstack->reg[regstack->top] = tmp;}/* Emit an insn before or after INSN to swap virtual register REG with the   top of stack.  See comments before emit_hard_swap_insn. */static voidemit_swap_insn (insn, regstack, reg, when)     rtx insn;     stack regstack;     rtx reg;     rtx (*when)();{  int hard_regno;  hard_regno = get_hard_regnum (regstack, reg);  if (hard_regno < FIRST_STACK_REG)    abort ();  emit_hard_swap_insn (insn, regstack, hard_regno, when);}/* Handle a move to or from a stack register in PAT, which is in INSN.   REGSTACK is the current stack. */static voidmove_for_stack_reg (insn, regstack, pat)     rtx insn;     stack regstack;     rtx pat;{  rtx *src =  get_true_reg (&SET_SRC (pat));  rtx *dest = get_true_reg (&SET_DEST (pat));  rtx note;  if (STACK_REG_P (*src) && STACK_REG_P (*dest))    {      /* Write from one stack reg to another.  If SRC dies here, then	 just change the register mapping and delete the insn. */      note = find_regno_note (insn, REG_DEAD, REGNO (*src));      if (note)	{	  int i;	  /* If this is a no-op move, there must not be a REG_DEAD note. */	  if (REGNO (*src) == REGNO (*dest))	    abort ();	  for (i = regstack->top; i >= 0; i--)	    if (regstack->reg[i] == REGNO (*src))	      break;	  /* The source must be live, and the dest must be dead. */	  if (i < 0 || get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG)	    abort ();	  /* It is possible that the dest is unused after this insn.	     If so, just pop the src. */	  if (find_regno_note (insn, REG_UNUSED, REGNO (*dest)))	    {	      emit_pop_insn (insn, regstack, *src, emit_insn_after);	      delete_insn_for_stacker (insn);	      return;	    }	  regstack->reg[i] = REGNO (*dest);	  SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src));	  delete_insn_for_stacker (insn);	  return;	}      /* The source reg does not die. */      /* If this appears to be a no-op move, delete it, or else it	 will confuse the machine description output patterns. But if	 it is REG_UNUSED, we must pop the reg now, as per-insn processing	 for REG_UNUSED will not work for deleted insns. */      if (REGNO (*src) == REGNO (*dest))	{	  if (find_regno_note (insn, REG_UNUSED, REGNO (*dest)))	    emit_pop_insn (insn, regstack, *dest, emit_insn_after);	  delete_insn_for_stacker (insn);	  return;	}      /* The destination ought to be dead */      if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG)	abort ();      replace_reg (src, get_hard_regnum (regstack, *src));      regstack->reg[++regstack->top] = REGNO (*dest);      SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));      replace_reg (dest, FIRST_STACK_REG);    }  else if (STACK_REG_P (*src))    {      /* Save from a stack reg to MEM, or possibly integer reg.  Since	 only top of stack may be saved, emit an exchange first if	 needs be. */      emit_swap_insn (insn, regstack, *src, emit_insn_before);      note = find_regno_note (insn, REG_DEAD, REGNO (*src));      if (note)	{	  replace_reg (&XEXP (note, 0), FIRST_STACK_REG);	  regstack->top--;	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src));	}      replace_reg (src, FIRST_STACK_REG);    }  else if (STACK_REG_P (*dest))    {      /* Load from MEM, or possibly integer REG or constant, into the	 stack regs.  The actual target is always the top of the	 stack. The stack mapping is changed to reflect that DEST is	 now at top of stack.  */      /* The destination ought to be dead */      if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG)	abort ();      if (regstack->top >= REG_STACK_SIZE)	abort ();      regstack->reg[++regstack->top] = REGNO (*dest);      SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));      replace_reg (dest, FIRST_STACK_REG);    }  else    abort ();}/* Handle a comparison.  Special care needs to be taken to avoid   causing comparisons that a 387 cannot do correctly, such as EQ.   Also, a pop insn may need to be emitted.  The 387 does have an   `fcompp' insn that can pop two regs, but it is sometimes too expensive   to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to   set up. */static voidcompare_for_stack_reg (insn, regstack, pat)     rtx insn;     stack regstack;     rtx pat;{  rtx *src1, *src2;  rtx src1_note, src2_note;  src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));  src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));  /* The first argument must always be a stack reg. */  /* ??? why? */  if (! STACK_REG_P (*src1))    abort ();  /* We will fix any death note later. */  src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));  if (STACK_REG_P (*src2))    src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));  else    src2_note = 0;  emit_swap_insn (insn, regstack, *src1, emit_insn_before);  replace_reg (src1, FIRST_STACK_REG);  if (STACK_REG_P (*src2))    replace_reg (src2, get_hard_regnum (regstack, *src2));  if (src1_note)    {      CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (XEXP (src1_note, 0)));      replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);      regstack->top--;    }  /* If the second operand dies, handle that.  But if the operands are     the same stack register, don't bother, because only one death is     needed, and it was just handled. */  if (src2_note      && ! (STACK_REG_P (*src1)	    && STACK_REG_P (*src2)	    && REGNO (*src1) == REGNO (*src2)))    {      /* As a special case, two regs may die in this insn if src2 is	 next to top of stack and the top of stack also dies.  Since	 we have already popped src1, "next to top of stack" is really	 at top (FIRST_STACK_REG) now. */      if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG	  && src1_note)	{	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (XEXP (src2_note, 0)));	  replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);	  regstack->top--;	}      else	{	  /* The 386 can only represent death of the first operand in	     the case handled above.  In all other cases, emit a separate	     pop and remove the death note from here. */	  link_cc0_insns (insn);	  remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0)));	  emit_pop_insn (insn, regstack, XEXP (src2_note, 0),			 emit_insn_after);	}    }

⌨️ 快捷键说明

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