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

📄 stmt.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   Make an entry on loop_stack to record the labels associated with   this loop.  */voidexpand_start_loop (exit_flag)     int exit_flag;{  register struct nesting *thisloop    = (struct nesting *) xmalloc (sizeof (struct nesting));  /* Make an entry on loop_stack for the loop we are entering.  */  thisloop->next = loop_stack;  thisloop->all = nesting_stack;  thisloop->depth = ++nesting_depth;  thisloop->data.loop.start_label = gen_label_rtx ();  thisloop->data.loop.end_label = gen_label_rtx ();  thisloop->data.loop.continue_label = thisloop->data.loop.start_label;  thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0;  loop_stack = thisloop;  nesting_stack = thisloop;  do_pending_stack_adjust ();  emit_queue ();  emit_note (0, NOTE_INSN_LOOP_BEG);  emit_label (thisloop->data.loop.start_label);}/* Like expand_start_loop but for a loop where the continuation point   (for expand_continue_loop) will be specified explicitly.  */voidexpand_start_loop_continue_elsewhere (exit_flag)     int exit_flag;{  expand_start_loop (exit_flag);  loop_stack->data.loop.continue_label = gen_label_rtx ();}/* Specify the continuation point for a loop started with   expand_start_loop_continue_elsewhere.   Use this at the point in the code to which a continue statement   should jump.  */voidexpand_loop_continue_here (){  do_pending_stack_adjust ();  emit_note (0, NOTE_INSN_LOOP_CONT);  emit_label (loop_stack->data.loop.continue_label);}/* Finish a loop.  Generate a jump back to the top and the loop-exit label.   Pop the block off of loop_stack.  */voidexpand_end_loop (){  register rtx insn = get_last_insn ();  register rtx start_label = loop_stack->data.loop.start_label;  do_pending_stack_adjust ();  while (insn && GET_CODE (insn) == NOTE)    insn = PREV_INSN (insn);  /* If optimizing, perhaps reorder the loop.  If the loop     does not already end with a conditional branch, scan over the     insns within the loop and try to find a conditional branch which     is a loop exit.  If such an insn is found, move that insn (and     its predecessors) to the end of the loop so that the conditional     exit and the jump back can perhaps be optimized into one insn.  */  if (optimize && insn != 0      &&      ! (GET_CODE (insn) == JUMP_INSN	 && GET_CODE (PATTERN (insn)) == SET	 && SET_DEST (PATTERN (insn)) == pc_rtx	 && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE))    {      /* Scan insns from the top of the loop looking for a qualified	 conditional exit.  */      for (insn = loop_stack->data.loop.start_label; insn; insn= NEXT_INSN (insn))	if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET	    && SET_DEST (PATTERN (insn)) == pc_rtx	    && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE	    &&	    ((GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == LABEL_REF	      && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0)		  == loop_stack->data.loop.end_label))	     ||	     (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 2)) == LABEL_REF	      && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0)		  == loop_stack->data.loop.end_label))))	  break;      if (insn != 0)	{	  /* We found one.  Move everything from there up	     to the end of the loop, and add a jump into the loop	     to jump to there.  */	  register rtx newstart_label = gen_label_rtx ();	  emit_label_after (newstart_label, PREV_INSN (start_label));	  reorder_insns (start_label, insn, get_last_insn ());	  emit_jump_insn_after (gen_jump (start_label), PREV_INSN (newstart_label));	  emit_barrier_after (PREV_INSN (newstart_label));	  start_label = newstart_label;	}    }  emit_jump (start_label);  emit_note (0, NOTE_INSN_LOOP_END);  emit_label (loop_stack->data.loop.end_label);  POPSTACK (loop_stack);  last_expr_type = 0;}/* Generate a jump to the current loop's continue-point.   This is usually the top of the loop, but may be specified   explicitly elsewhere.  If not currently inside a loop,   return 0 and do nothing; caller will print an error message.  */intexpand_continue_loop (){  last_expr_type = 0;  if (loop_stack == 0)    return 0;  expand_goto_internal (0, loop_stack->data.loop.continue_label, 0);  return 1;}/* Generate a jump to exit the current loop.  If not currently inside a loop,   return 0 and do nothing; caller will print an error message.  */intexpand_exit_loop (){  last_expr_type = 0;  if (loop_stack == 0)    return 0;  expand_goto_internal (0, loop_stack->data.loop.end_label, 0);  return 1;}/* Generate a conditional jump to exit the current loop if COND   evaluates to zero.  If not currently inside a loop,   return 0 and do nothing; caller will print an error message.  */intexpand_exit_loop_if_false (cond)     tree cond;{  last_expr_type = 0;  if (loop_stack == 0)    return 0;  do_jump (cond, loop_stack->data.loop.end_label, NULL);  return 1;}/* Return non-zero if currently inside a loop.  */intinside_loop (){  return loop_stack != 0;}/* Generate a jump to exit the current loop, conditional, binding contour   or case statement.  Not all such constructs are visible to this function,   only those started with EXIT_FLAG nonzero.  Individual languages use   the EXIT_FLAG parameter to control which kinds of constructs you can   exit this way.   If not currently inside anything that can be exited,   return 0 and do nothing; caller will print an error message.  */intexpand_exit_something (){  struct nesting *n;  last_expr_type = 0;  for (n = nesting_stack; n; n = n->all)    if (n->exit_label != 0)      {	expand_goto_internal (0, n->exit_label, 0);	return 1;      }  return 0;}/* Generate RTL to return from the current function, with no value.   (That is, we do not do anything about returning any value.)  */voidexpand_null_return (){  struct nesting *block = block_stack;  rtx last_insn = 0;  /* Does any pending block have cleanups?  */  while (block && block->data.block.cleanups == 0)    block = block->next;  /* If yes, use a goto to return, since that runs cleanups.  */  expand_null_return_1 (last_insn, block != 0);}/* Output a return with no value.  If LAST_INSN is nonzero,   pretend that the return takes place after LAST_INSN.   If USE_GOTO is nonzero then don't use a return instruction;   go to the return label instead.  This causes any cleanups   of pending blocks to be executed normally.  */static voidexpand_null_return_1 (last_insn, use_goto)     rtx last_insn;     int use_goto;{  rtx end_label = cleanup_label ? cleanup_label : return_label;  clear_pending_stack_adjust ();  do_pending_stack_adjust ();  last_expr_type = 0;  /* PCC-struct return always uses an epilogue.  */  if (current_function_returns_pcc_struct || use_goto)    {      if (end_label == 0)	end_label = return_label = gen_label_rtx ();      expand_goto_internal (0, end_label, last_insn);      return;    }  /* Otherwise output a simple return-insn if one is available,     unless it won't do the job.  */#ifdef HAVE_return  if (HAVE_return && cleanup_label == 0)    {      emit_jump_insn (gen_return ());      emit_barrier ();      return;    }#endif  /* Otherwise jump to the epilogue.  */  expand_goto_internal (0, end_label, last_insn);}/* Generate RTL to evaluate the expression RETVAL and return it   from the current function.  */voidexpand_return (retval)     tree retval;{  /* If there are any cleanups to be performed, then they will     be inserted following LAST_INSN.  It is desirable     that the last_insn, for such purposes, should be the     last insn before computing the return value.  Otherwise, cleanups     which call functions can clobber the return value.  */  /* ??? rms: I think that is erroneous, because in C++ it would     run destructors on variables that might be used in the subsequent     computation of the return value.  */  rtx last_insn = 0;  register rtx val = 0;  register rtx op0;  tree retval_rhs;  int cleanups;  struct nesting *block;  /* Are any cleanups needed?  E.g. C++ destructors to be run?  */  cleanups = 0;  for (block = block_stack; block; block = block->next)    if (block->data.block.cleanups != 0)      {	cleanups = 1;	break;      }  if (TREE_CODE (retval) == RESULT_DECL)    retval_rhs = retval;  else if ((TREE_CODE (retval) == MODIFY_EXPR || TREE_CODE (retval) == INIT_EXPR)	   && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)    retval_rhs = TREE_OPERAND (retval, 1);  else if (TREE_TYPE (retval) == void_type_node)    /* Recognize tail-recursive call to void function.  */    retval_rhs = retval;  else    retval_rhs = NULL_TREE;  /* Only use `last_insn' if there are cleanups which must be run.  */  if (cleanups || cleanup_label != 0)    last_insn = get_last_insn ();  /* For tail-recursive call to current function,     just jump back to the beginning.     It's unsafe if any auto variable in this function     has its address taken; for simplicity,     require stack frame to be empty.  */  if (optimize && retval_rhs != 0      && frame_offset == STARTING_FRAME_OFFSET      && TREE_CODE (retval_rhs) == CALL_EXPR      && TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR      && TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0) == this_function      /* Finish checking validity, and if valid emit code	 to set the argument variables for the new call.  */      && tail_recursion_args (TREE_OPERAND (retval_rhs, 1),			      DECL_ARGUMENTS (this_function)))    {      if (tail_recursion_label == 0)	{	  tail_recursion_label = gen_label_rtx ();	  emit_label_after (tail_recursion_label,			    tail_recursion_reentry);	}      emit_queue ();      expand_goto_internal (0, tail_recursion_label, last_insn);      emit_barrier ();      return;    }#ifdef HAVE_return  /* This optimization is safe if there are local cleanups     because expand_null_return takes care of them.     ??? I think it should also be safe when there is a cleanup label,     because expand_null_return takes care of them, too.     Any reason why not?  */  if (HAVE_return && cleanup_label == 0      && ! current_function_returns_pcc_struct)    {      /* If this is  return x == y;  then generate	 if (x == y) return 1; else return 0;	 if we can do it with explicit return insns.  */      if (retval_rhs)	switch (TREE_CODE (retval_rhs))	  {	  case EQ_EXPR:	  case NE_EXPR:	  case GT_EXPR:	  case GE_EXPR:	  case LT_EXPR:	  case LE_EXPR:	  case TRUTH_ANDIF_EXPR:	  case TRUTH_ORIF_EXPR:	  case TRUTH_AND_EXPR:	  case TRUTH_OR_EXPR:	  case TRUTH_NOT_EXPR:	    op0 = gen_label_rtx ();	    val = DECL_RTL (DECL_RESULT (this_function));	    jumpifnot (retval_rhs, op0);	    emit_move_insn (val, const1_rtx);	    emit_insn (gen_rtx (USE, VOIDmode, val));	    expand_null_return ();	    emit_label (op0);	    emit_move_insn (val, const0_rtx);	    emit_insn (gen_rtx (USE, VOIDmode, val));	    expand_null_return ();	    return;	  }    }#endif /* HAVE_return */  if (cleanups      && retval_rhs != 0      && TREE_TYPE (retval_rhs) != void_type_node      && GET_CODE (DECL_RTL (DECL_RESULT (this_function))) == REG)    {      rtx last_insn;      /* Calculate the return value into a pseudo reg.  */      val = expand_expr (retval_rhs, 0, VOIDmode, 0);      emit_queue ();      /* Put the cleanups here.  */      last_insn = get_last_insn ();      /* Copy the value into hard return reg.  */      emit_move_insn (DECL_RTL (DECL_RESULT (this_function)), val);      val = DECL_RTL (DECL_RESULT (this_function));      if (GET_CODE (val) == REG)	emit_insn (gen_rtx (USE, VOIDmode, val));      expand_null_return_1 (last_insn, cleanups);    }  else    {      /* No cleanups or no hard reg used;	 calculate value into hard return reg	 and let cleanups come after.  */      val = expand_expr (retval, 0, VOIDmode, 0);      emit_queue ();      val = DECL_RTL (DECL_RESULT (this_function));      if (val && GET_CODE (val) == REG)	emit_insn (gen_rtx (USE, VOIDmode, val));      expand_null_return ();    }}/* Return 1 if the end of the generated RTX is not a barrier.   This means code already compiled can drop through.  */intdrop_through_at_end_p (){  rtx insn = get_last_insn ();  while (insn && GET_CODE (insn) == NOTE)    insn = PREV_INSN (insn);  return insn && GET_CODE (insn) != BARRIER;}/* Emit code to alter this function's formal parms for a tail-recursive call.

⌨️ 快捷键说明

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