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

📄 ia64.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (call_used_regs[regno]	  && ! fixed_regs[regno]	  && ! global_regs[regno]	  && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)	{	  last_scratch_gr_reg = regno;	  return regno;	}    }  /* There must be _something_ available.  */  abort ();}/* Helper function for ia64_compute_frame_size, called through   diddle_return_value.  Mark REG in current_frame_info.gr_used_mask.  */static voidmark_reg_gr_used_mask (reg, data)     rtx reg;     void *data ATTRIBUTE_UNUSED;{  unsigned int regno = REGNO (reg);  if (regno < 32)    {      unsigned int i, n = HARD_REGNO_NREGS (regno, GET_MODE (reg));      for (i = 0; i < n; ++i)	current_frame_info.gr_used_mask |= 1 << (regno + i);    }}/* Returns the number of bytes offset between the frame pointer and the stack   pointer for the current function.  SIZE is the number of bytes of space   needed for local variables.  */static voidia64_compute_frame_size (size)     HOST_WIDE_INT size;{  HOST_WIDE_INT total_size;  HOST_WIDE_INT spill_size = 0;  HOST_WIDE_INT extra_spill_size = 0;  HOST_WIDE_INT pretend_args_size;  HARD_REG_SET mask;  int n_spilled = 0;  int spilled_gr_p = 0;  int spilled_fr_p = 0;  unsigned int regno;  int i;  if (current_frame_info.initialized)    return;  memset (&current_frame_info, 0, sizeof current_frame_info);  CLEAR_HARD_REG_SET (mask);  /* Don't allocate scratches to the return register.  */  diddle_return_value (mark_reg_gr_used_mask, NULL);  /* Don't allocate scratches to the EH scratch registers.  */  if (cfun->machine->ia64_eh_epilogue_sp)    mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_sp, NULL);  if (cfun->machine->ia64_eh_epilogue_bsp)    mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_bsp, NULL);  /* Find the size of the register stack frame.  We have only 80 local     registers, because we reserve 8 for the inputs and 8 for the     outputs.  */  /* Skip HARD_FRAME_POINTER_REGNUM (loc79) when frame_pointer_needed,     since we'll be adjusting that down later.  */  regno = LOC_REG (78) + ! frame_pointer_needed;  for (; regno >= LOC_REG (0); regno--)    if (regs_ever_live[regno])      break;  current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;  /* For functions marked with the syscall_linkage attribute, we must mark     all eight input registers as in use, so that locals aren't visible to     the caller.  */  if (cfun->machine->n_varargs > 0      || lookup_attribute ("syscall_linkage",			   TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))    current_frame_info.n_input_regs = 8;  else    {      for (regno = IN_REG (7); regno >= IN_REG (0); regno--)	if (regs_ever_live[regno])	  break;      current_frame_info.n_input_regs = regno - IN_REG (0) + 1;    }  for (regno = OUT_REG (7); regno >= OUT_REG (0); regno--)    if (regs_ever_live[regno])      break;  i = regno - OUT_REG (0) + 1;  /* When -p profiling, we need one output register for the mcount argument.     Likwise for -a profiling for the bb_init_func argument.  For -ax     profiling, we need two output registers for the two bb_init_trace_func     arguments.  */  if (current_function_profile)    i = MAX (i, 1);  current_frame_info.n_output_regs = i;  /* ??? No rotating register support yet.  */  current_frame_info.n_rotate_regs = 0;  /* Discover which registers need spilling, and how much room that     will take.  Begin with floating point and general registers,      which will always wind up on the stack.  */  for (regno = FR_REG (2); regno <= FR_REG (127); regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {	SET_HARD_REG_BIT (mask, regno);	spill_size += 16;	n_spilled += 1;	spilled_fr_p = 1;      }  for (regno = GR_REG (1); regno <= GR_REG (31); regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {	SET_HARD_REG_BIT (mask, regno);	spill_size += 8;	n_spilled += 1;	spilled_gr_p = 1;      }  for (regno = BR_REG (1); regno <= BR_REG (7); regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {	SET_HARD_REG_BIT (mask, regno);	spill_size += 8;	n_spilled += 1;      }  /* Now come all special registers that might get saved in other     general registers.  */    if (frame_pointer_needed)    {      current_frame_info.reg_fp = find_gr_spill (1);      /* If we did not get a register, then we take LOC79.  This is guaranteed	 to be free, even if regs_ever_live is already set, because this is	 HARD_FRAME_POINTER_REGNUM.  This requires incrementing n_local_regs,	 as we don't count loc79 above.  */      if (current_frame_info.reg_fp == 0)	{	  current_frame_info.reg_fp = LOC_REG (79);	  current_frame_info.n_local_regs++;	}    }  if (! current_function_is_leaf)    {      /* Emit a save of BR0 if we call other functions.  Do this even	 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;	}    }  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;	}    }  /* 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.  */  if (spilled_gr_p || cfun->machine->n_varargs)    {      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;    case RETURN_ADDRESS_POINTER_REGNUM:      offset = 0;      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

⌨️ 快捷键说明

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