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

📄 reg-stack.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	    }	  else if (GET_CODE (pat) == SET		   && SET_DEST (pat) == pc_rtx		   && uses_reg_or_mem (SET_SRC (pat)))	    computed_jump = 1;		    	  if (computed_jump)	    {	      for (x = label_value_list; x; x = XEXP (x, 1))		record_label_references (insn,					 gen_rtx (LABEL_REF, VOIDmode,						  XEXP (x, 0)));	      for (x = forced_labels; x; x = XEXP (x, 1))		record_label_references (insn,					 gen_rtx (LABEL_REF, VOIDmode,						  XEXP (x, 0)));	    }	  record_label_references (insn, pat);	}    }}/* Return 1 if X contain a REG or MEM that is not in the constant pool.  */static intuses_reg_or_mem (x)     rtx x;{  enum rtx_code code = GET_CODE (x);  int i, j;  char *fmt;  if (code == REG      || (code == MEM	  && ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF		&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))))    return 1;  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e'	  && uses_reg_or_mem (XEXP (x, i)))	return 1;      if (fmt[i] == 'E')	for (j = 0; j < XVECLEN (x, i); j++)	  if (uses_reg_or_mem (XVECEXP (x, i, j)))	    return 1;    }  return 0;}/* If current function returns its result in an fp stack register,   return the REG.  Otherwise, return 0.  */static rtxstack_result (decl)     tree decl;{  rtx result = DECL_RTL (DECL_RESULT (decl));  if (result != 0      && ! (GET_CODE (result) == REG	    && REGNO (result) < FIRST_PSEUDO_REGISTER))    {#ifdef FUNCTION_OUTGOING_VALUE      result        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);#else      result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);#endif    }  return result != 0 && STACK_REG_P (result) ? result : 0;}/* Determine the which registers are live at the start of each basic   block of the function whose first insn is FIRST.   First, if the function returns a real_type, mark the function   return type as live at each return point, as the RTL may not give any   hint that the register is live.   Then, start with the last block and work back to the first block.   Similarly, work backwards within each block, insn by insn, recording   which regs are dead and which are used (and therefore live) in the   hard reg set of block_stack_in[].   After processing each basic block, if there is a label at the start   of the block, propagate the live registers to all jumps to this block.   As a special case, if there are regs live in this block, that are   not live in a block containing a jump to this label, and the block   containing the jump has already been processed, we must propagate this   block's entry register life back to the block containing the jump, and   restart life analysis from there.   In the worst case, this function may traverse the insns   REG_STACK_SIZE times.  This is necessary, since a jump towards the end   of the insns may not know that a reg is live at a target that is early   in the insns.  So we back up and start over with the new reg live.   If there are registers that are live at the start of the function,   insns are emitted to initialize these registers.  Something similar is   done after CALL_INSNs in record_reg_life. */static voidstack_reg_life_analysis (first, stackentry)     rtx first;     HARD_REG_SET *stackentry;{  int reg, block;  struct stack_def regstack;   {     rtx retvalue;     if (retvalue = stack_result (current_function_decl))      {        /* Find all RETURN insns and mark them. */        for (block = blocks - 1; --block >= 0;)	   if (GET_CODE (block_end[block]) == JUMP_INSN	     && GET_CODE (PATTERN (block_end[block])) == RETURN)	      mark_regs_pat (retvalue, block_out_reg_set+block);        /* Mark off the end of last block if we "fall off" the end of the	   function into the epilogue. */        if (GET_CODE (block_end[blocks-1]) != JUMP_INSN	    || GET_CODE (PATTERN (block_end[blocks-1])) == RETURN)	  mark_regs_pat (retvalue, block_out_reg_set+blocks-1);      }   }  /* now scan all blocks backward for stack register use */  block = blocks - 1;  while (block >= 0)    {      register rtx insn, prev;      /* current register status at last instruction */      COPY_HARD_REG_SET (regstack.reg_set, block_out_reg_set[block]);      prev = block_end[block];      do	{	  insn = prev;	  prev = PREV_INSN (insn);	  /* If the insn is a CALL_INSN, we need to ensure that	     everything dies.  But otherwise don't process unless there	     are some stack regs present. */	  if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)	    record_reg_life (insn, block, &regstack);	} while (insn != block_begin[block]);      /* Set the state at the start of the block.  Mark that no	 register mapping information known yet. */      COPY_HARD_REG_SET (block_stack_in[block].reg_set, regstack.reg_set);      block_stack_in[block].top = -2;      /* If there is a label, propagate our register life to all jumps	 to this label. */      if (GET_CODE (insn) == CODE_LABEL)	{	  register rtx label;	  int must_restart = 0;	  for (label = LABEL_REFS (insn); label != insn;	       label = LABEL_NEXTREF (label))	    {	      int jump_block = BLOCK_NUM (CONTAINING_INSN (label));	      if (jump_block < block)		IOR_HARD_REG_SET (block_out_reg_set[jump_block],				  block_stack_in[block].reg_set);	      else		{		  /* The block containing the jump has already been		     processed.  If there are registers that were not known		     to be live then, but are live now, we must back up		     and restart life analysis from that point with the new		     life information. */		  GO_IF_HARD_REG_SUBSET (block_stack_in[block].reg_set,					 block_out_reg_set[jump_block],					 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. */  /* Load zero into each live register.  The fact that a register     appears live at the function start necessarily implies an error     in the user program: it means that (unless the offending code is *never*     executed) this program is using uninitialised floating point     variables.  In order to keep broken code like this happy, we initialise     those variables with zero.     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)        && ! TEST_HARD_REG_BIT (*stackentry, reg))      {	rtx init_rtx;	init_rtx = gen_rtx (SET, VOIDmode, FP_MODE_REG(reg, 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);      }}/*****************************************************************************   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 ();  switch (GET_MODE_CLASS (GET_MODE (*reg)))   {     default: abort ();     case MODE_FLOAT:     case MODE_COMPLEX_FLOAT:;   }  *reg = FP_MODE_REG (regno, 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;}/* 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, DFmode),		     FP_MODE_REG (FIRST_STACK_REG, DFmode));  pop_insn = (*when) (pop_rtx, insn);  /* ??? This used to be VOIDmode, but that seems wrong. */  PUT_MODE (pop_insn, QImode);  REG_NOTES (pop_insn) = gen_rtx (EXPR_LIST, REG_DEAD,				  FP_MODE_REG (FIRST_STACK_REG, 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_swap_insn (insn, regstack, reg)     rtx insn;     stack regstack;     rtx reg;{  int hard_regno;  rtx gen_swapdf();  rtx swap_rtx, swap_insn;  int tmp, other_reg;		/* swap regno temps */  rtx i1;			/* the stack-reg insn prior to INSN */  rtx i1set = NULL_RTX;		/* the SET rtx within I1 */  hard_regno = get_hard_regnum (regstack, reg);  if (hard_regno < FIRST_STACK_REG)    abort ();  if (hard_regno == FIRST_STACK_REG)    return;  other_reg = regstack->top - (hard_regno - FIRST_STACK_REG);  tmp = regstack->reg[other_reg];  regstack->reg[other_reg] = regstack->reg[regstack->top];  regstack->reg[regstack->top] = tmp;  /* Find the previous insn involving stack regs, but don't go past     any labels, calls or jumps.  */  i1 = prev_nonnote_insn (insn);  while (i1 && GET_CODE (i1) == INSN && GET_MODE (i1) != QImode)    i1 = prev_nonnote_insn (i1);  if (i1)    i1set = single_set (i1);  if (i1set)    {      rtx i2;			/* the stack-reg insn prior to I1 */      rtx i1src = *get_true_reg (&SET_SRC (i1set));      rtx i1dest = *get_true_reg (&SET_DEST (i1set));      /* If the previous register stack push was from the reg we are to	 swap with, omit the swap. */      if (GET_CODE (i1dest) == REG && REGNO (i1dest) == FIRST_STACK_REG	  && GET_CODE (i1src) == REG && REGNO (i1src) == hard_regno - 1	  && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)	return;      /* If the previous insn wrote to the reg we are to swap with,	 omit the swap.  */      if (GET_CODE (i1dest) == REG && REGNO (i1dest) == hard_regno	  && GET_CODE (i1src) == REG && REGNO (i1src) == FIRST_STACK_REG	  && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)	return;    }  if (GET_RTX_CLASS (GET_CODE (i1)) == 'i' && sets_cc0_p (PATTERN (i1)))    {      i1 = next_nonnote_insn (i1);      if (i1 == insn)

⌨️ 快捷键说明

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