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

📄 integrate.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     REG_FUNCTION_RETURN_VALUE_P.  */  map->inline_target = 0;  loc = DECL_RTL (DECL_RESULT (fndecl));  if (TYPE_MODE (type) == VOIDmode)    /* There is no return value to worry about.  */    ;  else if (GET_CODE (loc) == MEM)    {      if (! structure_value_addr || ! aggregate_value_p (DECL_RESULT (fndecl)))	abort ();        /* Pass the function the address in which to return a structure value.	 Note that a constructor can cause someone to call us with	 STRUCTURE_VALUE_ADDR, but the initialization takes place	 via the first parameter, rather than the struct return address.	 We have two cases:  If the address is a simple register indirect,	 use the mapping mechanism to point that register to our structure	 return address.  Otherwise, store the structure return value into	 the place that it will be referenced from.  */      if (GET_CODE (XEXP (loc, 0)) == REG)	{	  temp = force_reg (Pmode, structure_value_addr);	  map->reg_map[REGNO (XEXP (loc, 0))] = temp;	  if ((CONSTANT_P (structure_value_addr)	       || (GET_CODE (structure_value_addr) == PLUS		   && XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx		   && GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))	      && REGNO (temp) < map->const_equiv_map_size)	    {	      map->const_equiv_map[REGNO (temp)] = structure_value_addr;	      map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;	    }	}      else	{	  temp = copy_rtx_and_substitute (loc, map);	  subst_constants (&temp, NULL_RTX, map);	  apply_change_group ();	  emit_move_insn (temp, structure_value_addr);	}    }  else if (ignore)    /* We will ignore the result value, so don't look at its structure.       Note that preparations for an aggregate return value       do need to be made (above) even if it will be ignored.  */    ;  else if (GET_CODE (loc) == REG)    {      /* The function returns an object in a register and we use the return	 value.  Set up our target for remapping.  */      /* Machine mode function was declared to return.   */      enum machine_mode departing_mode = TYPE_MODE (type);      /* (Possibly wider) machine mode it actually computes	 (for the sake of callers that fail to declare it right).  */      enum machine_mode arriving_mode	= TYPE_MODE (TREE_TYPE (DECL_RESULT (fndecl)));      rtx reg_to_map;      /* Don't use MEMs as direct targets because on some machines	 substituting a MEM for a REG makes invalid insns.	 Let the combiner substitute the MEM if that is valid.  */      if (target == 0 || GET_CODE (target) != REG	  || GET_MODE (target) != departing_mode)	target = gen_reg_rtx (departing_mode);      /* If function's value was promoted before return,	 avoid machine mode mismatch when we substitute INLINE_TARGET.	 But TARGET is what we will return to the caller.  */      if (arriving_mode != departing_mode)	reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);      else	reg_to_map = target;      /* Usually, the result value is the machine's return register.	 Sometimes it may be a pseudo. Handle both cases.  */      if (REG_FUNCTION_VALUE_P (loc))	map->inline_target = reg_to_map;      else	map->reg_map[REGNO (loc)] = reg_to_map;    }  /* Make new label equivalences for the labels in the called function.  */  for (i = min_labelno; i < max_labelno; i++)    map->label_map[i] = gen_label_rtx ();  /* Perform postincrements before actually calling the function.  */  emit_queue ();  /* Clean up stack so that variables might have smaller offsets.  */  do_pending_stack_adjust ();  /* Save a copy of the location of const_equiv_map for mark_stores, called     via note_stores.  */  global_const_equiv_map = map->const_equiv_map;  global_const_equiv_map_size = map->const_equiv_map_size;  /* If the called function does an alloca, save and restore the     stack pointer around the call.  This saves stack space, but     also is required if this inline is being done between two     pushes.  */  if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)    emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);  /* Now copy the insns one by one.  Do this in two passes, first the insns and     then their REG_NOTES, just like save_for_inline.  */  /* This loop is very similar to the loop in copy_loop_body in unroll.c.  */  for (insn = insns; insn; insn = NEXT_INSN (insn))    {      rtx copy, pattern, set;      map->orig_asm_operands_vector = 0;      switch (GET_CODE (insn))	{	case INSN:	  pattern = PATTERN (insn);	  set = single_set (insn);	  copy = 0;	  if (GET_CODE (pattern) == USE	      && GET_CODE (XEXP (pattern, 0)) == REG	      && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))	    /* The (USE (REG n)) at return from the function should	       be ignored since we are changing (REG n) into	       inline_target.  */	    break;	  /* Ignore setting a function value that we don't want to use.  */	  if (map->inline_target == 0	      && set != 0	      && GET_CODE (SET_DEST (set)) == REG	      && REG_FUNCTION_VALUE_P (SET_DEST (set)))	    {	      if (volatile_refs_p (SET_SRC (set)))		{		  rtx new_set;		  /* If we must not delete the source,		     load it into a new temporary.  */		  copy = emit_insn (copy_rtx_and_substitute (pattern, map));		  new_set = single_set (copy);		  if (new_set == 0)		    abort ();		  SET_DEST (new_set)		    = gen_reg_rtx (GET_MODE (SET_DEST (new_set)));		}	      /* If the source and destination are the same and it		 has a note on it, keep the insn.  */	      else if (rtx_equal_p (SET_DEST (set), SET_SRC (set))		       && REG_NOTES (insn) != 0)		copy = emit_insn (copy_rtx_and_substitute (pattern, map));	      else		break;	    }	  /* If this is setting the static chain rtx, omit it.  */	  else if (static_chain_value != 0		   && set != 0		   && GET_CODE (SET_DEST (set)) == REG		   && rtx_equal_p (SET_DEST (set),				   static_chain_incoming_rtx))	    break;	  /* If this is setting the static chain pseudo, set it from	     the value we want to give it instead.  */	  else if (static_chain_value != 0		   && set != 0		   && rtx_equal_p (SET_SRC (set),				   static_chain_incoming_rtx))	    {	      rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map);	      copy = emit_move_insn (newdest, static_chain_value);	      static_chain_value = 0;	    }	  else	    copy = emit_insn (copy_rtx_and_substitute (pattern, map));	  /* REG_NOTES will be copied later.  */#ifdef HAVE_cc0	  /* If this insn is setting CC0, it may need to look at	     the insn that uses CC0 to see what type of insn it is.	     In that case, the call to recog via validate_change will	     fail.  So don't substitute constants here.  Instead,	     do it when we emit the following insn.	     For example, see the pyr.md file.  That machine has signed and	     unsigned compares.  The compare patterns must check the	     following branch insn to see which what kind of compare to	     emit.	     If the previous insn set CC0, substitute constants on it as	     well.  */	  if (sets_cc0_p (PATTERN (copy)) != 0)	    cc0_insn = copy;	  else	    {	      if (cc0_insn)		try_constants (cc0_insn, map);	      cc0_insn = 0;	      try_constants (copy, map);	    }#else	  try_constants (copy, map);#endif	  break;	case JUMP_INSN:	  if (GET_CODE (PATTERN (insn)) == RETURN)	    {	      if (local_return_label == 0)		local_return_label = gen_label_rtx ();	      pattern = gen_jump (local_return_label);	    }	  else	    pattern = copy_rtx_and_substitute (PATTERN (insn), map);	  copy = emit_jump_insn (pattern);#ifdef HAVE_cc0	  if (cc0_insn)	    try_constants (cc0_insn, map);	  cc0_insn = 0;#endif	  try_constants (copy, map);	  /* If this used to be a conditional jump insn but whose branch	     direction is now know, we must do something special.  */	  if (condjump_p (insn) && ! simplejump_p (insn) && map->last_pc_value)	    {#ifdef HAVE_cc0	      /* The previous insn set cc0 for us.  So delete it.  */	      delete_insn (PREV_INSN (copy));#endif	      /* If this is now a no-op, delete it.  */	      if (map->last_pc_value == pc_rtx)		{		  delete_insn (copy);		  copy = 0;		}	      else		/* Otherwise, this is unconditional jump so we must put a		   BARRIER after it.  We could do some dead code elimination		   here, but jump.c will do it just as well.  */		emit_barrier ();	    }	  break;	case CALL_INSN:	  pattern = copy_rtx_and_substitute (PATTERN (insn), map);	  copy = emit_call_insn (pattern);	  /* Because the USAGE information potentially contains objects other	     than hard registers, we need to copy it.  */	  CALL_INSN_FUNCTION_USAGE (copy) =	     copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn), map);#ifdef HAVE_cc0	  if (cc0_insn)	    try_constants (cc0_insn, map);	  cc0_insn = 0;#endif	  try_constants (copy, map);	  /* Be lazy and assume CALL_INSNs clobber all hard registers.  */	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	    map->const_equiv_map[i] = 0;	  break;	case CODE_LABEL:	  copy = emit_label (map->label_map[CODE_LABEL_NUMBER (insn)]);	  LABEL_NAME (copy) = LABEL_NAME (insn);	  map->const_age++;	  break;	case BARRIER:	  copy = emit_barrier ();	  break;	case NOTE:	  /* It is important to discard function-end and function-beg notes,	     so we have only one of each in the current function.	     Also, NOTE_INSN_DELETED notes aren't useful (save_for_inline	     deleted these in the copy used for continuing compilation,	     not the copy used for inlining).  */	  if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END	      && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG	      && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)	    copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));	  else	    copy = 0;	  break;	default:	  abort ();	  break;	}      if (copy)	RTX_INTEGRATED_P (copy) = 1;      map->insn_map[INSN_UID (insn)] = copy;    }  /* Now copy the REG_NOTES.  Increment const_age, so that only constants     from parameters can be substituted in.  These are the only ones that     are valid across the entire function.  */  map->const_age++;  for (insn = insns; insn; insn = NEXT_INSN (insn))    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'	&& map->insn_map[INSN_UID (insn)]	&& REG_NOTES (insn))      {	rtx tem = copy_rtx_and_substitute (REG_NOTES (insn), map);	/* We must also do subst_constants, in case one of our parameters	   has const type and constant value.  */	subst_constants (&tem, NULL_RTX, map);	apply_change_group ();	REG_NOTES (map->insn_map[INSN_UID (insn)]) = tem;      }  if (local_return_label)    emit_label (local_return_label);  /* Restore the stack pointer if we saved it above.  */  if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)    emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX);  /* Make copies of the decls of the symbols in the inline function, so that     the copies of the variables get declared in the current function.  Set     up things so that lookup_static_chain knows that to interpret registers     in SAVE_EXPRs for TYPE_SIZEs as local.  */  inline_function_decl = fndecl;  integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);  integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map);  inline_function_decl = 0;  /* End the scope containing the copied formal parameter variables     and copied LABEL_DECLs.  */  expand_end_bindings (getdecls (), 1, 1);  block = poplevel (1, 1, 0);  BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL				   ? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));  poplevel (0, 0, 0);  emit_line_note (input_filename, lineno);  if (structure_value_addr)    {      target = gen_rtx (MEM, TYPE_MODE (type),			memory_address (TYPE_MODE (type), structure_value_addr));      MEM_IN_STRUCT_P (target) = 1;    }  return target;}/* Given a chain of PARM_DECLs, ARGS, copy each decl into a VAR_DECL,   push all of those decls and give each one the corresponding home.  */static voidintegrate_parm_decls (args, map, arg_vector)     tree args;     struct inline_remap *map;     rtvec arg_vector;{  register tree tail;  register int i;  for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)    {      register tree decl = build_decl (VAR_DECL, DECL_NAME (tail),				       TREE_TYPE (tail));      rtx new_decl_rtl	= copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map);      DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (tail);      /* We really should be setting DECL_INCOMING_RTL to something reasonable	 here, but that's going

⌨️ 快捷键说明

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