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

📄 ia64.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	 if this function doesn't return, as EH depends on this to be	 able to unwind the stack.  */      SET_HARD_REG_BIT (mask, BR_REG (0));      current_frame_info.reg_save_b0 = find_gr_spill (1);      if (current_frame_info.reg_save_b0 == 0)	{	  spill_size += 8;	  n_spilled += 1;	}      /* Similarly for ar.pfs.  */      SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);      current_frame_info.reg_save_ar_pfs = find_gr_spill (1);      if (current_frame_info.reg_save_ar_pfs == 0)	{	  extra_spill_size += 8;	  n_spilled += 1;	}      /* Similarly for gp.  Note that if we're calling setjmp, the stacked	 registers are clobbered, so we fall back to the stack.  */      current_frame_info.reg_save_gp	= (current_function_calls_setjmp ? 0 : find_gr_spill (1));      if (current_frame_info.reg_save_gp == 0)	{	  SET_HARD_REG_BIT (mask, GR_REG (1));	  spill_size += 8;	  n_spilled += 1;	}    }  else    {      if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)])	{	  SET_HARD_REG_BIT (mask, BR_REG (0));	  spill_size += 8;	  n_spilled += 1;	}      if (regs_ever_live[AR_PFS_REGNUM])	{	  SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);	  current_frame_info.reg_save_ar_pfs = find_gr_spill (1);	  if (current_frame_info.reg_save_ar_pfs == 0)	    {	      extra_spill_size += 8;	      n_spilled += 1;	    }	}    }  /* Unwind descriptor hackery: things are most efficient if we allocate     consecutive GR save registers for RP, PFS, FP in that order. However,     it is absolutely critical that FP get the only hard register that's     guaranteed to be free, so we allocated it first.  If all three did     happen to be allocated hard regs, and are consecutive, rearrange them     into the preferred order now.  */  if (current_frame_info.reg_fp != 0      && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1      && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2)    {      current_frame_info.reg_save_b0 = current_frame_info.reg_fp;      current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1;      current_frame_info.reg_fp = current_frame_info.reg_fp + 2;    }  /* See if we need to store the predicate register block.  */  for (regno = PR_REG (0); regno <= PR_REG (63); regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      break;  if (regno <= PR_REG (63))    {      SET_HARD_REG_BIT (mask, PR_REG (0));      current_frame_info.reg_save_pr = find_gr_spill (1);      if (current_frame_info.reg_save_pr == 0)	{	  extra_spill_size += 8;	  n_spilled += 1;	}      /* ??? Mark them all as used so that register renaming and such	 are free to use them.  */      for (regno = PR_REG (0); regno <= PR_REG (63); regno++)	regs_ever_live[regno] = 1;    }  /* If we're forced to use st8.spill, we're forced to save and restore     ar.unat as well.  The check for existing liveness allows inline asm     to touch ar.unat.  */  if (spilled_gr_p || cfun->machine->n_varargs      || regs_ever_live[AR_UNAT_REGNUM])    {      regs_ever_live[AR_UNAT_REGNUM] = 1;      SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);      current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0);      if (current_frame_info.reg_save_ar_unat == 0)	{	  extra_spill_size += 8;	  n_spilled += 1;	}    }  if (regs_ever_live[AR_LC_REGNUM])    {      SET_HARD_REG_BIT (mask, AR_LC_REGNUM);      current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0);      if (current_frame_info.reg_save_ar_lc == 0)	{	  extra_spill_size += 8;	  n_spilled += 1;	}    }  /* If we have an odd number of words of pretend arguments written to     the stack, then the FR save area will be unaligned.  We round the     size of this area up to keep things 16 byte aligned.  */  if (spilled_fr_p)    pretend_args_size = IA64_STACK_ALIGN (current_function_pretend_args_size);  else    pretend_args_size = current_function_pretend_args_size;  total_size = (spill_size + extra_spill_size + size + pretend_args_size		+ current_function_outgoing_args_size);  total_size = IA64_STACK_ALIGN (total_size);  /* We always use the 16-byte scratch area provided by the caller, but     if we are a leaf function, there's no one to which we need to provide     a scratch area.  */  if (current_function_is_leaf)    total_size = MAX (0, total_size - 16);  current_frame_info.total_size = total_size;  current_frame_info.spill_cfa_off = pretend_args_size - 16;  current_frame_info.spill_size = spill_size;  current_frame_info.extra_spill_size = extra_spill_size;  COPY_HARD_REG_SET (current_frame_info.mask, mask);  current_frame_info.n_spilled = n_spilled;  current_frame_info.initialized = reload_completed;}/* Compute the initial difference between the specified pair of registers.  */HOST_WIDE_INTia64_initial_elimination_offset (from, to)     int from, to;{  HOST_WIDE_INT offset;  ia64_compute_frame_size (get_frame_size ());  switch (from)    {    case FRAME_POINTER_REGNUM:      if (to == HARD_FRAME_POINTER_REGNUM)	{	  if (current_function_is_leaf)	    offset = -current_frame_info.total_size;	  else	    offset = -(current_frame_info.total_size		       - current_function_outgoing_args_size - 16);	}      else if (to == STACK_POINTER_REGNUM)	{	  if (current_function_is_leaf)	    offset = 0;	  else	    offset = 16 + current_function_outgoing_args_size;	}      else	abort ();      break;    case ARG_POINTER_REGNUM:      /* Arguments start above the 16 byte save area, unless stdarg	 in which case we store through the 16 byte save area.  */      if (to == HARD_FRAME_POINTER_REGNUM)	offset = 16 - current_function_pretend_args_size;      else if (to == STACK_POINTER_REGNUM)	offset = (current_frame_info.total_size		  + 16 - current_function_pretend_args_size);      else	abort ();      break;    default:      abort ();    }  return offset;}/* If there are more than a trivial number of register spills, we use   two interleaved iterators so that we can get two memory references   per insn group.   In order to simplify things in the prologue and epilogue expanders,   we use helper functions to fix up the memory references after the   fact with the appropriate offsets to a POST_MODIFY memory mode.   The following data structure tracks the state of the two iterators   while insns are being emitted.  */struct spill_fill_data{  rtx init_after;		/* point at which to emit initializations */  rtx init_reg[2];		/* initial base register */  rtx iter_reg[2];		/* the iterator registers */  rtx *prev_addr[2];		/* address of last memory use */  rtx prev_insn[2];		/* the insn corresponding to prev_addr */  HOST_WIDE_INT prev_off[2];	/* last offset */  int n_iter;			/* number of iterators in use */  int next_iter;		/* next iterator to use */  unsigned int save_gr_used_mask;};static struct spill_fill_data spill_fill_data;static voidsetup_spill_pointers (n_spills, init_reg, cfa_off)     int n_spills;     rtx init_reg;     HOST_WIDE_INT cfa_off;{  int i;  spill_fill_data.init_after = get_last_insn ();  spill_fill_data.init_reg[0] = init_reg;  spill_fill_data.init_reg[1] = init_reg;  spill_fill_data.prev_addr[0] = NULL;  spill_fill_data.prev_addr[1] = NULL;  spill_fill_data.prev_insn[0] = NULL;  spill_fill_data.prev_insn[1] = NULL;  spill_fill_data.prev_off[0] = cfa_off;  spill_fill_data.prev_off[1] = cfa_off;  spill_fill_data.next_iter = 0;  spill_fill_data.save_gr_used_mask = current_frame_info.gr_used_mask;  spill_fill_data.n_iter = 1 + (n_spills > 2);  for (i = 0; i < spill_fill_data.n_iter; ++i)    {      int regno = next_scratch_gr_reg ();      spill_fill_data.iter_reg[i] = gen_rtx_REG (DImode, regno);      current_frame_info.gr_used_mask |= 1 << regno;    }}static voidfinish_spill_pointers (){  current_frame_info.gr_used_mask = spill_fill_data.save_gr_used_mask;}static rtxspill_restore_mem (reg, cfa_off)     rtx reg;     HOST_WIDE_INT cfa_off;{  int iter = spill_fill_data.next_iter;  HOST_WIDE_INT disp = spill_fill_data.prev_off[iter] - cfa_off;  rtx disp_rtx = GEN_INT (disp);  rtx mem;  if (spill_fill_data.prev_addr[iter])    {      if (CONST_OK_FOR_N (disp))	{	  *spill_fill_data.prev_addr[iter]	    = gen_rtx_POST_MODIFY (DImode, spill_fill_data.iter_reg[iter],				   gen_rtx_PLUS (DImode,						 spill_fill_data.iter_reg[iter],						 disp_rtx));	  REG_NOTES (spill_fill_data.prev_insn[iter])	    = gen_rtx_EXPR_LIST (REG_INC, spill_fill_data.iter_reg[iter],				 REG_NOTES (spill_fill_data.prev_insn[iter]));	}      else	{	  /* ??? Could use register post_modify for loads.  */	  if (! CONST_OK_FOR_I (disp))	    {	      rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());	      emit_move_insn (tmp, disp_rtx);	      disp_rtx = tmp;	    }	  emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],				 spill_fill_data.iter_reg[iter], disp_rtx));	}    }  /* Micro-optimization: if we've created a frame pointer, it's at     CFA 0, which may allow the real iterator to be initialized lower,     slightly increasing parallelism.  Also, if there are few saves     it may eliminate the iterator entirely.  */  else if (disp == 0	   && spill_fill_data.init_reg[iter] == stack_pointer_rtx	   && frame_pointer_needed)    {      mem = gen_rtx_MEM (GET_MODE (reg), hard_frame_pointer_rtx);      set_mem_alias_set (mem, get_varargs_alias_set ());      return mem;    }  else    {      rtx seq, insn;      if (disp == 0)	seq = gen_movdi (spill_fill_data.iter_reg[iter],			 spill_fill_data.init_reg[iter]);      else	{	  start_sequence ();	  if (! CONST_OK_FOR_I (disp))	    {	      rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());	      emit_move_insn (tmp, disp_rtx);	      disp_rtx = tmp;	    }	  emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],				 spill_fill_data.init_reg[iter],				 disp_rtx));	  seq = get_insns ();	  end_sequence ();	}      /* Careful for being the first insn in a sequence.  */      if (spill_fill_data.init_after)	insn = emit_insn_after (seq, spill_fill_data.init_after);      else	{	  rtx first = get_insns ();	  if (first)	    insn = emit_insn_before (seq, first);	  else	    insn = emit_insn (seq);	}      spill_fill_data.init_after = insn;      /* If DISP is 0, we may or may not have a further adjustment	 afterward.  If we do, then the load/store insn may be modified	 to be a post-modify.  If we don't, then this copy may be	 eliminated by copyprop_hardreg_forward, which makes this	 insn garbage, which runs afoul of the sanity check in	 propagate_one_insn.  So mark this insn as legal to delete.  */      if (disp == 0)	REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,					     REG_NOTES (insn));    }  mem = gen_rtx_MEM (GET_MODE (reg), spill_fill_data.iter_reg[iter]);  /* ??? Not all of the spills are for varargs, but some of them are.     The rest of the spills belong in an alias set of their own.  But     it doesn't actually hurt to include them here.  */  set_mem_alias_set (mem, get_varargs_alias_set ());  spill_fill_data.prev_addr[iter] = &XEXP (mem, 0);  spill_fill_data.prev_off[iter] = cfa_off;  if (++iter >= spill_fill_data.n_iter)    iter = 0;  spill_fill_data.next_iter = iter;  return mem;}static voiddo_spill (move_fn, reg, cfa_off, frame_reg)     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));     rtx reg, frame_reg;     HOST_WIDE_INT cfa_off;{  int iter = spill_fill_data.next_iter;  rtx mem, insn;  mem = spill_restore_mem (reg, cfa_off);  insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off)));  spill_fill_data.prev_insn[iter] = insn;  if (frame_reg)    {      rtx base;      HOST_WIDE_INT off;      RTX_FRAME_RELATED_P (insn) = 1;      /* Don't even pretend that the unwind code can intuit its way 	 through a pair of interleaved post_modify iterators.  Just	 provide the correct answer.  */      if (frame_pointer_needed)	{	  base = hard_frame_pointer_rtx;	  off = - cfa_off;	}      else	{	  base = stack_pointer_rtx;	  off = current_frame_info.total_size - cfa_off;	}      REG_NOTES (insn)	= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,		gen_rtx_SET (VOIDmode,			     gen_rtx_MEM (GET_MODE (reg),					  plus_constant (base, off)),			     frame_reg),		REG_NOTES (insn));    }}static voiddo_restore (move_fn, reg, cfa_off)     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));     rtx reg;     HOST_WIDE_INT cfa_off;{  int iter = spill_fill_data.next_iter;  rtx insn;  insn = emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off),				GEN_INT (cfa_off)));  spill_fill_data.prev_insn[iter] = insn;}/* Wrapper functions that discards the CONST_INT spill offset.  These   exist so that we can give gr_spill/gr_fill the offset they need and   use a consistant function interface.  */static rtxgen_movdi_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_movdi (dest, src);}static rtxgen_fr_spill_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_fr_spill (dest, src);}static rtxgen_fr_restore_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_fr_restore (dest, src);}/* Called after register allocation to add any instructions needed for the   prologue.  Using a prologue insn is favored compared to putting all of the   instructions in output_function_prologu

⌨️ 快捷键说明

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