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

📄 integrate.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		  SET_DEST (PATTERN (copy)) 		    = gen_reg_rtx (GET_MODE (SET_DEST (PATTERN (copy))));		}	      else		break;	    }	  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);#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.  */  for (insn = insns; insn; insn = NEXT_INSN (insn))    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'	&& map->insn_map[INSN_UID (insn)])      REG_NOTES (map->insn_map[INSN_UID (insn)])	= copy_rtx_and_substitute (REG_NOTES (insn), map);  if (local_return_label)    emit_label (local_return_label);  /* 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)    return gen_rtx (MEM, TYPE_MODE (type),		    memory_address (TYPE_MODE (type), structure_value_addr));  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);      /* These args would always appear unused, if not for this.  */      TREE_USED (decl) = 1;      /* Prevent warning for shadowing with these.  */      DECL_ABSTRACT_ORIGIN (decl) = tail;      pushdecl (decl);      /* Fully instantiate the address with the equivalent form so that the	 debugging information contains the actual register, instead of the	 virtual register.   Do this by not passing an insn to	 subst_constants.  */      subst_constants (&new_decl_rtl, NULL_RTX, map);      apply_change_group ();      DECL_RTL (decl) = new_decl_rtl;    }}/* Given a BLOCK node LET, push decls and levels so as to construct in the   current function a tree of contexts isomorphic to the one that is given.   LEVEL indicates how far down into the BLOCK tree is the node we are   currently traversing.  It is always zero except for recursive calls.   MAP, if nonzero, is a pointer to an inline_remap map which indicates how   registers used in the DECL_RTL field should be remapped.  If it is zero,   no mapping is necessary.  */static voidintegrate_decl_tree (let, level, map)     tree let;     int level;     struct inline_remap *map;{  tree t, node;  if (level > 0)    pushlevel (0);    for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))    {      tree d = build_decl (TREE_CODE (t), DECL_NAME (t), TREE_TYPE (t));      DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t);      DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t);      if (DECL_RTL (t) != 0)	{	  DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map);	  /* Fully instantiate the address with the equivalent form so that the	     debugging information contains the actual register, instead of the	     virtual register.   Do this by not passing an insn to	     subst_constants.  */	  subst_constants (&DECL_RTL (d), NULL_RTX, map);	  apply_change_group ();	}      else if (DECL_RTL (t))	DECL_RTL (d) = copy_rtx (DECL_RTL (t));      DECL_EXTERNAL (d) = DECL_EXTERNAL (t);      TREE_STATIC (d) = TREE_STATIC (t);      TREE_PUBLIC (d) = TREE_PUBLIC (t);      TREE_CONSTANT (d) = TREE_CONSTANT (t);      TREE_ADDRESSABLE (d) = TREE_ADDRESSABLE (t);      TREE_READONLY (d) = TREE_READONLY (t);      TREE_SIDE_EFFECTS (d) = TREE_SIDE_EFFECTS (t);      /* These args would always appear unused, if not for this.  */      TREE_USED (d) = 1;      /* Prevent warning for shadowing with these.  */      DECL_ABSTRACT_ORIGIN (d) = t;      pushdecl (d);    }  for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))    integrate_decl_tree (t, level + 1, map);  if (level > 0)    {      node = poplevel (1, 0, 0);      if (node)	{	  TREE_USED (node) = TREE_USED (let);	  BLOCK_ABSTRACT_ORIGIN (node) = let;	}    }}/* Create a new copy of an rtx.   Recursively copies the operands of the rtx,   except for those few rtx codes that are sharable.   We always return an rtx that is similar to that incoming rtx, with the   exception of possibly changing a REG to a SUBREG or vice versa.  No   rtl is ever emitted.   Handle constants that need to be placed in the constant pool by   calling `force_const_mem'.  */rtxcopy_rtx_and_substitute (orig, map)     register rtx orig;     struct inline_remap *map;{  register rtx copy, temp;  register int i, j;  register RTX_CODE code;  register enum machine_mode mode;  register char *format_ptr;  int regno;  if (orig == 0)    return 0;  code = GET_CODE (orig);  mode = GET_MODE (orig);  switch (code)    {    case REG:      /* If the stack pointer register shows up, it must be part of	 stack-adjustments (*not* because we eliminated the frame pointer!).	 Small hard registers are returned as-is.  Pseudo-registers	 go through their `reg_map'.  */      regno = REGNO (orig);      if (regno <= LAST_VIRTUAL_REGISTER)	{	  /* Some hard registers are also mapped,	     but others are not translated.  */	  if (map->reg_map[regno] != 0)	    return map->reg_map[regno];	  /* If this is the virtual frame pointer, make space in current	     function's stack frame for the stack frame of the inline function.	     Copy the address of this area into a pseudo.  Map	     virtual_stack_vars_rtx to this pseudo and set up a constant	     equivalence for it to be the address.  This will substitute the	     address into insns where it can be substituted and use the new	     pseudo where it can't.  */	  if (regno == VIRTUAL_STACK_VARS_REGNUM)	    {	      rtx loc, seq;	      int size = DECL_FRAME_SIZE (map->fndecl);	      int rounded;	      start_sequence ();	      loc = assign_stack_temp (BLKmode, size, 1);	      loc = XEXP (loc, 0);#ifdef FRAME_GROWS_DOWNWARD	      /* In this case, virtual_stack_vars_rtx points to one byte		 higher than the top of the frame area.  So compute the offset		 to one byte higher than our substitute frame.		 Keep the fake frame pointer aligned like a real one.  */	      rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);	      loc = plus_constant (loc, rounded);#endif	      map->reg_map[regno] = temp		= force_reg (Pmode, force_operand (loc, NULL_RTX));	      map->const_equiv_map[REGNO (temp)] = loc;	      map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;	      seq = gen_sequence ();	      end_sequence ();	      emit_insn_after (seq, map->insns_at_start);	      return temp;	    }	  else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)	    {	      /* Do the same for a block to contain any arguments referenced		 in memory. */	      rtx loc, seq;	      int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));	      start_sequence ();	      loc = assign_stack_temp (BLKmode, size, 1);	      loc = XEXP (loc, 0);	      /* When arguments grow downward, the virtual incoming 		 args pointer points to the top of the argument block,		 so the remapped location better do the same. */#ifdef ARGS_GROW_DOWNWARD	      loc = plus_constant (loc, size);#endif	      map->reg_map[regno] = temp		= force_reg (Pmode, force_operand (loc, NULL_RTX));	      map->const_equiv_map[REGNO (temp)] = loc;	      map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;	      seq = gen_sequence ();	      end_sequence ();	      emit_insn_after (seq, map->insns_at_start);	      return temp;	    }	  else if (REG_FUNCTION_VALUE_P (orig))	    {	      /* This is a reference to the function return value.  If		 the function doesn't have a return value, error.  If the		 mode doesn't agree, make a SUBREG.  */	      if (map->inline_target == 0)		/* Must be unrolling loops or replicating code if we		   reach here, so return the register unchanged.  */		return orig;	      else if (mode != GET_MODE (map->inline_target))		return gen_rtx (SUBREG, mode, map->inline_target, 0);	      else		return map->inline_target;	    }	  return orig;	}      if (map->reg_map[regno] == NULL)	{	  map->reg_map[regno] = gen_reg_rtx (mode);	  REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (

⌨️ 快捷键说明

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