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

📄 stmt.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
  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;};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));extern rtx bc_allocate_local ();extern rtx bc_allocate_variable_array ();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;  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;}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;  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 ();      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()     directly. This is rather an exceptional case, and there aren't     that many places where this is necessary. */  if (output_bytecode)    {      expand_goto_internal (body, label, last_insn);      return;    }  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, 1, 1);	      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);

⌨️ 快捷键说明

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