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

📄 stmt.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  int block_start_count;  /* 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,     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;  /* Bytecode specific members follow */  /* The label that this jump is jumping to, or 0 for break, continue     or return.  */  struct bc_label *bc_target;  /* The label we use for the fixup patch */  struct bc_label *label;  /* True (non-0) if fixup has been handled */  int bc_handled:1;  /* Like stack_level above, except refers to the interpreter stack */  int bc_stack_level;};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;};/* Non-zero if we are using EH to handle cleanus.  */static int using_eh_for_cleanups_p = 0;static void expand_goto_internal	PROTO((tree, rtx, rtx));static void bc_expand_goto_internal	PROTO((enum bytecode_opcode,					       struct bc_label *, tree));static int expand_fixup			PROTO((tree, rtx, rtx));static void bc_expand_fixup		PROTO((enum bytecode_opcode,					       struct bc_label *, int));static void fixup_gotos			PROTO((struct nesting *, rtx, tree,					       rtx, int));static void bc_fixup_gotos		PROTO((struct nesting *, int, tree,					       rtx, int));static void bc_expand_start_cond	PROTO((tree, int));static void bc_expand_end_cond		PROTO((void));static void bc_expand_start_else	PROTO((void));static void bc_expand_end_loop		PROTO((void));static void bc_expand_end_bindings	PROTO((tree, int, int));static void bc_expand_decl		PROTO((tree, tree));static void bc_expand_variable_local_init PROTO((tree));static void bc_expand_decl_init		PROTO((tree));static void expand_null_return_1	PROTO((rtx, int));static void expand_value_return		PROTO((rtx));static int tail_recursion_args		PROTO((tree, tree));static void expand_cleanups		PROTO((tree, tree, int, int));static void bc_expand_start_case	PROTO((struct nesting *, tree,					       tree, char *));static int bc_pushcase			PROTO((tree, tree));static void bc_check_for_full_enumeration_handling PROTO((tree));static void bc_expand_end_case		PROTO((tree));static void do_jump_if_equal		PROTO((rtx, rtx, rtx, int));static int estimate_case_costs		PROTO((case_node_ptr));static void group_case_nodes		PROTO((case_node_ptr));static void balance_case_nodes		PROTO((case_node_ptr *,					       case_node_ptr));static int node_has_low_bound		PROTO((case_node_ptr, tree));static int node_has_high_bound		PROTO((case_node_ptr, tree));static int node_is_bounded		PROTO((case_node_ptr, tree));static void emit_jump_if_reachable	PROTO((rtx));static void emit_case_nodes		PROTO((rtx, case_node_ptr, rtx, tree));static int add_case_node		PROTO((tree, tree, tree, tree *));static struct case_node *case_tree2list	PROTO((case_node *, case_node *));extern rtx bc_allocate_local ();extern rtx bc_allocate_variable_array ();voidusing_eh_for_cleanups (){  using_eh_for_cleanups_p = 1;}voidinit_stmt (){  gcc_obstack_init (&stmt_obstack);  init_eh ();}voidinit_stmt_for_function (){  /* We are not currently within any block, conditional, loop or case.  */  block_stack = 0;  stack_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;  init_eh_for_function ();}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;  save_eh_status (p);}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;  restore_eh_status (p);}/* Emit a no-op instruction.  */voidemit_nop (){  rtx last_insn;  if (!output_bytecode)    {      last_insn = get_last_insn ();      if (!optimize	  && (GET_CODE (last_insn) == CODE_LABEL	      || (GET_CODE (last_insn) == NOTE		  && 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;{  if (output_bytecode)    {      bc_expand_expr (exp);      bc_emit_instruction (jumpP);    }  else    {      rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);#ifdef POINTERS_EXTEND_UNSIGNED      x = convert_memory_address (Pmode, x);#endif      emit_queue ();      /* Be sure the function is executable.  */      if (flag_check_memory_usage)	emit_library_call (chkr_check_exec_libfunc, 1,			   VOIDmode, 1, x, ptr_mode);      do_pending_stack_adjust ();      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;  if (output_bytecode)    {      if (! DECL_RTL (label))	DECL_RTL (label) = bc_gen_rtx ((char *) 0, 0, bc_get_bytecode_label ());      if (! bc_emit_bytecode_labeldef (BYTECODE_BC_LABEL (DECL_RTL (label))))	error ("multiply defined label");      return;    }  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;{  tree context;  if (output_bytecode)    {      expand_goto_internal (label, label_rtx (label), NULL_RTX);      return;    }  /* Check for a nonlocal goto to a containing function.  */  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;      current_function_has_nonlocal_goto = 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 (hard_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,					   hard_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,				hard_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 hard_frame_pointer_rtx added for consistency; not clear if	     really needed.  */	  emit_insn (gen_rtx (USE, VOIDmode, hard_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;  /* NOTICE!  If a bytecode instruction other than `jump' is needed,     then the caller has to call bc_expand_goto_internal()

⌨️ 快捷键说明

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