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

📄 stmt.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Expands front end tree to back end RTL for GNU C-Compiler   Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  *//* This file handles the generation of rtl code from tree structure   above the level of expressions, using subroutines in exp*.c and emit-rtl.c.   It also creates the rtl expressions for parameters and auto variables   and has full responsibility for allocating stack slots.   The functions whose names start with `expand_' are called by the   parser to generate RTL instructions for various kinds of constructs.   Some control and binding constructs require calling several such   functions at different times.  For example, a simple if-then   is expanded by calling `expand_start_cond' (with the condition-expression   as argument) before parsing the then-clause and calling `expand_end_cond'   after parsing the then-clause.  */#include "config.h"#include <stdio.h>#include <ctype.h>#include "rtl.h"#include "tree.h"#include "flags.h"#include "except.h"#include "function.h"#include "insn-flags.h"#include "insn-config.h"#include "insn-codes.h"#include "expr.h"#include "hard-reg-set.h"#include "obstack.h"#include "loop.h"#include "recog.h"#include "machmode.h"#include "bytecode.h"#include "bc-typecd.h"#include "bc-opcode.h"#include "bc-optab.h"#include "bc-emit.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freestruct obstack stmt_obstack;/* Filename and line number of last line-number note,   whether we actually emitted it or not.  */char *emit_filename;int emit_lineno;/* Nonzero if within a ({...}) grouping, in which case we must   always compute a value for each expr-stmt in case it is the last one.  */int expr_stmts_for_value;/* Each time we expand an expression-statement,   record the expr's type and its RTL value here.  */static tree last_expr_type;static rtx last_expr_value;/* Each time we expand the end of a binding contour (in `expand_end_bindings')   and we emit a new NOTE_INSN_BLOCK_END note, we save a pointer to it here.   This is used by the `remember_end_note' function to record the endpoint   of each generated block in its associated BLOCK node.  */static rtx last_block_end_note;/* Number of binding contours started so far in this function.  */int block_start_count;/* Nonzero if function being compiled needs to   return the address of where it has put a structure value.  */extern int current_function_returns_pcc_struct;/* Label that will go on parm cleanup code, if any.   Jumping to this label runs cleanup code for parameters, if   such code must be run.  Following this code is the logical return label.  */extern rtx cleanup_label;/* Label that will go on function epilogue.   Jumping to this label serves as a "return" instruction   on machines which require execution of the epilogue on all returns.  */extern rtx return_label;/* Offset to end of allocated area of stack frame.   If stack grows down, this is the address of the last stack slot allocated.   If stack grows up, this is the address for the next slot.  */extern int frame_offset;/* Label to jump back to for tail recursion, or 0 if we have   not yet needed one for this function.  */extern rtx tail_recursion_label;/* Place after which to insert the tail_recursion_label if we need one.  */extern rtx tail_recursion_reentry;/* Location at which to save the argument pointer if it will need to be   referenced.  There are two cases where this is done: if nonlocal gotos   exist, or if vars whose is an offset from the argument pointer will be   needed by inner routines.  */extern rtx arg_pointer_save_area;/* Chain of all RTL_EXPRs that have insns in them.  */extern tree rtl_expr_chain;/* Stack allocation level in which temporaries for TARGET_EXPRs live.  */extern int target_temp_slot_level;extern int temp_slot_level;/* Functions and data structures for expanding case statements.  *//* Case label structure, used to hold info on labels within case   statements.  We handle "range" labels; for a single-value label   as in C, the high and low limits are the same.   An AVL tree of case nodes is initially created, and later transformed   to a list linked via the RIGHT fields in the nodes.  Nodes with   higher case values are later in the list.   Switch statements can be output in one of two forms.  A branch table   is used if there are more than a few labels and the labels are dense   within the range between the smallest and largest case value.  If a   branch table is used, no further manipulations are done with the case   node chain.   The alternative to the use of a branch table is to generate a series   of compare and jump insns.  When that is done, we use the LEFT, RIGHT,   and PARENT fields to hold a binary tree.  Initially the tree is   totally unbalanced, with everything on the right.  We balance the tree   with nodes on the left having lower case values than the parent   and nodes on the right having higher values.  We then output the tree   in order.  */struct case_node{  struct case_node	*left;	/* Left son in binary tree */  struct case_node	*right;	/* Right son in binary tree; also node chain */  struct case_node	*parent; /* Parent of node in binary tree */  tree			low;	/* Lowest index value for this label */  tree			high;	/* Highest index value for this label */  tree			code_label; /* Label to jump to when node matches */  int			balance;};typedef struct case_node case_node;typedef struct case_node *case_node_ptr;/* These are used by estimate_case_costs and balance_case_nodes.  *//* This must be a signed type, and non-ANSI compilers lack signed char.  */static short *cost_table;static int use_cost_table;/* Stack of control and binding constructs we are currently inside.   These constructs begin when you call `expand_start_WHATEVER'   and end when you call `expand_end_WHATEVER'.  This stack records   info about how the construct began that tells the end-function   what to do.  It also may provide information about the construct   to alter the behavior of other constructs within the body.   For example, they may affect the behavior of C `break' and `continue'.   Each construct gets one `struct nesting' object.   All of these objects are chained through the `all' field.   `nesting_stack' points to the first object (innermost construct).   The position of an entry on `nesting_stack' is in its `depth' field.   Each type of construct has its own individual stack.   For example, loops have `loop_stack'.  Each object points to the   next object of the same type through the `next' field.   Some constructs are visible to `break' exit-statements and others   are not.  Which constructs are visible depends on the language.   Therefore, the data structure allows each construct to be visible   or not, according to the args given when the construct is started.   The construct is visible if the `exit_label' field is non-null.   In that case, the value should be a CODE_LABEL rtx.  */struct nesting{  struct nesting *all;  struct nesting *next;  int depth;  rtx exit_label;  union    {      /* For conds (if-then and if-then-else statements).  */      struct	{	  /* Label for the end of the if construct.	     There is none if EXITFLAG was not set	     and no `else' has been seen yet.  */	  rtx endif_label;	  /* Label for the end of this alternative.	     This may be the end of the if or the next else/elseif.  */	  rtx next_label;	} cond;      /* For loops.  */      struct	{	  /* Label at the top of the loop; place to loop back to.  */	  rtx start_label;	  /* Label at the end of the whole construct.  */	  rtx end_label;	  /* Label before a jump that branches to the end of the whole	     construct.  This is where destructors go if any.  */	  rtx alt_end_label;	  /* Label for `continue' statement to jump to;	     this is in front of the stepper of the loop.  */	  rtx continue_label;	} loop;      /* For variable binding contours.  */      struct	{	  /* Sequence number of this binding contour within the function,	     in order of entry.  */	  int block_start_count;	  /* Nonzero => value to restore stack to on exit.  Complemented by	     bc_stack_level (see below) when generating bytecodes.  */	  rtx stack_level;	  /* The NOTE that starts this contour.	     Used by expand_goto to check whether the destination	     is within each contour or not.  */	  rtx first_insn;	  /* Innermost containing binding contour that has a stack level.  */	  struct nesting *innermost_stack_block;	  /* List of cleanups to be run on exit from this contour.	     This is a list of expressions to be evaluated.	     The TREE_PURPOSE of each link is the ..._DECL node	     which the cleanup pertains to.  */	  tree cleanups;	  /* List of cleanup-lists of blocks containing this block,	     as they were at the locus where this block appears.	     There is an element for each containing block,	     ordered innermost containing block first.	     The tail of this list can be 0,	     if all remaining elements would be empty lists.	     The element's TREE_VALUE is the cleanup-list of that block,	     which may be null.  */	  tree outer_cleanups;	  /* Chain of labels defined inside this binding contour.	     For contours that have stack levels or cleanups.  */	  struct label_chain *label_chain;	  /* Number of function calls seen, as of start of this block.  */	  int function_call_count;	  /* Bytecode specific: stack level to restore stack to on exit.  */	  int bc_stack_level;	  /* Nonzero if this is associated with a EH region.  */	  int exception_region;	  /* The saved target_temp_slot_level from our outer block.	     We may reset target_temp_slot_level to be the level of	     this block, if that is done, target_temp_slot_level	     reverts to the saved target_temp_slot_level at the very	     end of the block.  */	  int target_temp_slot_level;	  /* True if we are currently emitting insns in an area of	     output code that is controlled by a conditional	     expression.  This is used by the cleanup handling code to	     generate conditional cleanup actions.  */	  int conditional_code;	  /* A place to move the start of the exception region for any	     of the conditional cleanups, must be at the end or after	     the start of the last unconditional cleanup, and before any	     conditional branch points.  */	  rtx last_unconditional_cleanup;	  /* When in a conditional context, this is the specific	     cleanup list associated with last_unconditional_cleanup,	     where we place the conditionalized cleanups.  */	  tree *cleanup_ptr;	} block;      /* For switch (C) or case (Pascal) statements,	 and also for dummies (see `expand_start_case_dummy').  */      struct	{	  /* The insn after which the case dispatch should finally	     be emitted.  Zero for a dummy.  */	  rtx start;	  /* For bytecodes, the case table is in-lined right in the code.	     A label is needed for skipping over this block. It is only	     used when generating bytecodes.  */	  rtx skip_label;	  /* A list of case labels; it is first built as an AVL tree.	     During expand_end_case, this is converted to a list, and may be	     rearranged into a nearly balanced binary tree.  */	  struct case_node *case_list;	  /* Label to jump to if no case matches.  */	  tree default_label;	  /* The expression to be dispatched on.  */	  tree index_expr;	  /* Type that INDEX_EXPR should be converted to.  */	  tree nominal_type;	  /* Number of range exprs in case statement.  */	  int num_ranges;	  /* Name of this kind of statement, for warnings.  */	  char *printname;	  /* Nonzero if a case label has been seen in this case stmt.  */	  char seenlabel;	} case_stmt;    } data;};/* Chain of all pending binding contours.  */struct nesting *block_stack;/* If any new stacks are added here, add them to POPSTACKS too.  *//* Chain of all pending binding contours that restore stack levels   or have cleanups.  */struct nesting *stack_block_stack;/* Chain of all pending conditional statements.  */struct nesting *cond_stack;/* Chain of all pending loops.  */struct nesting *loop_stack;/* Chain of all pending case or switch statements.  */struct nesting *case_stack;/* Separate chain including all of the above,   chained through the `all' field.  */struct nesting *nesting_stack;/* Number of entries on nesting_stack now.  */int nesting_depth;/* Allocate and return a new `struct nesting'.  */#define ALLOC_NESTING() \ (struct nesting *) obstack_alloc (&stmt_obstack, sizeof (struct nesting))/* Pop the nesting stack element by element until we pop off   the element which is at the top of STACK.   Update all the other stacks, popping off elements from them   as we pop them from nesting_stack.  */#define POPSTACK(STACK)					\do { struct nesting *target = STACK;			\     struct nesting *this;				\     do { this = nesting_stack;				\	  if (loop_stack == this)			\	    loop_stack = loop_stack->next;		\	  if (cond_stack == this)			\	    cond_stack = cond_stack->next;		\	  if (block_stack == this)			\	    block_stack = block_stack->next;		\	  if (stack_block_stack == this)		\	    stack_block_stack = stack_block_stack->next; \	  if (case_stack == this)			\	    case_stack = case_stack->next;		\	  nesting_depth = nesting_stack->depth - 1;	\	  nesting_stack = this->all;			\	  obstack_free (&stmt_obstack, this); }		\     while (this != target); } while (0)/* In some cases it is impossible to generate code for a forward goto   until the label definition is seen.  This happens when it may be necessary   for the goto to reset the stack pointer: we don't yet know how to do that.   So expand_goto puts an entry on this fixup list.   Each time a binding contour that resets the stack is exited,   we check each fixup.   If the target label has now been defined, we can insert the proper code.  */struct goto_fixup{  /* Points to following fixup.  */  struct goto_fixup *next;  /* Points to the insn before the jump insn.     If more code must be inserted, it goes after this insn.  */  rtx before_jump;  /* The LABEL_DECL that this jump is jumping to, or 0     for break, continue or return.  */  tree target;  /* The BLOCK for the place where this goto was found.  */  tree context;  /* The CODE_LABEL rtx that this is jumping to.  */  rtx target_rtl;  /* Number of binding contours started in current function     before the label reference.  */

⌨️ 快捷键说明

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