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

📄 stmt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* The outermost stack level that should be restored for this jump.     Each time a binding contour that resets the stack is exited,     if the target label is *not* yet defined, this slot is updated.  */  rtx stack_level;  /* List of lists of cleanup expressions to be run by this goto.     There is one element for each block that this goto is within.     The tail of this list can be 0 (was empty_cleanup_list),     if all remaining elements would be empty.     The TREE_VALUE contains the cleanup list of that block as of the     time this goto was seen.     The TREE_ADDRESSABLE flag is 1 for a block that has been exited.  */  tree cleanup_list_list;};static struct goto_fixup *goto_fixup_chain;/* Within any binding contour that must restore a stack level,   all labels are recorded with a chain of these structures.  */struct label_chain{  /* Points to following fixup.  */  struct label_chain *next;  tree label;};voidinit_stmt (){  gcc_obstack_init (&stmt_obstack);#if 0  empty_cleanup_list = build_tree_list (NULL_TREE, NULL_TREE);#endif}voidinit_stmt_for_function (){  /* We are not currently within any block, conditional, loop or case.  */  block_stack = 0;  loop_stack = 0;  case_stack = 0;  cond_stack = 0;  nesting_stack = 0;  nesting_depth = 0;  block_start_count = 0;  /* No gotos have been expanded yet.  */  goto_fixup_chain = 0;  /* We are not processing a ({...}) grouping.  */  expr_stmts_for_value = 0;  last_expr_type = 0;}voidsave_stmt_status (p)     struct function *p;{  p->block_stack = block_stack;  p->stack_block_stack = stack_block_stack;  p->cond_stack = cond_stack;  p->loop_stack = loop_stack;  p->case_stack = case_stack;  p->nesting_stack = nesting_stack;  p->nesting_depth = nesting_depth;  p->block_start_count = block_start_count;  p->last_expr_type = last_expr_type;  p->last_expr_value = last_expr_value;  p->expr_stmts_for_value = expr_stmts_for_value;  p->emit_filename = emit_filename;  p->emit_lineno = emit_lineno;  p->goto_fixup_chain = goto_fixup_chain;}voidrestore_stmt_status (p)     struct function *p;{  block_stack = p->block_stack;  stack_block_stack = p->stack_block_stack;  cond_stack = p->cond_stack;  loop_stack = p->loop_stack;  case_stack = p->case_stack;  nesting_stack = p->nesting_stack;  nesting_depth = p->nesting_depth;  block_start_count = p->block_start_count;  last_expr_type = p->last_expr_type;  last_expr_value = p->last_expr_value;  expr_stmts_for_value = p->expr_stmts_for_value;  emit_filename = p->emit_filename;  emit_lineno = p->emit_lineno;  goto_fixup_chain = p->goto_fixup_chain;}/* Emit a no-op instruction.  */voidemit_nop (){  rtx last_insn = get_last_insn ();  if (!optimize      && (GET_CODE (last_insn) == CODE_LABEL	  || prev_real_insn (last_insn) == 0))    emit_insn (gen_nop ());}/* Return the rtx-label that corresponds to a LABEL_DECL,   creating it if necessary.  */rtxlabel_rtx (label)     tree label;{  if (TREE_CODE (label) != LABEL_DECL)    abort ();  if (DECL_RTL (label))    return DECL_RTL (label);  return DECL_RTL (label) = gen_label_rtx ();}/* Add an unconditional jump to LABEL as the next sequential instruction.  */voidemit_jump (label)     rtx label;{  do_pending_stack_adjust ();  emit_jump_insn (gen_jump (label));  emit_barrier ();}/* Emit code to jump to the address   specified by the pointer expression EXP.  */voidexpand_computed_goto (exp)     tree exp;{  rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);  emit_queue ();  emit_indirect_jump (x);}/* Handle goto statements and the labels that they can go to.  *//* Specify the location in the RTL code of a label LABEL,   which is a LABEL_DECL tree node.   This is used for the kind of label that the user can jump to with a   goto statement, and for alternatives of a switch or case statement.   RTL labels generated for loops and conditionals don't go through here;   they are generated directly at the RTL level, by other functions below.   Note that this has nothing to do with defining label *names*.   Languages vary in how they do that and what that even means.  */voidexpand_label (label)     tree label;{  struct label_chain *p;  do_pending_stack_adjust ();  emit_label (label_rtx (label));  if (DECL_NAME (label))    LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label));  if (stack_block_stack != 0)    {      p = (struct label_chain *) oballoc (sizeof (struct label_chain));      p->next = stack_block_stack->data.block.label_chain;      stack_block_stack->data.block.label_chain = p;      p->label = label;    }}/* Declare that LABEL (a LABEL_DECL) may be used for nonlocal gotos   from nested functions.  */voiddeclare_nonlocal_label (label)     tree label;{  nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);  LABEL_PRESERVE_P (label_rtx (label)) = 1;  if (nonlocal_goto_handler_slot == 0)    {      nonlocal_goto_handler_slot	= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);      emit_stack_save (SAVE_NONLOCAL,		       &nonlocal_goto_stack_level,		       PREV_INSN (tail_recursion_reentry));    }}/* Generate RTL code for a `goto' statement with target label LABEL.   LABEL should be a LABEL_DECL tree node that was or will later be   defined with `expand_label'.  */voidexpand_goto (label)     tree label;{  /* Check for a nonlocal goto to a containing function.  */  tree context = decl_function_context (label);  if (context != 0 && context != current_function_decl)    {      struct function *p = find_function_data (context);      rtx label_ref = gen_rtx (LABEL_REF, Pmode, label_rtx (label));      rtx temp;      p->has_nonlocal_label = 1;      LABEL_REF_NONLOCAL_P (label_ref) = 1;      /* Copy the rtl for the slots so that they won't be shared in	 case the virtual stack vars register gets instantiated differently	 in the parent than in the child.  */#if HAVE_nonlocal_goto      if (HAVE_nonlocal_goto)	emit_insn (gen_nonlocal_goto (lookup_static_chain (label),				      copy_rtx (p->nonlocal_goto_handler_slot),				      copy_rtx (p->nonlocal_goto_stack_level),				      label_ref));      else#endif	{	  rtx addr;	  /* Restore frame pointer for containing function.	     This sets the actual hard register used for the frame pointer	     to the location of the function's incoming static chain info.	     The non-local goto handler will then adjust it to contain the	     proper value and reload the argument pointer, if needed.  */	  emit_move_insn (frame_pointer_rtx, lookup_static_chain (label));	  /* We have now loaded the frame pointer hardware register with	     the address of that corresponds to the start of the virtual	     stack vars.  So replace virtual_stack_vars_rtx in all	     addresses we use with stack_pointer_rtx.  */	  /* Get addr of containing function's current nonlocal goto handler,	     which will do any cleanups and then jump to the label.  */	  addr = copy_rtx (p->nonlocal_goto_handler_slot);	  temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,					   frame_pointer_rtx));	  	  /* Restore the stack pointer.  Note this uses fp just restored.  */	  addr = p->nonlocal_goto_stack_level;	  if (addr)	    addr = replace_rtx (copy_rtx (addr),				virtual_stack_vars_rtx, frame_pointer_rtx);	  emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX);	  /* Put in the static chain register the nonlocal label address.  */	  emit_move_insn (static_chain_rtx, label_ref);	  /* USE of frame_pointer_rtx added for consistency; not clear if	     really needed.  */	  emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));	  emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));	  emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));	  emit_indirect_jump (temp);	}     }  else    expand_goto_internal (label, label_rtx (label), NULL_RTX);}/* Generate RTL code for a `goto' statement with target label BODY.   LABEL should be a LABEL_REF.   LAST_INSN, if non-0, is the rtx we should consider as the last   insn emitted (for the purposes of cleaning up a return).  */static voidexpand_goto_internal (body, label, last_insn)     tree body;     rtx label;     rtx last_insn;{  struct nesting *block;  rtx stack_level = 0;  if (GET_CODE (label) != CODE_LABEL)    abort ();  /* If label has already been defined, we can tell now     whether and how we must alter the stack level.  */  if (PREV_INSN (label) != 0)    {      /* Find the innermost pending block that contains the label.	 (Check containment by comparing insn-uids.)	 Then restore the outermost stack level within that block,	 and do cleanups of all blocks contained in it.  */      for (block = block_stack; block; block = block->next)	{	  if (INSN_UID (block->data.block.first_insn) < INSN_UID (label))	    break;	  if (block->data.block.stack_level != 0)	    stack_level = block->data.block.stack_level;	  /* Execute the cleanups for blocks we are exiting.  */	  if (block->data.block.cleanups != 0)	    {	      expand_cleanups (block->data.block.cleanups, NULL_TREE);	      do_pending_stack_adjust ();	    }	}      if (stack_level)	{	  /* Ensure stack adjust isn't done by emit_jump, as this would clobber	     the stack pointer.  This one should be deleted as dead by flow. */	  clear_pending_stack_adjust ();	  do_pending_stack_adjust ();	  emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);	}      if (body != 0 && DECL_TOO_LATE (body))	error ("jump to `%s' invalidly jumps into binding contour",	       IDENTIFIER_POINTER (DECL_NAME (body)));    }  /* Label not yet defined: may need to put this goto     on the fixup list.  */  else if (! expand_fixup (body, label, last_insn))    {      /* No fixup needed.  Record that the label is the target	 of at least one goto that has no fixup.  */      if (body != 0)	TREE_ADDRESSABLE (body) = 1;    }  emit_jump (label);}/* Generate if necessary a fixup for a goto   whose target label in tree structure (if any) is TREE_LABEL   and whose target in rtl is RTL_LABEL.   If LAST_INSN is nonzero, we pretend that the jump appears   after insn LAST_INSN instead of at the current point in the insn stream.   The fixup will be used later to insert insns just before the goto.   Those insns will restore the stack level as appropriate for the   target label, and will (in the case of C++) also invoke any object   destructors which have to be invoked when we exit the scopes which   are exited by the goto.   Value is nonzero if a fixup is made.  */static intexpand_fixup (tree_label, rtl_label, last_insn)     tree tree_label;     rtx rtl_label;     rtx last_insn;{  struct nesting *block, *end_block;  /* See if we can recognize which block the label will be output in.     This is possible in some very common cases.     If we succeed, set END_BLOCK to that block.     Otherwise, set it to 0.  */  if (cond_stack      && (rtl_label == cond_stack->data.cond.endif_label	  || rtl_label == cond_stack->data.cond.next_label))    end_block = cond_stack;  /* If we are in a loop, recognize certain labels which     are likely targets.  This reduces the number of fixups     we need to create.  */  else if (loop_stack      && (rtl_label == loop_stack->data.loop.start_label	  || rtl_label == loop_stack->data.loop.end_label	  || rtl_label == loop_stack->data.loop.continue_label))    end_block = loop_stack;  else    end_block = 0;  /* Now set END_BLOCK to the binding level to which we will return.  */  if (end_block)    {      struct nesting *next_block = end_block->all;      block = block_stack;      /* First see if the END_BLOCK is inside the innermost binding level.	 If so, then no cleanups or stack levels are relevant.  */      while (next_block && next_block != block)	next_block = next_block->all;      if (next_block)	return 0;      /* Otherwise, set END_BLOCK to the innermost binding level	 which is outside the relevant control-structure nesting.  */      next_block = block_stack->next;      for (block = block_stack; block != end_block; block = block->all)	if (block == next_block)	  next_block = next_block->next;      end_block = next_block;    }  /* Does any containing block have a stack level or cleanups?     If not, no fixup is needed, and that is the normal case     (the only case, for standard C).  */  for (block = block_stack; block != end_block; block = block->next)    if (block->data.block.stack_level != 0	|| block->data.block.cleanups != 0)      break;  if (block != end_block)

⌨️ 快捷键说明

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