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

📄 stmt.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs).   FORMALS is the chain of decls of formals.   Return 1 if this can be done;   otherwise return 0 and do not emit any code.  */static inttail_recursion_args (actuals, formals)     tree actuals, formals;{  register tree a = actuals, f = formals;  register int i;  register rtx *argvec;  /* Check that number and types of actuals are compatible     with the formals.  This is not always true in valid C code.     Also check that no formal needs to be addressable     and that all formals are scalars.  */  /* Also count the args.  */  for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)    {      if (TREE_TYPE (TREE_VALUE (a)) != TREE_TYPE (f))	return 0;      if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)	return 0;    }  if (a != 0 || f != 0)    return 0;  /* Compute all the actuals.  */  argvec = (rtx *) alloca (i * sizeof (rtx));  for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)    argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0);  /* Find which actual values refer to current values of previous formals.     Copy each of them now, before any formal is changed.  */  for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)    {      int copy = 0;      register int j;      for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++)	if (reg_mentioned_p (DECL_RTL (f), argvec[i]))	  { copy = 1; break; }      if (copy)	argvec[i] = copy_to_reg (argvec[i]);    }  /* Store the values of the actuals into the formals.  */  for (f = formals, a = actuals, i = 0; f;       f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++)    {      if (DECL_MODE (f) == GET_MODE (argvec[i]))	emit_move_insn (DECL_RTL (f), argvec[i]);      else	convert_move (DECL_RTL (f), argvec[i],		      TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a))));    }  return 1;}/* Generate the RTL code for entering a binding contour.   The variables are declared one by one, by calls to `expand_decl'.   EXIT_FLAG is nonzero if this construct should be visible to   `exit_something'.  */voidexpand_start_bindings (exit_flag)     int exit_flag;{  struct nesting *thisblock    = (struct nesting *) xmalloc (sizeof (struct nesting));  rtx note = emit_note (0, NOTE_INSN_BLOCK_BEG);  /* Make an entry on block_stack for the block we are entering.  */  thisblock->next = block_stack;  thisblock->all = nesting_stack;  thisblock->depth = ++nesting_depth;  thisblock->data.block.stack_level = 0;  thisblock->data.block.cleanups = 0;  /* We build this even if the cleanups lists are empty     because we rely on having an element in the chain     for each block that is pending.  */  thisblock->data.block.outer_cleanups    = (block_stack       ? tree_cons (NULL_TREE, block_stack->data.block.cleanups,		    block_stack->data.block.outer_cleanups)       : 0);  thisblock->data.block.label_chain = 0;  thisblock->data.block.innermost_stack_block = stack_block_stack;  thisblock->data.block.first_insn = note;  thisblock->data.block.block_start_count = ++block_start_count;  thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;  block_stack = thisblock;  nesting_stack = thisblock;}/* Output a USE for any register use in RTL.   This is used with -noreg to mark the extent of lifespan   of any registers used in a user-visible variable's DECL_RTL.  */voiduse_variable (rtl)     rtx rtl;{  if (GET_CODE (rtl) == REG)    /* This is a register variable.  */    emit_insn (gen_rtx (USE, VOIDmode, rtl));  else if (GET_CODE (rtl) == SUBREG)    use_variable (SUBREG_REG (rtl));  else if (GET_CODE (rtl) == MEM	   && GET_CODE (XEXP (rtl, 0)) == REG	   && XEXP (rtl, 0) != frame_pointer_rtx	   && XEXP (rtl, 0) != arg_pointer_rtx)    /* This is a variable-sized structure.  */    emit_insn (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)));}/* Like use_variable except that it outputs the USEs after INSN   instead of at the end of the insn-chain.  */static voiduse_variable_after (rtl, insn)     rtx rtl, insn;{  if (GET_CODE (rtl) == REG)    /* This is a register variable.  */    emit_insn_after (gen_rtx (USE, VOIDmode, rtl), insn);  else if (GET_CODE (rtl) == SUBREG)    use_variable_after (SUBREG_REG (rtl), insn);  else if (GET_CODE (rtl) == MEM	   && GET_CODE (XEXP (rtl, 0)) == REG	   && XEXP (rtl, 0) != frame_pointer_rtx	   && XEXP (rtl, 0) != arg_pointer_rtx)    /* This is a variable-sized structure.  */    emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)), insn);}/* Generate RTL code to terminate a binding contour.   VARS is the chain of VAR_DECL nodes   for the variables bound in this contour.   MARK_ENDS is nonzero if we should put a note at the beginning   and end of this binding contour.   DONT_JUMP_IN is nonzero if it is not valid to jump into this contour.   (That is true automatically if the contour has a saved stack level.)  */voidexpand_end_bindings (vars, mark_ends, dont_jump_in)     tree vars;     int mark_ends;     int dont_jump_in;{  register struct nesting *thisblock = block_stack;  register tree decl;  if (warn_unused)    for (decl = vars; decl; decl = TREE_CHAIN (decl))      if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL)	warning_with_decl (decl, "unused variable `%s'");  /* Mark the beginning and end of the scope if requested.  */  if (mark_ends)    emit_note (0, NOTE_INSN_BLOCK_END);  else    /* Get rid of the beginning-mark if we don't make an end-mark.  */    NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;  if (thisblock->exit_label)    {      do_pending_stack_adjust ();      emit_label (thisblock->exit_label);    }  if (dont_jump_in      || thisblock->data.block.stack_level != 0      || thisblock->data.block.cleanups != 0)    {      struct label_chain *chain;      /* Any labels in this block are no longer valid to go to.	 Mark them to cause an error message.  */      for (chain = thisblock->data.block.label_chain; chain; chain = chain->next)	{	  TREE_PACKED (chain->label) = 1;	  /* If any goto without a fixup came to this label,	     that must be an error, because gotos without fixups	     come from outside all saved stack-levels and all cleanups.  */	  if (TREE_ADDRESSABLE (chain->label))	    error_with_decl (chain->label,			     "label `%s' used before containing binding contour");	}    }  /* Restore stack level in effect before the block     (only if variable-size objects allocated).  */  if (thisblock->data.block.stack_level != 0      || thisblock->data.block.cleanups != 0)    {      /* Perform any cleanups associated with the block.  */      expand_cleanups (thisblock->data.block.cleanups, 0);      /* Restore the stack level.  */      if (thisblock->data.block.stack_level != 0)	{	  do_pending_stack_adjust ();	  emit_move_insn (stack_pointer_rtx,			  thisblock->data.block.stack_level);	}      /* Any gotos out of this block must also do these things.	 Also report any gotos with fixups that came to labels in this level.  */      fixup_gotos (thisblock,		   thisblock->data.block.stack_level,		   thisblock->data.block.cleanups,		   thisblock->data.block.first_insn,		   dont_jump_in);    }  /* If doing stupid register allocation, make sure lives of all     register variables declared here extend thru end of scope.  */  if (obey_regdecls)    for (decl = vars; decl; decl = TREE_CHAIN (decl))      {	rtx rtl = DECL_RTL (decl);	if (TREE_CODE (decl) == VAR_DECL && rtl != 0)	  use_variable (rtl);      }  /* Restore block_stack level for containing block.  */  stack_block_stack = thisblock->data.block.innermost_stack_block;  POPSTACK (block_stack);}/* Generate RTL for the automatic variable declaration DECL.   (Other kinds of declarations are simply ignored if seen here.)   CLEANUP is an expression to be executed at exit from this binding contour;   for example, in C++, it might call the destructor for this variable.   If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them   either before or after calling `expand_decl' but before compiling   any subsequent expressions.  This is because CLEANUP may be expanded   more than once, on different branches of execution.   For the same reason, CLEANUP may not contain a CALL_EXPR   except as its topmost node--else `preexpand_calls' would get confused.   If CLEANUP is nonzero and DECL is zero, we record a cleanup   that is not associated with any particular variable.   There is no special support here for C++ constructors.   They should be handled by the proper code in DECL_INITIAL.  */voidexpand_decl (decl, cleanup)     register tree decl;     tree cleanup;{  struct nesting *thisblock = block_stack;  tree type;    /* Record the cleanup if there is one.  */  if (cleanup != 0)    {      thisblock->data.block.cleanups	= temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);      /* If this block has a cleanup, it belongs in stack_block_stack.  */      stack_block_stack = thisblock;    }  if (decl == NULL_TREE)    {      /* This was a cleanup with no variable.  */      if (cleanup == 0)	abort ();      return;    }  type = TREE_TYPE (decl);  /* Aside from that, only automatic variables need any expansion done.     Static and external variables, and external functions,     will be handled by `assemble_variable' (called from finish_decl).     TYPE_DECL and CONST_DECL require nothing.     PARM_DECLs are handled in `assign_parms'.  */  if (TREE_CODE (decl) != VAR_DECL)    return;  if (TREE_STATIC (decl) || TREE_EXTERNAL (decl))    return;  /* Create the RTL representation for the variable.  */  if (type == error_mark_node)    DECL_RTL (decl) = gen_rtx (MEM, BLKmode, const0_rtx);  else if (DECL_SIZE (decl) == 0)    /* Variable with incomplete type.  */    {      if (DECL_INITIAL (decl) == 0)	/* Error message was already done; now avoid a crash.  */	DECL_RTL (decl) = assign_stack_local (DECL_MODE (decl), 0);      else	/* An initializer is going to decide the size of this array.	   Until we know the size, represent its address with a reg.  */	DECL_RTL (decl) = gen_rtx (MEM, BLKmode, gen_reg_rtx (Pmode));    }  else if (DECL_MODE (decl) != BLKmode	   /* If -ffloat-store, don't put explicit float vars	      into regs.  */	   && !(flag_float_store		&& TREE_CODE (type) == REAL_TYPE)	   && ! TREE_VOLATILE (decl)	   && ! TREE_ADDRESSABLE (decl)	   && (TREE_REGDECL (decl) || ! obey_regdecls))    {      /* Automatic variable that can go in a register.  */      DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));      if (TREE_CODE (type) == POINTER_TYPE)	mark_reg_pointer (DECL_RTL (decl));      REG_USERVAR_P (DECL_RTL (decl)) = 1;    }  else if (TREE_LITERAL (DECL_SIZE (decl)))    {      rtx oldaddr = 0;      rtx addr;      /* If we previously made RTL for this decl, it must be an array	 whose size was determined by the initializer.	 The old address was a register; set that register now	 to the proper address.  */      if (DECL_RTL (decl) != 0)	{	  if (GET_CODE (DECL_RTL (decl)) != MEM	      || GET_CODE (XEXP (DECL_RTL (decl), 0)) != REG)	    abort ();	  oldaddr = XEXP (DECL_RTL (decl), 0);	}      /* Variable of fixed size that goes on the stack.  */      DECL_RTL (decl)	= assign_stack_local (DECL_MODE (decl),			      (TREE_INT_CST_LOW (DECL_SIZE (decl))			       * DECL_SIZE_UNIT (decl)			       + BITS_PER_UNIT - 1)			      / BITS_PER_UNIT);      if (oldaddr)	{	  addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);	  emit_move_insn (oldaddr, addr);	}      /* If this is a memory ref that contains aggregate components,	 mark it as such for cse and loop optimize.  */      MEM_IN_STRUCT_P (DECL_RTL (decl))	= (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE	   || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE	   || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);#if 0      /* If this is in memory because of -ffloat-store,	 set the volatile bit, to prevent optimizations from	 undoing the effects.  */      if (flag_float_store && TREE_CODE (type) == REAL_TYPE)	MEM_VOLATILE_P (DECL_RTL (decl)) = 1;#endif    }  else    /* Dynamic-size object: must push space on the stack.  */    {      rtx address, size;      frame_pointer_needed = 1;      /* Record the stack pointer on entry to block, if have	 not already done so.  */      if (thisblock->data.block.stack_level == 0)	{	  do_pending_stack_adjust ();	  thisblock->data.block.stack_level	    = copy_to_reg (stack_pointer_rtx);	  stack_block_stack = thisblock;	}      /* Compute the variable's size, in bytes.  */      size = expand_expr (convert_units (DECL_SIZE (decl),					 DECL_SIZE_UNIT (decl),					 BITS_PER_UNIT),			  0, VOIDmode, 0);      /* Round it up to this machine's required stack boundary.  */#ifdef STACK_BOUNDARY      /* Avoid extra code if we can prove it's a multiple already.  */      if (DECL_SIZE_UNIT (decl) % STACK_BOUNDARY)	{#ifdef STACK_POINTER_OFFSET	  /* Avoid extra code if we can prove that adding STACK_POINTER_OFFSET	     will not give this address invalid alignment.  */	  if (DECL_ALIGN (decl) > ((S

⌨️ 快捷键说明

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