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

📄 integrate.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.     Later we set TREE_READONLY to 0 if the parm is modified inside the fn.     Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values     for the parms, prior to elimination of virtual registers.     These values are needed for substituting parms properly.  */  max_parm_reg = max_parm_reg_num ();  parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));  head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);  if (current_function_uses_const_pool)    {      /* Replace any constant pool references with the actual constant.  We	 will put the constants back in the copy made below.  */      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))	if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')	  {	    save_constants (&PATTERN (insn));	    if (REG_NOTES (insn))	      save_constants (&REG_NOTES (insn));	  }      /* Clear out the constant pool so that we can recreate it with the	 copied constants below.  */      init_const_rtx_hash_table ();      clear_const_double_mem ();    }  max_uid = INSN_UID (head);  /* We have now allocated all that needs to be allocated permanently     on the rtx obstack.  Set our high-water mark, so that we     can free the rest of this when the time comes.  */  preserve_data ();  /* Copy the chain insns of this function.     Install the copied chain as the insns of this function,     for continued compilation;     the original chain is recorded as the DECL_SAVED_INSNS     for inlining future calls.  */  /* If there are insns that copy parms from the stack into pseudo registers,     those insns are not copied.  `expand_inline_function' must     emit the correct code to handle such things.  */  insn = get_insns ();  if (GET_CODE (insn) != NOTE)    abort ();  first_insn = rtx_alloc (NOTE);  NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);  NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);  INSN_UID (first_insn) = INSN_UID (insn);  PREV_INSN (first_insn) = NULL;  NEXT_INSN (first_insn) = NULL;  last_insn = first_insn;  /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.     Make these new rtx's now, and install them in regno_reg_rtx, so they     will be the official pseudo-reg rtx's for the rest of compilation.  */  reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));  len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);  for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)    reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,				    regno_reg_rtx[i], len);  bcopy (reg_map + LAST_VIRTUAL_REGISTER + 1,	 regno_reg_rtx + LAST_VIRTUAL_REGISTER + 1,	 (max_reg - (LAST_VIRTUAL_REGISTER + 1)) * sizeof (rtx));  /* Likewise each label rtx must have a unique rtx as its copy.  */  label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));  label_map -= min_labelno;  for (i = min_labelno; i < max_labelno; i++)    label_map[i] = gen_label_rtx ();  /* Record the mapping of old insns to copied insns.  */  insn_map = (rtx *) alloca (max_uid * sizeof (rtx));  bzero (insn_map, max_uid * sizeof (rtx));  /* Get the insn which signals the end of parameter setup code.  */  first_nonparm_insn = get_first_nonparm_insn ();  /* Copy any entries in regno_reg_rtx or DECL_RTLs that reference MEM     (the former occurs when a variable has its address taken)     since these may be shared and can be changed by virtual     register instantiation.  DECL_RTL values for our arguments     have already been copied by initialize_for_inline.  */  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_reg; i++)    if (GET_CODE (regno_reg_rtx[i]) == MEM)      XEXP (regno_reg_rtx[i], 0)	= copy_for_inline (XEXP (regno_reg_rtx[i], 0));  /* Copy the tree of subblocks of the function, and the decls in them.     We will use the copy for compiling this function, then restore the original     subblocks and decls for use when inlining this function.     Several parts of the compiler modify BLOCK trees.  In particular,     instantiate_virtual_regs will instantiate any virtual regs     mentioned in the DECL_RTLs of the decls, and loop     unrolling will replicate any BLOCK trees inside an unrolled loop.     The modified subblocks or DECL_RTLs would be incorrect for the original rtl     which we will use for inlining.  The rtl might even contain pseudoregs     whose space has been freed.  */  DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl));  DECL_ARGUMENTS (fndecl) = copy_decl_list (DECL_ARGUMENTS (fndecl));  /* Now copy each DECL_RTL which is a MEM,     so it is safe to modify their addresses.  */  copy_decl_rtls (DECL_INITIAL (fndecl));  /* The fndecl node acts as its own progenitor, so mark it as such.  */  DECL_ABSTRACT_ORIGIN (fndecl) = fndecl;  /* Now copy the chain of insns.  Do this twice.  The first copy the insn     itself and its body.  The second time copy of REG_NOTES.  This is because     a REG_NOTE may have a forward pointer to another insn.  */  for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))    {      orig_asm_operands_vector = 0;      if (insn == first_nonparm_insn)	in_nonparm_insns = 1;      switch (GET_CODE (insn))	{	case NOTE:	  /* No need to keep these.  */	  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)	    continue;	  copy = rtx_alloc (NOTE);	  NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);	  if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END)	    NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);	  else	    {	      NOTE_SOURCE_FILE (insn) = (char *) copy;	      NOTE_SOURCE_FILE (copy) = 0;	    }	  break;	case INSN:	case CALL_INSN:	case JUMP_INSN:	  copy = rtx_alloc (GET_CODE (insn));	  PATTERN (copy) = copy_for_inline (PATTERN (insn));	  INSN_CODE (copy) = -1;	  LOG_LINKS (copy) = NULL;	  RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);	  break;	case CODE_LABEL:	  copy = label_map[CODE_LABEL_NUMBER (insn)];	  LABEL_NAME (copy) = LABEL_NAME (insn);	  break;	case BARRIER:	  copy = rtx_alloc (BARRIER);	  break;	default:	  abort ();	}      INSN_UID (copy) = INSN_UID (insn);      insn_map[INSN_UID (insn)] = copy;      NEXT_INSN (last_insn) = copy;      PREV_INSN (copy) = last_insn;      last_insn = copy;    }  adjust_copied_decl_tree (DECL_INITIAL (fndecl));  /* Now copy the REG_NOTES.  */  for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn))    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'	&& insn_map[INSN_UID(insn)])      REG_NOTES (insn_map[INSN_UID (insn)])	= copy_for_inline (REG_NOTES (insn));  NEXT_INSN (last_insn) = NULL;  finish_inline (fndecl, head);  set_new_first_and_last_insn (first_insn, last_insn);}/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.   For example, this can copy a list made of TREE_LIST nodes.  While copying,   for each node copied which doesn't already have is DECL_ABSTRACT_ORIGIN   set to some non-zero value, set the DECL_ABSTRACT_ORIGIN of the copy to   point to the corresponding (abstract) original node.  */static treecopy_decl_list (list)     tree list;{  tree head;  register tree prev, next;  if (list == 0)    return 0;  head = prev = copy_node (list);  if (DECL_ABSTRACT_ORIGIN (head) == NULL_TREE)    DECL_ABSTRACT_ORIGIN (head) = list;  next = TREE_CHAIN (list);  while (next)    {      register tree copy;      copy = copy_node (next);      if (DECL_ABSTRACT_ORIGIN (copy) == NULL_TREE)	DECL_ABSTRACT_ORIGIN (copy) = next;      TREE_CHAIN (prev) = copy;      prev = copy;      next = TREE_CHAIN (next);    }  return head;}/* Make a copy of the entire tree of blocks BLOCK, and return it.  */static treecopy_decl_tree (block)     tree block;{  tree t, vars, subblocks;  vars = copy_decl_list (BLOCK_VARS (block));  subblocks = 0;  /* Process all subblocks.  */  for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))    {      tree copy = copy_decl_tree (t);      TREE_CHAIN (copy) = subblocks;      subblocks = copy;    }  t = copy_node (block);  BLOCK_VARS (t) = vars;  BLOCK_SUBBLOCKS (t) = nreverse (subblocks);  /* If the BLOCK being cloned is already marked as having been instantiated     from something else, then leave that `origin' marking alone.  Elsewise,     mark the clone as having originated from the BLOCK we are cloning.  */  if (BLOCK_ABSTRACT_ORIGIN (t) == NULL_TREE)    BLOCK_ABSTRACT_ORIGIN (t) = block;  return t;}/* Copy DECL_RTLs in all decls in the given BLOCK node.  */static voidcopy_decl_rtls (block)     tree block;{  tree t;  for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))    if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)      DECL_RTL (t) = copy_for_inline (DECL_RTL (t));  /* Process all subblocks.  */  for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))    copy_decl_rtls (t);}/* Make the insns and PARM_DECLs of the current function permanent   and record other information in DECL_SAVED_INSNS to allow inlining   of this function in subsequent calls.   This routine need not copy any insns because we are not going   to immediately compile the insns in the insn chain.  There   are two cases when we would compile the insns for FNDECL:   (1) when FNDECL is expanded inline, and (2) when FNDECL needs to   be output at the end of other compilation, because somebody took   its address.  In the first case, the insns of FNDECL are copied   as it is expanded inline, so FNDECL's saved insns are not   modified.  In the second case, FNDECL is used for the last time,   so modifying the rtl is not a problem.   ??? Actually, we do not verify that FNDECL is not inline expanded   by other functions which must also be written down at the end   of compilation.  We could set flag_no_inline to nonzero when   the time comes to write down such functions.  */voidsave_for_inline_nocopy (fndecl)     tree fndecl;{  rtx insn;  rtx head, copy;  tree parms;  int max_labelno, min_labelno, i, len;  int max_reg;  int max_uid;  rtx first_nonparm_insn;  int function_flags;  /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.     Later we set TREE_READONLY to 0 if the parm is modified inside the fn.     Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values     for the parms, prior to elimination of virtual registers.     These values are needed for substituting parms properly.  */  max_parm_reg = max_parm_reg_num ();  parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));  /* Make and emit a return-label if we have not already done so.  */  if (return_label == 0)    {      return_label = gen_label_rtx ();      emit_label (return_label);    }  head = initialize_for_inline (fndecl, get_first_label_num (),				max_label_num (), max_reg_num (), 0);  /* If there are insns that copy parms from the stack into pseudo registers,     those insns are not copied.  `expand_inline_function' must     emit the correct code to handle such things.  */  insn = get_insns ();  if (GET_CODE (insn) != NOTE)    abort ();  /* Get the insn which signals the end of parameter setup code.  */  first_nonparm_insn = get_first_nonparm_insn ();  /* Now just scan the chain of insns to see what happens to our     PARM_DECLs.  If a PARM_DECL is used but never modified, we     can substitute its rtl directly when expanding inline (and     perform constant folding when its incoming value is constant).     Otherwise, we have to copy its value into a new register and track     the new register's life.  */  for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))    {      if (insn == first_nonparm_insn)	in_nonparm_insns = 1;      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')	{	  if (current_function_uses_const_pool)	    {	      /* Replace any constant pool references with the actual constant.		 We will put the constant back if we need to write the		 function out after all.  */	      save_constants (&PATTERN (insn));	      if (REG_NOTES (insn))		save_constants (&REG_NOTES (insn));	    }	  /* Record what interesting things happen to our parameters.  */	  note_stores (PATTERN (insn), note_modified_parmregs);	}    }  /* We have now allocated all that needs to be allocated permanently     on the rtx obstack.  Set our high-water mark, so that we     can free the rest of this when the time comes.  */  preserve_data ();  finish_inline (fndecl, head);}/* Given PX, a pointer into an insn, search for references to the constant   pool.  Replace each with a CONST that has the mode of the original   constant, contains the constant, and has RTX_INTEGRATED_P set.   Similarly, constant pool addresses not enclosed in a MEM are replaced   with an ADDRESS rtx which also gives the constant, mode, and has   RTX_INTEGRATED_P set.  */static voidsave_constants (px)     rtx *px;{  rtx x;  int i, j; again:  x = *px;

⌨️ 快捷键说明

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