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

📄 ia64.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 with the POST_DEC below, but it's nice to not use it when we	 can immediately tell it's not necessary.  */      addr_dead_p = ((noreturn_p || sibcall_p		      || TEST_HARD_REG_BIT (regs_invalidated_by_call,					    REGNO (addr)))		     && !FUNCTION_ARG_REGNO_P (REGNO (addr)));      /* Load the code address into scratch_b.  */      tmp = gen_rtx_POST_INC (Pmode, addr);      tmp = gen_rtx_MEM (Pmode, tmp);      emit_move_insn (scratch_r, tmp);      emit_move_insn (scratch_b, scratch_r);      /* Load the GP address.  If ADDR is not dead here, then we must	 revert the change made above via the POST_INCREMENT.  */      if (!addr_dead_p)	tmp = gen_rtx_POST_DEC (Pmode, addr);      else	tmp = addr;      tmp = gen_rtx_MEM (Pmode, tmp);      emit_move_insn (pic_offset_table_rtx, tmp);      is_desc = true;      addr = scratch_b;    }  if (sibcall_p)    insn = gen_sibcall_nogp (addr);  else if (retval)    insn = gen_call_value_nogp (retval, addr, retaddr);  else    insn = gen_call_nogp (addr, retaddr);  emit_call_insn (insn);  if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)    ia64_reload_gp ();}/* Begin the assembly file.  */static voidia64_file_start (void){  /* Variable tracking should be run after all optimizations which change order     of insns.  It also needs a valid CFG.  This can't be done in     ia64_override_options, because flag_var_tracking is finallized after     that.  */  ia64_flag_var_tracking = flag_var_tracking;  flag_var_tracking = 0;  default_file_start ();  emit_safe_across_calls ();}voidemit_safe_across_calls (void){  unsigned int rs, re;  int out_state;  rs = 1;  out_state = 0;  while (1)    {      while (rs < 64 && call_used_regs[PR_REG (rs)])	rs++;      if (rs >= 64)	break;      for (re = rs + 1; re < 64 && ! call_used_regs[PR_REG (re)]; re++)	continue;      if (out_state == 0)	{	  fputs ("\t.pred.safe_across_calls ", asm_out_file);	  out_state = 1;	}      else	fputc (',', asm_out_file);      if (re == rs + 1)	fprintf (asm_out_file, "p%u", rs);      else	fprintf (asm_out_file, "p%u-p%u", rs, re - 1);      rs = re + 1;    }  if (out_state)    fputc ('\n', asm_out_file);}/* Helper function for ia64_compute_frame_size: find an appropriate general   register to spill some special register to.  SPECIAL_SPILL_MASK contains   bits in GR0 to GR31 that have already been allocated by this routine.   TRY_LOCALS is true if we should attempt to locate a local regnum.  */static intfind_gr_spill (int try_locals){  int regno;  /* If this is a leaf function, first try an otherwise unused     call-clobbered register.  */  if (current_function_is_leaf)    {      for (regno = GR_REG (1); regno <= GR_REG (31); regno++)	if (! regs_ever_live[regno]	    && call_used_regs[regno]	    && ! fixed_regs[regno]	    && ! global_regs[regno]	    && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)	  {	    current_frame_info.gr_used_mask |= 1 << regno;	    return regno;	  }    }  if (try_locals)    {      regno = current_frame_info.n_local_regs;      /* If there is a frame pointer, then we can't use loc79, because	 that is HARD_FRAME_POINTER_REGNUM.  In particular, see the	 reg_name switching code in ia64_expand_prologue.  */      if (regno < (80 - frame_pointer_needed))	{	  current_frame_info.n_local_regs = regno + 1;	  return LOC_REG (0) + regno;	}    }  /* Failed to find a general register to spill to.  Must use stack.  */  return 0;}/* In order to make for nice schedules, we try to allocate every temporary   to a different register.  We must of course stay away from call-saved,   fixed, and global registers.  We must also stay away from registers   allocated in current_frame_info.gr_used_mask, since those include regs   used all through the prologue.   Any register allocated here must be used immediately.  The idea is to   aid scheduling, not to solve data flow problems.  */static int last_scratch_gr_reg;static intnext_scratch_gr_reg (void){  int i, regno;  for (i = 0; i < 32; ++i)    {      regno = (last_scratch_gr_reg + i + 1) & 31;      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 (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 (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.     Likewise 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;	}      /* 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

⌨️ 快捷键说明

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