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

📄 function.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
voidfixup_stack_slots (){  register rtx insn;  /* Did we generate a stack slot that is out of range     or otherwise has an invalid address?  */  if (invalid_stack_slot)    {      /* Yes.  Must scan all insns for stack-refs that exceed the limit.  */      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))	if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN	    || GET_CODE (insn) == JUMP_INSN)	  fixup_stack_1 (PATTERN (insn), insn);    }}#endif/* For each memory ref within X, if it refers to a stack slot   with an out of range displacement, put the address in a temp register   (emitting new insns before INSN to load these registers)   and alter the memory ref to use that register.   Replace each such MEM rtx with a copy, to avoid clobberage.  */static rtxfixup_stack_1 (x, insn)     rtx x;     rtx insn;{  register int i;  register RTX_CODE code = GET_CODE (x);  register char *fmt;  if (code == MEM)    {      register rtx ad = XEXP (x, 0);      /* If we have address of a stack slot but it's not valid	 (displacement is too large), compute the sum in a register.  */      if (GET_CODE (ad) == PLUS	  && GET_CODE (XEXP (ad, 0)) == REG	  && REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER	  && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER	  && GET_CODE (XEXP (ad, 1)) == CONST_INT)	{	  rtx temp, seq;	  if (memory_address_p (GET_MODE (x), ad))	    return x;	  start_sequence ();	  temp = copy_to_reg (ad);	  seq = gen_sequence ();	  end_sequence ();	  emit_insn_before (seq, insn);	  return change_address (x, VOIDmode, temp);	}      return x;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);	}    }  return x;}/* Optimization: a bit-field instruction whose field   happens to be a byte or halfword in memory   can be changed to a move instruction.   We call here when INSN is an insn to examine or store into a bit-field.   BODY is the SET-rtx to be altered.   EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.   (Currently this is called only from function.c, and EQUIV_MEM   is always 0.)  */static voidoptimize_bit_field (body, insn, equiv_mem)     rtx body;     rtx insn;     rtx *equiv_mem;{  register rtx bitfield;  int destflag;  rtx seq = 0;  enum machine_mode mode;  if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT      || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)    bitfield = SET_DEST (body), destflag = 1;  else    bitfield = SET_SRC (body), destflag = 0;  /* First check that the field being stored has constant size and position     and is in fact a byte or halfword suitably aligned.  */  if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT      && GET_CODE (XEXP (bitfield, 2)) == CONST_INT      && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))	  != BLKmode)      && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)    {      register rtx memref = 0;      /* Now check that the containing word is memory, not a register,	 and that it is safe to change the machine mode.  */      if (GET_CODE (XEXP (bitfield, 0)) == MEM)	memref = XEXP (bitfield, 0);      else if (GET_CODE (XEXP (bitfield, 0)) == REG	       && equiv_mem != 0)	memref = equiv_mem[REGNO (XEXP (bitfield, 0))];      else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG	       && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)	memref = SUBREG_REG (XEXP (bitfield, 0));      else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG	       && equiv_mem != 0	       && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)	memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];      if (memref	  && ! mode_dependent_address_p (XEXP (memref, 0))	  && ! MEM_VOLATILE_P (memref))	{	  /* Now adjust the address, first for any subreg'ing	     that we are now getting rid of,	     and then for which byte of the word is wanted.  */	  register int offset = INTVAL (XEXP (bitfield, 2));	  /* Adjust OFFSET to count bits from low-address byte.  */#if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN	  offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))		    - offset - INTVAL (XEXP (bitfield, 1)));#endif	  /* Adjust OFFSET to count bytes from low-address byte.  */	  offset /= BITS_PER_UNIT;	  if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)	    {	      offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;#if BYTES_BIG_ENDIAN	      offset -= (MIN (UNITS_PER_WORD,			      GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))			 - MIN (UNITS_PER_WORD,				GET_MODE_SIZE (GET_MODE (memref))));#endif	    }	  memref = change_address (memref, mode, 				   plus_constant (XEXP (memref, 0), offset));	  /* Store this memory reference where	     we found the bit field reference.  */	  if (destflag)	    {	      validate_change (insn, &SET_DEST (body), memref, 1);	      if (! CONSTANT_ADDRESS_P (SET_SRC (body)))		{		  rtx src = SET_SRC (body);		  while (GET_CODE (src) == SUBREG			 && SUBREG_WORD (src) == 0)		    src = SUBREG_REG (src);		  if (GET_MODE (src) != GET_MODE (memref))		    src = gen_lowpart (GET_MODE (memref), SET_SRC (body));		  validate_change (insn, &SET_SRC (body), src, 1);		}	      else if (GET_MODE (SET_SRC (body)) != VOIDmode		       && GET_MODE (SET_SRC (body)) != GET_MODE (memref))		/* This shouldn't happen because anything that didn't have		   one of these modes should have got converted explicitly		   and then referenced through a subreg.		   This is so because the original bit-field was		   handled by agg_mode and so its tree structure had		   the same mode that memref now has.  */		abort ();	    }	  else	    {	      rtx dest = SET_DEST (body);	      while (GET_CODE (dest) == SUBREG		     && SUBREG_WORD (dest) == 0)		dest = SUBREG_REG (dest);	      validate_change (insn, &SET_DEST (body), dest, 1);	      if (GET_MODE (dest) == GET_MODE (memref))		validate_change (insn, &SET_SRC (body), memref, 1);	      else		{		  /* Convert the mem ref to the destination mode.  */		  rtx newreg = gen_reg_rtx (GET_MODE (dest));		  start_sequence ();		  convert_move (newreg, memref,				GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);		  seq = get_insns ();		  end_sequence ();		  validate_change (insn, &SET_SRC (body), newreg, 1);		}	    }	  /* See if we can convert this extraction or insertion into	     a simple move insn.  We might not be able to do so if this	     was, for example, part of a PARALLEL.	     If we succeed, write out any needed conversions.  If we fail,	     it is hard to guess why we failed, so don't do anything	     special; just let the optimization be suppressed.  */	  if (apply_change_group () && seq)	    emit_insns_before (seq, insn);	}    }}/* These routines are responsible for converting virtual register references   to the actual hard register references once RTL generation is complete.   The following four variables are used for communication between the   routines.  They contain the offsets of the virtual registers from their   respective hard registers.  */static int in_arg_offset;static int var_offset;static int dynamic_offset;static int out_arg_offset;/* In most machines, the stack pointer register is equivalent to the bottom   of the stack.  */#ifndef STACK_POINTER_OFFSET#define STACK_POINTER_OFFSET	0#endif/* If not defined, pick an appropriate default for the offset of dynamically   allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,   REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */#ifndef STACK_DYNAMIC_OFFSET#ifdef ACCUMULATE_OUTGOING_ARGS/* The bottom of the stack points to the actual arguments.  If   REG_PARM_STACK_SPACE is defined, this includes the space for the register   parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,   stack space for register parameters is not pushed by the caller, but    rather part of the fixed stack areas and hence not included in   `current_function_outgoing_args_size'.  Nevertheless, we must allow   for it when allocating stack dynamic objects.  */#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)#define STACK_DYNAMIC_OFFSET(FNDECL)	\(current_function_outgoing_args_size	\ + REG_PARM_STACK_SPACE (FNDECL) + (STACK_POINTER_OFFSET))#else#define STACK_DYNAMIC_OFFSET(FNDECL)	\(current_function_outgoing_args_size + (STACK_POINTER_OFFSET))#endif#else#define STACK_DYNAMIC_OFFSET(FNDECL) STACK_POINTER_OFFSET#endif#endif/* Pass through the INSNS of function FNDECL and convert virtual register   references to hard register references.  */voidinstantiate_virtual_regs (fndecl, insns)     tree fndecl;     rtx insns;{  rtx insn;  /* Compute the offsets to use for this function.  */  in_arg_offset = FIRST_PARM_OFFSET (fndecl);  var_offset = STARTING_FRAME_OFFSET;  dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);  out_arg_offset = STACK_POINTER_OFFSET;  /* Scan all variables and parameters of this function.  For each that is     in memory, instantiate all virtual registers if the result is a valid     address.  If not, we do it later.  That will handle most uses of virtual     regs on many machines.  */  instantiate_decls (fndecl, 1);  /* Initialize recognition, indicating that volatile is OK.  */  init_recog ();  /* Scan through all the insns, instantiating every virtual register still     present.  */  for (insn = insns; insn; insn = NEXT_INSN (insn))    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN	|| GET_CODE (insn) == CALL_INSN)      {	instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);	instantiate_virtual_regs_1 (&REG_NOTES (insn), NULL_RTX, 0);      }  /* Now instantiate the remaining register equivalences for debugging info.     These will not be valid addresses.  */  instantiate_decls (fndecl, 0);  /* Indicate that, from now on, assign_stack_local should use     frame_pointer_rtx.  */  virtuals_instantiated = 1;}/* Scan all decls in FNDECL (both variables and parameters) and instantiate   all virtual registers in their DECL_RTL's.   If VALID_ONLY, do this only if the resulting address is still valid.   Otherwise, always do it.  */static voidinstantiate_decls (fndecl, valid_only)     tree fndecl;     int valid_only;{  tree decl;  if (DECL_INLINE (fndecl))    /* When compiling an inline function, the obstack used for       rtl allocation is the maybepermanent_obstack.  Calling       `resume_temporary_allocation' switches us back to that       obstack while we process this function's parameters.  */    resume_temporary_allocation ();  /* Process all parameters of the function.  */  for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))    {      instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)),			valid_only);	      instantiate_decl (DECL_INCOMING_RTL (decl),			int_size_in_bytes (TREE_TYPE (decl)), valid_only);    }  /* Now process all variables defined in the function or its subblocks. */  instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);  if (DECL_INLINE (fndecl))    {      /* Save all rtl allocated for this function by raising the	 high-water mark on the maybepermanent_obstack.  */      preserve_data ();      /* All further rtl allocation is now done in the current_obstack.  */      rtl_in_current_obstack ();    }}/* Subroutine of instantiate_decls: Process all decls in the given   BLOCK node and all its subblocks.  */static voidinstantiate_decls_1 (let, valid_only)     tree let;     int valid_only;{  tree t;  for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))    instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)),		      valid_only);  /* Process all subblocks.  */  for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))    instantiate_decls_1 (t, valid_only);}/* Subroutine of the preceeding procedures: Given RTL representing a   decl and the size of the object, do any instantiation required.   If VALID_ONLY is non-zero, it means that the RTL should only be   changed if the new address is valid.  */static voidinstantiate_decl (x, size, valid_only)     rtx x;     int size;     int valid_only;{  enum machine_mode mode;  rtx addr;  /* If this is not a MEM, no need to do anything.  Similarly if the     address is a constant or a register that is not a virtual register.  */  if (x == 0 || GET_CODE (x) != MEM)    return;  addr = XEXP (x, 0);  if (CONSTANT_P (addr)      || (GET_CODE (addr) == REG	  && (REGNO (addr) <

⌨️ 快捷键说明

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