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

📄 function.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* Free all temporary slots used in T, an RTL_EXPR node.  */voidfree_temps_for_rtl_expr (t)     tree t;{  struct temp_slot *p;  for (p = temp_slots; p; p = p->next)    if (p->rtl_expr == t)      p->in_use = 0;  combine_temp_slots ();}/* Mark all temporaries ever allocated in this function as not suitable   for reuse until the current level is exited.  */voidmark_all_temps_used (){  struct temp_slot *p;  for (p = temp_slots; p; p = p->next)    {      p->in_use = p->keep = 1;      p->level = MIN (p->level, temp_slot_level);    }}/* Push deeper into the nesting level for stack temporaries.  */voidpush_temp_slots (){  temp_slot_level++;}/* Pop a temporary nesting level.  All slots in use in the current level   are freed.  */voidpop_temp_slots (){  struct temp_slot *p;  for (p = temp_slots; p; p = p->next)    if (p->in_use && p->level == temp_slot_level && p->rtl_expr == 0)      p->in_use = 0;  combine_temp_slots ();  temp_slot_level--;}/* Initialize temporary slots.  */voidinit_temp_slots (){  /* We have not allocated any temporaries yet.  */  temp_slots = 0;  temp_slot_level = 0;  target_temp_slot_level = 0;}/* Retroactively move an auto variable from a register to a stack slot.   This is done when an address-reference to the variable is seen.  */voidput_var_into_stack (decl)     tree decl;{  register rtx reg;  enum machine_mode promoted_mode, decl_mode;  struct function *function = 0;  tree context;  int can_use_addressof;  if (output_bytecode)    return;    context = decl_function_context (decl);  /* Get the current rtl used for this object and it's original mode.  */  reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl);  /* No need to do anything if decl has no rtx yet     since in that case caller is setting TREE_ADDRESSABLE     and a stack slot will be assigned when the rtl is made.  */  if (reg == 0)    return;  /* Get the declared mode for this object.  */  decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))	       : DECL_MODE (decl));  /* Get the mode it's actually stored in.  */  promoted_mode = GET_MODE (reg);  /* If this variable comes from an outer function,     find that function's saved context.  */  if (context != current_function_decl && context != inline_function_decl)    for (function = outer_function_chain; function; function = function->next)      if (function->decl == context)	break;  /* If this is a variable-size object with a pseudo to address it,     put that pseudo into the stack, if the var is nonlocal.  */  if (DECL_NONLOCAL (decl)      && GET_CODE (reg) == MEM      && GET_CODE (XEXP (reg, 0)) == REG      && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)    {      reg = XEXP (reg, 0);      decl_mode = promoted_mode = GET_MODE (reg);    }  can_use_addressof    = (function == 0       /* FIXME make it work for promoted modes too */       && decl_mode == promoted_mode#ifdef NON_SAVING_SETJMP       && ! (NON_SAVING_SETJMP && current_function_calls_setjmp)#endif       );  /* If we can't use ADDRESSOF, make sure we see through one we already     generated.  */  if (! can_use_addressof && GET_CODE (reg) == MEM      && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)    reg = XEXP (XEXP (reg, 0), 0);  /* Now we should have a value that resides in one or more pseudo regs.  */  if (GET_CODE (reg) == REG)    {      /* If this variable lives in the current function and we don't need	 to put things in the stack for the sake of setjmp, try to keep it	 in a register until we know we actually need the address.  */      if (can_use_addressof)	gen_mem_addressof (reg, decl);      else	put_reg_into_stack (function, reg, TREE_TYPE (decl),			    promoted_mode, decl_mode,			    TREE_SIDE_EFFECTS (decl), 0);    }  else if (GET_CODE (reg) == CONCAT)    {      /* A CONCAT contains two pseudos; put them both in the stack.	 We do it so they end up consecutive.  */      enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));      tree part_type = TREE_TYPE (TREE_TYPE (decl));#ifdef FRAME_GROWS_DOWNWARD      /* Since part 0 should have a lower address, do it second.  */      put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,			  part_mode, TREE_SIDE_EFFECTS (decl), 0);      put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,			  part_mode, TREE_SIDE_EFFECTS (decl), 0);#else      put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,			  part_mode, TREE_SIDE_EFFECTS (decl), 0);      put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,			  part_mode, TREE_SIDE_EFFECTS (decl), 0);#endif      /* Change the CONCAT into a combined MEM for both parts.  */      PUT_CODE (reg, MEM);      MEM_VOLATILE_P (reg) = MEM_VOLATILE_P (XEXP (reg, 0));      /* The two parts are in memory order already.	 Use the lower parts address as ours.  */      XEXP (reg, 0) = XEXP (XEXP (reg, 0), 0);      /* Prevent sharing of rtl that might lose.  */      if (GET_CODE (XEXP (reg, 0)) == PLUS)	XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));    }  else    return;    if (flag_check_memory_usage)    emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,		       XEXP (reg, 0), ptr_mode,		       GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),		       TYPE_MODE (sizetype),		       GEN_INT (MEMORY_USE_RW),		       TYPE_MODE (integer_type_node));}/* Subroutine of put_var_into_stack.  This puts a single pseudo reg REG   into the stack frame of FUNCTION (0 means the current function).   DECL_MODE is the machine mode of the user-level data type.   PROMOTED_MODE is the machine mode of the register.   VOLATILE_P is nonzero if this is for a "volatile" decl.  */static voidput_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,		    original_regno)     struct function *function;     rtx reg;     tree type;     enum machine_mode promoted_mode, decl_mode;     int volatile_p;     int original_regno;{  rtx new = 0;  int regno = original_regno;  if (regno == 0)    regno = REGNO (reg);  if (function)    {      if (regno < function->max_parm_reg)	new = function->parm_reg_stack_loc[regno];      if (new == 0)	new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),					0, function);    }  else    {      if (regno < max_parm_reg)	new = parm_reg_stack_loc[regno];      if (new == 0)	new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);    }  PUT_MODE (reg, decl_mode);  XEXP (reg, 0) = XEXP (new, 0);  /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */  MEM_VOLATILE_P (reg) = volatile_p;  PUT_CODE (reg, MEM);  /* If this is a memory ref that contains aggregate components,     mark it as such for cse and loop optimize.  */  MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);  /* Now make sure that all refs to the variable, previously made     when it was a register, are fixed up to be valid again.  */  if (function)    {      struct var_refs_queue *temp;      /* Variable is inherited; fix it up when we get back to its function.  */      push_obstacks (function->function_obstack,		     function->function_maybepermanent_obstack);      /* See comment in restore_tree_status in tree.c for why this needs to be	 on saveable obstack.  */      temp	= (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));      temp->modified = reg;      temp->promoted_mode = promoted_mode;      temp->unsignedp = TREE_UNSIGNED (type);      temp->next = function->fixup_var_refs_queue;      function->fixup_var_refs_queue = temp;      pop_obstacks ();    }  else    /* Variable is local; fix it up now.  */    fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type));}static voidfixup_var_refs (var, promoted_mode, unsignedp)     rtx var;     enum machine_mode promoted_mode;     int unsignedp;{  tree pending;  rtx first_insn = get_insns ();  struct sequence_stack *stack = sequence_stack;  tree rtl_exps = rtl_expr_chain;  /* Must scan all insns for stack-refs that exceed the limit.  */  fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);  /* Scan all pending sequences too.  */  for (; stack; stack = stack->next)    {      push_to_sequence (stack->first);      fixup_var_refs_insns (var, promoted_mode, unsignedp,			    stack->first, stack->next != 0);      /* Update remembered end of sequence	 in case we added an insn at the end.  */      stack->last = get_last_insn ();      end_sequence ();    }  /* Scan all waiting RTL_EXPRs too.  */  for (pending = rtl_exps; pending; pending = TREE_CHAIN (pending))    {      rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));      if (seq != const0_rtx && seq != 0)	{	  push_to_sequence (seq);	  fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);	  end_sequence ();	}    }}/* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is   some part of an insn.  Return a struct fixup_replacement whose OLD   value is equal to X.  Allocate a new structure if no such entry exists.  */static struct fixup_replacement *find_fixup_replacement (replacements, x)     struct fixup_replacement **replacements;     rtx x;{  struct fixup_replacement *p;  /* See if we have already replaced this.  */  for (p = *replacements; p && p->old != x; p = p->next)    ;  if (p == 0)    {      p = (struct fixup_replacement *) oballoc (sizeof (struct fixup_replacement));      p->old = x;      p->new = 0;      p->next = *replacements;      *replacements = p;    }  return p;}/* Scan the insn-chain starting with INSN for refs to VAR   and fix them up.  TOPLEVEL is nonzero if this chain is the   main chain of insns for the current function.  */static voidfixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)     rtx var;     enum machine_mode promoted_mode;     int unsignedp;     rtx insn;     int toplevel;{  rtx call_dest = 0;  while (insn)    {      rtx next = NEXT_INSN (insn);      rtx note;      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')	{	  /* If this is a CLOBBER of VAR, delete it.	     If it has a REG_LIBCALL note, delete the REG_LIBCALL	     and REG_RETVAL notes too.  */ 	  if (GET_CODE (PATTERN (insn)) == CLOBBER	      && XEXP (PATTERN (insn), 0) == var)	    {	      if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)		/* The REG_LIBCALL note will go away since we are going to		   turn INSN into a NOTE, so just delete the		   corresponding REG_RETVAL note.  */		remove_note (XEXP (note, 0),			     find_reg_note (XEXP (note, 0), REG_RETVAL,					    NULL_RTX));	      /* In unoptimized compilation, we shouldn't call delete_insn		 except in jump.c doing warnings.  */	      PUT_CODE (insn, NOTE);	      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;	      NOTE_SOURCE_FILE (insn) = 0;	    }	  /* The insn to load VAR from a home in the arglist	     is now a no-op.  When we see it, just delete it.  */	  else if (toplevel		   && GET_CODE (PATTERN (insn)) == SET		   && SET_DEST (PATTERN (insn)) == var		   /* If this represents the result of an insn group,		      don't delete the insn.  */		   && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0		   && rtx_equal_p (SET_SRC (PATTERN (insn)), var))	    {	      /* In unoptimized compilation, we shouldn't call delete_insn		 except in jump.c doing warnings.  */	      PUT_CODE (insn, NOTE);	      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;	      NOTE_SOURCE_FILE (insn) = 0;	      if (insn == last_parm_insn)		last_parm_insn = PREV_INSN (next);	    }	  else	    {	      struct fixup_replacement *replacements = 0;	      rtx next_insn = NEXT_INSN (insn);	      if (SMALL_REGISTER_CLASSES)		{		  /* If the insn that copies the results of a CALL_INSN		     into a pseudo now references VAR, we have to use an		     intermediate pseudo since we want the life of the		     return value register to be only a single insn.		     If we don't use an intermediate pseudo, such things as		     address computations to make the address of VAR valid		     if it is not can be placed between the CALL_INSN and INSN.		     To make sure this doesn't happen, we record the destination		     of the CALL_INSN and see if the next insn uses both that		     and VAR.  */		  if (call_dest != 0 && GET_CODE (insn) == INSN

⌨️ 快捷键说明

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