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

📄 integrate.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  rtx header = DECL_SAVED_INSNS (fndecl);  rtx insns = FIRST_FUNCTION_INSN (header);  rtx parm_insns = FIRST_PARM_INSN (header);  tree *arg_trees;  rtx *arg_vals;  rtx insn;  int max_regno;  register int i;  int min_labelno = FIRST_LABELNO (header);  int max_labelno = LAST_LABELNO (header);  int nargs;  rtx local_return_label = 0;  rtx loc;  rtx stack_save = 0;  rtx temp;  struct inline_remap *map;  rtx cc0_insn = 0;  rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);  rtx static_chain_value = 0;  /* Allow for equivalences of the pseudos we make for virtual fp and ap.  */  max_regno = MAX_REGNUM (header) + 3;  if (max_regno < FIRST_PSEUDO_REGISTER)    abort ();  nargs = list_length (DECL_ARGUMENTS (fndecl));  /* Check that the parms type match and that sufficient arguments were     passed.  Since the appropriate conversions or default promotions have     already been applied, the machine modes should match exactly.  */  for (formal = DECL_ARGUMENTS (fndecl),       actual = parms;       formal;       formal = TREE_CHAIN (formal),       actual = TREE_CHAIN (actual))    {      tree arg;      enum machine_mode mode;      if (actual == 0)	return (rtx) (HOST_WIDE_INT) -1;      arg = TREE_VALUE (actual);      mode= TYPE_MODE (DECL_ARG_TYPE (formal));      if (mode != TYPE_MODE (TREE_TYPE (arg))	  /* If they are block mode, the types should match exactly.	     They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,	     which could happen if the parameter has incomplete type.  */	  || (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal)))	return (rtx) (HOST_WIDE_INT) -1;    }  /* Extra arguments are valid, but will be ignored below, so we must     evaluate them here for side-effects.  */  for (; actual; actual = TREE_CHAIN (actual))    expand_expr (TREE_VALUE (actual), const0_rtx,		 TYPE_MODE (TREE_TYPE (TREE_VALUE (actual))), 0);  /* Make a binding contour to keep inline cleanups called at     outer function-scope level from looking like they are shadowing     parameter declarations.  */  pushlevel (0);  /* Make a fresh binding contour that we can easily remove.  */  pushlevel (0);  expand_start_bindings (0);  /* Expand the function arguments.  Do this first so that any     new registers get created before we allocate the maps.  */  arg_vals = (rtx *) alloca (nargs * sizeof (rtx));  arg_trees = (tree *) alloca (nargs * sizeof (tree));  for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;       formal;       formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)    {      /* Actual parameter, converted to the type of the argument within the	 function.  */      tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));      /* Mode of the variable used within the function.  */      enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));      int invisiref = 0;      arg_trees[i] = arg;      loc = RTVEC_ELT (arg_vector, i);      /* If this is an object passed by invisible reference, we copy the	 object into a stack slot and save its address.  If this will go	 into memory, we do nothing now.  Otherwise, we just expand the	 argument.  */      if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG	  && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)	{	  rtx stack_slot	    = assign_stack_temp (TYPE_MODE (TREE_TYPE (arg)),				 int_size_in_bytes (TREE_TYPE (arg)), 1);	  MEM_IN_STRUCT_P (stack_slot) = AGGREGATE_TYPE_P (TREE_TYPE (arg));	  store_expr (arg, stack_slot, 0);	  arg_vals[i] = XEXP (stack_slot, 0);	  invisiref = 1;	}      else if (GET_CODE (loc) != MEM)	{	  if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))	    /* The mode if LOC and ARG can differ if LOC was a variable	       that had its mode promoted via PROMOTED_MODE.  */	    arg_vals[i] = convert_modes (GET_MODE (loc),					 TYPE_MODE (TREE_TYPE (arg)),					 expand_expr (arg, NULL_RTX, mode,						      EXPAND_SUM),					 TREE_UNSIGNED (TREE_TYPE (formal)));	  else	    arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);	}      else	arg_vals[i] = 0;      if (arg_vals[i] != 0	  && (! TREE_READONLY (formal)	      /* If the parameter is not read-only, copy our argument through		 a register.  Also, we cannot use ARG_VALS[I] if it overlaps		 TARGET in any way.  In the inline function, they will likely		 be two different pseudos, and `safe_from_p' will make all		 sorts of smart assumptions about their not conflicting.		 But if ARG_VALS[I] overlaps TARGET, these assumptions are		 wrong, so put ARG_VALS[I] into a fresh register.		 Don't worry about invisible references, since their stack		 temps will never overlap the target.  */	      || (target != 0		  && ! invisiref		  && (GET_CODE (arg_vals[i]) == REG		      || GET_CODE (arg_vals[i]) == SUBREG		      || GET_CODE (arg_vals[i]) == MEM)		  && reg_overlap_mentioned_p (arg_vals[i], target))	      /* ??? We must always copy a SUBREG into a REG, because it might		 get substituted into an address, and not all ports correctly		 handle SUBREGs in addresses.  */	      || (GET_CODE (arg_vals[i]) == SUBREG)))	arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);    }	  /* Allocate the structures we use to remap things.  */  map = (struct inline_remap *) alloca (sizeof (struct inline_remap));  map->fndecl = fndecl;  map->reg_map = (rtx *) alloca (max_regno * sizeof (rtx));  bzero ((char *) map->reg_map, max_regno * sizeof (rtx));  map->label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));  map->label_map -= min_labelno;  map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));  bzero ((char *) map->insn_map, INSN_UID (header) * sizeof (rtx));  map->min_insnno = 0;  map->max_insnno = INSN_UID (header);  map->integrating = 1;  /* const_equiv_map maps pseudos in our routine to constants, so it needs to     be large enough for all our pseudos.  This is the number we are currently     using plus the number in the called routine, plus 15 for each arg,     five to compute the virtual frame pointer, and five for the return value.     This should be enough for most cases.  We do not reference entries     outside the range of the map.     ??? These numbers are quite arbitrary and were obtained by     experimentation.  At some point, we should try to allocate the     table after all the parameters are set up so we an more accurately     estimate the number of pseudos we will need.  */  map->const_equiv_map_size    = max_reg_num () + (max_regno - FIRST_PSEUDO_REGISTER) + 15 * nargs + 10;  map->const_equiv_map    = (rtx *)alloca (map->const_equiv_map_size * sizeof (rtx));  bzero ((char *) map->const_equiv_map,	 map->const_equiv_map_size * sizeof (rtx));  map->const_age_map    = (unsigned *)alloca (map->const_equiv_map_size * sizeof (unsigned));  bzero ((char *) map->const_age_map,	 map->const_equiv_map_size * sizeof (unsigned));  map->const_age = 0;  /* Record the current insn in case we have to set up pointers to frame     and argument memory blocks.  */  map->insns_at_start = get_last_insn ();  /* Update the outgoing argument size to allow for those in the inlined     function.  */  if (OUTGOING_ARGS_SIZE (header) > current_function_outgoing_args_size)    current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (header);  /* If the inline function needs to make PIC references, that means     that this function's PIC offset table must be used.  */  if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)    current_function_uses_pic_offset_table = 1;  /* If this function needs a context, set it up.  */  if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_NEEDS_CONTEXT)    static_chain_value = lookup_static_chain (fndecl);  if (GET_CODE (parm_insns) == NOTE      && NOTE_LINE_NUMBER (parm_insns) > 0)    {      rtx note = emit_note (NOTE_SOURCE_FILE (parm_insns),			    NOTE_LINE_NUMBER (parm_insns));      if (note)	RTX_INTEGRATED_P (note) = 1;    }  /* Process each argument.  For each, set up things so that the function's     reference to the argument will refer to the argument being passed.     We only replace REG with REG here.  Any simplifications are done     via const_equiv_map.     We make two passes:  In the first, we deal with parameters that will     be placed into registers, since we need to ensure that the allocated     register number fits in const_equiv_map.  Then we store all non-register     parameters into their memory location.  */  /* Don't try to free temp stack slots here, because we may put one of the     parameters into a temp stack slot.  */  for (i = 0; i < nargs; i++)    {      rtx copy = arg_vals[i];      loc = RTVEC_ELT (arg_vector, i);      /* There are three cases, each handled separately.  */      if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG	  && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)	{	  /* This must be an object passed by invisible reference (it could	     also be a variable-sized object, but we forbid inlining functions	     with variable-sized arguments).  COPY is the address of the	     actual value (this computation will cause it to be copied).  We	     map that address for the register, noting the actual address as	     an equivalent in case it can be substituted into the insns.  */	  if (GET_CODE (copy) != REG)	    {	      temp = copy_addr_to_reg (copy);	      if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))		  && REGNO (temp) < map->const_equiv_map_size)		{		  map->const_equiv_map[REGNO (temp)] = copy;		  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;		}	      copy = temp;	    }	  map->reg_map[REGNO (XEXP (loc, 0))] = copy;	}      else if (GET_CODE (loc) == MEM)	{	  /* This is the case of a parameter that lives in memory.	     It will live in the block we allocate in the called routine's	     frame that simulates the incoming argument area.  Do nothing	     now; we will call store_expr later.  */	  ;	}      else if (GET_CODE (loc) == REG)	{	  /* This is the good case where the parameter is in a register.	     If it is read-only and our argument is a constant, set up the	     constant equivalence.	     If LOC is REG_USERVAR_P, the usual case, COPY must also have	     that flag set if it is a register.	     Also, don't allow hard registers here; they might not be valid	     when substituted into insns. */	  if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)	      || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)		  && ! REG_USERVAR_P (copy))	      || (GET_CODE (copy) == REG		  && REGNO (copy) < FIRST_PSEUDO_REGISTER))	    {	      temp = copy_to_mode_reg (GET_MODE (loc), copy);	      REG_USERVAR_P (temp) = REG_USERVAR_P (loc);	      if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))		  && REGNO (temp) < map->const_equiv_map_size)		{		  map->const_equiv_map[REGNO (temp)] = copy;		  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;		}	      copy = temp;	    }	  map->reg_map[REGNO (loc)] = copy;	}      else if (GET_CODE (loc) == CONCAT)	{	  /* This is the good case where the parameter is in a	     pair of separate pseudos.	     If it is read-only and our argument is a constant, set up the	     constant equivalence.	     If LOC is REG_USERVAR_P, the usual case, COPY must also have	     that flag set if it is a register.	     Also, don't allow hard registers here; they might not be valid	     when substituted into insns. */	  rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);	  rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);	  rtx copyreal = gen_realpart (GET_MODE (locreal), copy);	  rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);	  if ((GET_CODE (copyreal) != REG && GET_CODE (copyreal) != SUBREG)	      || (GET_CODE (copyreal) == REG && REG_USERVAR_P (locreal)		  && ! REG_USERVAR_P (copyreal))	      || (GET_CODE (copyreal) == REG		  && REGNO (copyreal) < FIRST_PSEUDO_REGISTER))	    {	      temp = copy_to_mode_reg (GET_MODE (locreal), copyreal);	      REG_USERVAR_P (temp) = REG_USERVAR_P (locreal);	      if ((CONSTANT_P (copyreal) || FIXED_BASE_PLUS_P (copyreal))		  && REGNO (temp) < map->const_equiv_map_size)		{		  map->const_equiv_map[REGNO (temp)] = copyreal;		  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;		}	      copyreal = temp;	    }	  map->reg_map[REGNO (locreal)] = copyreal;	  if ((GET_CODE (copyimag) != REG && GET_CODE (copyimag) != SUBREG)	      || (GET_CODE (copyimag) == REG && REG_USERVAR_P (locimag)		  && ! REG_USERVAR_P (copyimag))	      || (GET_CODE (copyimag) == REG		  && REGNO (copyimag) < FIRST_PSEUDO_REGISTER))	    {	      temp = copy_to_mode_reg (GET_MODE (locimag), copyimag);	      REG_USERVAR_P (temp) = REG_USERVAR_P (locimag);	      if ((CONSTANT_P (copyimag) || FIXED_BASE_PLUS_P (copyimag))		  && REGNO (temp) < map->const_equiv_map_size)		{		  map->const_equiv_map[REGNO (temp)] = copyimag;		  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;		}	      copyimag = temp;	    }	  map->reg_map[REGNO (locimag)] = copyimag;	}      else	abort ();    }  /* Now do the parameters that will be placed in memory.  */  for (formal = DECL_ARGUMENTS (fndecl), i = 0;       formal; formal = TREE_CHAIN (formal), i++)    {      loc = RTVEC_ELT (arg_vector, i);      if (GET_CODE (loc) == MEM	  /* Exclude case handled above.  */	  && ! (GET_CODE (XEXP (loc, 0)) == REG		&& REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))	{	  rtx note = emit_note (DECL_SOURCE_FILE (formal),				DECL_SOURCE_LINE (formal));	  if (note)	    RTX_INTEGRATED_P (note) = 1;	  /* Compute the address in the area we reserved and store the	     value there.  */	  temp = copy_rtx_and_substitute (loc, map);	  subst_constants (&temp, NULL_RTX, map);	  apply_change_group ();	  if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))	    temp = change_address (temp, VOIDmode, XEXP (temp, 0));	  store_expr (arg_trees[i], temp, 0);	}    }  /* Deal with the places that the function puts its result.     We are driven by what is placed into DECL_RESULT.     Initially, we assume that we don't have anything special handling for

⌨️ 快捷键说明

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