xref: /openbsd/gnu/usr.bin/gcc/gcc/stmt.c (revision 8c057a53)
1c87b03e5Sespie /* Expands front end tree to back end RTL for GNU C-Compiler
2c87b03e5Sespie    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
3c87b03e5Sespie    1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4c87b03e5Sespie 
5c87b03e5Sespie This file is part of GCC.
6c87b03e5Sespie 
7c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it under
8c87b03e5Sespie the terms of the GNU General Public License as published by the Free
9c87b03e5Sespie Software Foundation; either version 2, or (at your option) any later
10c87b03e5Sespie version.
11c87b03e5Sespie 
12c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13c87b03e5Sespie WARRANTY; without even the implied warranty of MERCHANTABILITY or
14c87b03e5Sespie FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15c87b03e5Sespie for more details.
16c87b03e5Sespie 
17c87b03e5Sespie You should have received a copy of the GNU General Public License
18c87b03e5Sespie along with GCC; see the file COPYING.  If not, write to the Free
19c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20c87b03e5Sespie 02111-1307, USA.  */
21c87b03e5Sespie 
22c87b03e5Sespie /* This file handles the generation of rtl code from tree structure
23c87b03e5Sespie    above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
24c87b03e5Sespie    It also creates the rtl expressions for parameters and auto variables
25c87b03e5Sespie    and has full responsibility for allocating stack slots.
26c87b03e5Sespie 
27c87b03e5Sespie    The functions whose names start with `expand_' are called by the
28c87b03e5Sespie    parser to generate RTL instructions for various kinds of constructs.
29c87b03e5Sespie 
30c87b03e5Sespie    Some control and binding constructs require calling several such
31c87b03e5Sespie    functions at different times.  For example, a simple if-then
32c87b03e5Sespie    is expanded by calling `expand_start_cond' (with the condition-expression
33c87b03e5Sespie    as argument) before parsing the then-clause and calling `expand_end_cond'
34c87b03e5Sespie    after parsing the then-clause.  */
35c87b03e5Sespie 
36c87b03e5Sespie #include "config.h"
37c87b03e5Sespie #include "system.h"
38c87b03e5Sespie 
39c87b03e5Sespie #include "rtl.h"
40c87b03e5Sespie #include "tree.h"
41c87b03e5Sespie #include "tm_p.h"
42c87b03e5Sespie #include "flags.h"
43c87b03e5Sespie #include "except.h"
44c87b03e5Sespie #include "function.h"
45c87b03e5Sespie #include "insn-config.h"
46c87b03e5Sespie #include "expr.h"
47c87b03e5Sespie #include "libfuncs.h"
48c87b03e5Sespie #include "hard-reg-set.h"
49c87b03e5Sespie #include "loop.h"
50c87b03e5Sespie #include "recog.h"
51c87b03e5Sespie #include "machmode.h"
52c87b03e5Sespie #include "toplev.h"
53c87b03e5Sespie #include "output.h"
54c87b03e5Sespie #include "ggc.h"
55c87b03e5Sespie #include "langhooks.h"
56c87b03e5Sespie #include "predict.h"
57c87b03e5Sespie 
58c87b03e5Sespie /* Assume that case vectors are not pc-relative.  */
59c87b03e5Sespie #ifndef CASE_VECTOR_PC_RELATIVE
60c87b03e5Sespie #define CASE_VECTOR_PC_RELATIVE 0
61c87b03e5Sespie #endif
62c87b03e5Sespie 
63c87b03e5Sespie /* Functions and data structures for expanding case statements.  */
64c87b03e5Sespie 
65c87b03e5Sespie /* Case label structure, used to hold info on labels within case
66c87b03e5Sespie    statements.  We handle "range" labels; for a single-value label
67c87b03e5Sespie    as in C, the high and low limits are the same.
68c87b03e5Sespie 
69c87b03e5Sespie    An AVL tree of case nodes is initially created, and later transformed
70c87b03e5Sespie    to a list linked via the RIGHT fields in the nodes.  Nodes with
71c87b03e5Sespie    higher case values are later in the list.
72c87b03e5Sespie 
73c87b03e5Sespie    Switch statements can be output in one of two forms.  A branch table
74c87b03e5Sespie    is used if there are more than a few labels and the labels are dense
75c87b03e5Sespie    within the range between the smallest and largest case value.  If a
76c87b03e5Sespie    branch table is used, no further manipulations are done with the case
77c87b03e5Sespie    node chain.
78c87b03e5Sespie 
79c87b03e5Sespie    The alternative to the use of a branch table is to generate a series
80c87b03e5Sespie    of compare and jump insns.  When that is done, we use the LEFT, RIGHT,
81c87b03e5Sespie    and PARENT fields to hold a binary tree.  Initially the tree is
82c87b03e5Sespie    totally unbalanced, with everything on the right.  We balance the tree
83c87b03e5Sespie    with nodes on the left having lower case values than the parent
84c87b03e5Sespie    and nodes on the right having higher values.  We then output the tree
85c87b03e5Sespie    in order.  */
86c87b03e5Sespie 
87c87b03e5Sespie struct case_node GTY(())
88c87b03e5Sespie {
89c87b03e5Sespie   struct case_node	*left;	/* Left son in binary tree */
90c87b03e5Sespie   struct case_node	*right;	/* Right son in binary tree; also node chain */
91c87b03e5Sespie   struct case_node	*parent; /* Parent of node in binary tree */
92c87b03e5Sespie   tree			low;	/* Lowest index value for this label */
93c87b03e5Sespie   tree			high;	/* Highest index value for this label */
94c87b03e5Sespie   tree			code_label; /* Label to jump to when node matches */
95c87b03e5Sespie   int			balance;
96c87b03e5Sespie };
97c87b03e5Sespie 
98c87b03e5Sespie typedef struct case_node case_node;
99c87b03e5Sespie typedef struct case_node *case_node_ptr;
100c87b03e5Sespie 
101c87b03e5Sespie /* These are used by estimate_case_costs and balance_case_nodes.  */
102c87b03e5Sespie 
103c87b03e5Sespie /* This must be a signed type, and non-ANSI compilers lack signed char.  */
104c87b03e5Sespie static short cost_table_[129];
105c87b03e5Sespie static int use_cost_table;
106c87b03e5Sespie static int cost_table_initialized;
107c87b03e5Sespie 
108c87b03e5Sespie /* Special care is needed because we allow -1, but TREE_INT_CST_LOW
109c87b03e5Sespie    is unsigned.  */
110c87b03e5Sespie #define COST_TABLE(I)  cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
111c87b03e5Sespie 
112c87b03e5Sespie /* Stack of control and binding constructs we are currently inside.
113c87b03e5Sespie 
114c87b03e5Sespie    These constructs begin when you call `expand_start_WHATEVER'
115c87b03e5Sespie    and end when you call `expand_end_WHATEVER'.  This stack records
116c87b03e5Sespie    info about how the construct began that tells the end-function
117c87b03e5Sespie    what to do.  It also may provide information about the construct
118c87b03e5Sespie    to alter the behavior of other constructs within the body.
119c87b03e5Sespie    For example, they may affect the behavior of C `break' and `continue'.
120c87b03e5Sespie 
121c87b03e5Sespie    Each construct gets one `struct nesting' object.
122c87b03e5Sespie    All of these objects are chained through the `all' field.
123c87b03e5Sespie    `nesting_stack' points to the first object (innermost construct).
124c87b03e5Sespie    The position of an entry on `nesting_stack' is in its `depth' field.
125c87b03e5Sespie 
126c87b03e5Sespie    Each type of construct has its own individual stack.
127c87b03e5Sespie    For example, loops have `loop_stack'.  Each object points to the
128c87b03e5Sespie    next object of the same type through the `next' field.
129c87b03e5Sespie 
130c87b03e5Sespie    Some constructs are visible to `break' exit-statements and others
131c87b03e5Sespie    are not.  Which constructs are visible depends on the language.
132c87b03e5Sespie    Therefore, the data structure allows each construct to be visible
133c87b03e5Sespie    or not, according to the args given when the construct is started.
134c87b03e5Sespie    The construct is visible if the `exit_label' field is non-null.
135c87b03e5Sespie    In that case, the value should be a CODE_LABEL rtx.  */
136c87b03e5Sespie 
137c87b03e5Sespie struct nesting GTY(())
138c87b03e5Sespie {
139c87b03e5Sespie   struct nesting *all;
140c87b03e5Sespie   struct nesting *next;
141c87b03e5Sespie   int depth;
142c87b03e5Sespie   rtx exit_label;
143c87b03e5Sespie   enum nesting_desc {
144c87b03e5Sespie     COND_NESTING,
145c87b03e5Sespie     LOOP_NESTING,
146c87b03e5Sespie     BLOCK_NESTING,
147c87b03e5Sespie     CASE_NESTING
148c87b03e5Sespie   } desc;
149c87b03e5Sespie   union nesting_u
150c87b03e5Sespie     {
151c87b03e5Sespie       /* For conds (if-then and if-then-else statements).  */
152c87b03e5Sespie       struct nesting_cond
153c87b03e5Sespie 	{
154c87b03e5Sespie 	  /* Label for the end of the if construct.
155c87b03e5Sespie 	     There is none if EXITFLAG was not set
156c87b03e5Sespie 	     and no `else' has been seen yet.  */
157c87b03e5Sespie 	  rtx endif_label;
158c87b03e5Sespie 	  /* Label for the end of this alternative.
159c87b03e5Sespie 	     This may be the end of the if or the next else/elseif.  */
160c87b03e5Sespie 	  rtx next_label;
161c87b03e5Sespie 	} GTY ((tag ("COND_NESTING"))) cond;
162c87b03e5Sespie       /* For loops.  */
163c87b03e5Sespie       struct nesting_loop
164c87b03e5Sespie 	{
165c87b03e5Sespie 	  /* Label at the top of the loop; place to loop back to.  */
166c87b03e5Sespie 	  rtx start_label;
167c87b03e5Sespie 	  /* Label at the end of the whole construct.  */
168c87b03e5Sespie 	  rtx end_label;
169c87b03e5Sespie 	  /* Label before a jump that branches to the end of the whole
170c87b03e5Sespie 	     construct.  This is where destructors go if any.  */
171c87b03e5Sespie 	  rtx alt_end_label;
172c87b03e5Sespie 	  /* Label for `continue' statement to jump to;
173c87b03e5Sespie 	     this is in front of the stepper of the loop.  */
174c87b03e5Sespie 	  rtx continue_label;
175c87b03e5Sespie 	} GTY ((tag ("LOOP_NESTING"))) loop;
176c87b03e5Sespie       /* For variable binding contours.  */
177c87b03e5Sespie       struct nesting_block
178c87b03e5Sespie 	{
179c87b03e5Sespie 	  /* Sequence number of this binding contour within the function,
180c87b03e5Sespie 	     in order of entry.  */
181c87b03e5Sespie 	  int block_start_count;
182c87b03e5Sespie 	  /* Nonzero => value to restore stack to on exit.  */
183c87b03e5Sespie 	  rtx stack_level;
184c87b03e5Sespie 	  /* The NOTE that starts this contour.
185c87b03e5Sespie 	     Used by expand_goto to check whether the destination
186c87b03e5Sespie 	     is within each contour or not.  */
187c87b03e5Sespie 	  rtx first_insn;
188c87b03e5Sespie 	  /* Innermost containing binding contour that has a stack level.  */
189c87b03e5Sespie 	  struct nesting *innermost_stack_block;
190c87b03e5Sespie 	  /* List of cleanups to be run on exit from this contour.
191c87b03e5Sespie 	     This is a list of expressions to be evaluated.
192c87b03e5Sespie 	     The TREE_PURPOSE of each link is the ..._DECL node
193c87b03e5Sespie 	     which the cleanup pertains to.  */
194c87b03e5Sespie 	  tree cleanups;
195c87b03e5Sespie 	  /* List of cleanup-lists of blocks containing this block,
196c87b03e5Sespie 	     as they were at the locus where this block appears.
197c87b03e5Sespie 	     There is an element for each containing block,
198c87b03e5Sespie 	     ordered innermost containing block first.
199c87b03e5Sespie 	     The tail of this list can be 0,
200c87b03e5Sespie 	     if all remaining elements would be empty lists.
201c87b03e5Sespie 	     The element's TREE_VALUE is the cleanup-list of that block,
202c87b03e5Sespie 	     which may be null.  */
203c87b03e5Sespie 	  tree outer_cleanups;
204c87b03e5Sespie 	  /* Chain of labels defined inside this binding contour.
205c87b03e5Sespie 	     For contours that have stack levels or cleanups.  */
206c87b03e5Sespie 	  struct label_chain *label_chain;
207c87b03e5Sespie 	  /* Number of function calls seen, as of start of this block.  */
208c87b03e5Sespie 	  int n_function_calls;
209c87b03e5Sespie 	  /* Nonzero if this is associated with an EH region.  */
210c87b03e5Sespie 	  int exception_region;
211c87b03e5Sespie 	  /* The saved target_temp_slot_level from our outer block.
212c87b03e5Sespie 	     We may reset target_temp_slot_level to be the level of
213c87b03e5Sespie 	     this block, if that is done, target_temp_slot_level
214c87b03e5Sespie 	     reverts to the saved target_temp_slot_level at the very
215c87b03e5Sespie 	     end of the block.  */
216c87b03e5Sespie 	  int block_target_temp_slot_level;
217c87b03e5Sespie 	  /* True if we are currently emitting insns in an area of
218c87b03e5Sespie 	     output code that is controlled by a conditional
219c87b03e5Sespie 	     expression.  This is used by the cleanup handling code to
220c87b03e5Sespie 	     generate conditional cleanup actions.  */
221c87b03e5Sespie 	  int conditional_code;
222c87b03e5Sespie 	  /* A place to move the start of the exception region for any
223c87b03e5Sespie 	     of the conditional cleanups, must be at the end or after
224c87b03e5Sespie 	     the start of the last unconditional cleanup, and before any
225c87b03e5Sespie 	     conditional branch points.  */
226c87b03e5Sespie 	  rtx last_unconditional_cleanup;
227c87b03e5Sespie 	} GTY ((tag ("BLOCK_NESTING"))) block;
228c87b03e5Sespie       /* For switch (C) or case (Pascal) statements,
229c87b03e5Sespie 	 and also for dummies (see `expand_start_case_dummy').  */
230c87b03e5Sespie       struct nesting_case
231c87b03e5Sespie 	{
232c87b03e5Sespie 	  /* The insn after which the case dispatch should finally
233c87b03e5Sespie 	     be emitted.  Zero for a dummy.  */
234c87b03e5Sespie 	  rtx start;
235c87b03e5Sespie 	  /* A list of case labels; it is first built as an AVL tree.
236c87b03e5Sespie 	     During expand_end_case, this is converted to a list, and may be
237c87b03e5Sespie 	     rearranged into a nearly balanced binary tree.  */
238c87b03e5Sespie 	  struct case_node *case_list;
239c87b03e5Sespie 	  /* Label to jump to if no case matches.  */
240c87b03e5Sespie 	  tree default_label;
241c87b03e5Sespie 	  /* The expression to be dispatched on.  */
242c87b03e5Sespie 	  tree index_expr;
243c87b03e5Sespie 	  /* Type that INDEX_EXPR should be converted to.  */
244c87b03e5Sespie 	  tree nominal_type;
245c87b03e5Sespie 	  /* Name of this kind of statement, for warnings.  */
246c87b03e5Sespie 	  const char *printname;
247c87b03e5Sespie 	  /* Used to save no_line_numbers till we see the first case label.
248c87b03e5Sespie 	     We set this to -1 when we see the first case label in this
249c87b03e5Sespie 	     case statement.  */
250c87b03e5Sespie 	  int line_number_status;
251c87b03e5Sespie 	} GTY ((tag ("CASE_NESTING"))) case_stmt;
252c87b03e5Sespie     } GTY ((desc ("%1.desc"))) data;
253c87b03e5Sespie };
254c87b03e5Sespie 
255c87b03e5Sespie /* Allocate and return a new `struct nesting'.  */
256c87b03e5Sespie 
257c87b03e5Sespie #define ALLOC_NESTING() \
258c87b03e5Sespie  (struct nesting *) ggc_alloc (sizeof (struct nesting))
259c87b03e5Sespie 
260c87b03e5Sespie /* Pop the nesting stack element by element until we pop off
261c87b03e5Sespie    the element which is at the top of STACK.
262c87b03e5Sespie    Update all the other stacks, popping off elements from them
263c87b03e5Sespie    as we pop them from nesting_stack.  */
264c87b03e5Sespie 
265c87b03e5Sespie #define POPSTACK(STACK)					\
266c87b03e5Sespie do { struct nesting *target = STACK;			\
267c87b03e5Sespie      struct nesting *this;				\
268c87b03e5Sespie      do { this = nesting_stack;				\
269c87b03e5Sespie 	  if (loop_stack == this)			\
270c87b03e5Sespie 	    loop_stack = loop_stack->next;		\
271c87b03e5Sespie 	  if (cond_stack == this)			\
272c87b03e5Sespie 	    cond_stack = cond_stack->next;		\
273c87b03e5Sespie 	  if (block_stack == this)			\
274c87b03e5Sespie 	    block_stack = block_stack->next;		\
275c87b03e5Sespie 	  if (stack_block_stack == this)		\
276c87b03e5Sespie 	    stack_block_stack = stack_block_stack->next; \
277c87b03e5Sespie 	  if (case_stack == this)			\
278c87b03e5Sespie 	    case_stack = case_stack->next;		\
279c87b03e5Sespie 	  nesting_depth = nesting_stack->depth - 1;	\
280c87b03e5Sespie 	  nesting_stack = this->all; }			\
281c87b03e5Sespie      while (this != target); } while (0)
282c87b03e5Sespie 
283c87b03e5Sespie /* In some cases it is impossible to generate code for a forward goto
284c87b03e5Sespie    until the label definition is seen.  This happens when it may be necessary
285c87b03e5Sespie    for the goto to reset the stack pointer: we don't yet know how to do that.
286c87b03e5Sespie    So expand_goto puts an entry on this fixup list.
287c87b03e5Sespie    Each time a binding contour that resets the stack is exited,
288c87b03e5Sespie    we check each fixup.
289c87b03e5Sespie    If the target label has now been defined, we can insert the proper code.  */
290c87b03e5Sespie 
291c87b03e5Sespie struct goto_fixup GTY(())
292c87b03e5Sespie {
293c87b03e5Sespie   /* Points to following fixup.  */
294c87b03e5Sespie   struct goto_fixup *next;
295c87b03e5Sespie   /* Points to the insn before the jump insn.
296c87b03e5Sespie      If more code must be inserted, it goes after this insn.  */
297c87b03e5Sespie   rtx before_jump;
298c87b03e5Sespie   /* The LABEL_DECL that this jump is jumping to, or 0
299c87b03e5Sespie      for break, continue or return.  */
300c87b03e5Sespie   tree target;
301c87b03e5Sespie   /* The BLOCK for the place where this goto was found.  */
302c87b03e5Sespie   tree context;
303c87b03e5Sespie   /* The CODE_LABEL rtx that this is jumping to.  */
304c87b03e5Sespie   rtx target_rtl;
305c87b03e5Sespie   /* Number of binding contours started in current function
306c87b03e5Sespie      before the label reference.  */
307c87b03e5Sespie   int block_start_count;
308c87b03e5Sespie   /* The outermost stack level that should be restored for this jump.
309c87b03e5Sespie      Each time a binding contour that resets the stack is exited,
310c87b03e5Sespie      if the target label is *not* yet defined, this slot is updated.  */
311c87b03e5Sespie   rtx stack_level;
312c87b03e5Sespie   /* List of lists of cleanup expressions to be run by this goto.
313c87b03e5Sespie      There is one element for each block that this goto is within.
314c87b03e5Sespie      The tail of this list can be 0,
315c87b03e5Sespie      if all remaining elements would be empty.
316c87b03e5Sespie      The TREE_VALUE contains the cleanup list of that block as of the
317c87b03e5Sespie      time this goto was seen.
318c87b03e5Sespie      The TREE_ADDRESSABLE flag is 1 for a block that has been exited.  */
319c87b03e5Sespie   tree cleanup_list_list;
320c87b03e5Sespie };
321c87b03e5Sespie 
322c87b03e5Sespie /* Within any binding contour that must restore a stack level,
323c87b03e5Sespie    all labels are recorded with a chain of these structures.  */
324c87b03e5Sespie 
325c87b03e5Sespie struct label_chain GTY(())
326c87b03e5Sespie {
327c87b03e5Sespie   /* Points to following fixup.  */
328c87b03e5Sespie   struct label_chain *next;
329c87b03e5Sespie   tree label;
330c87b03e5Sespie };
331c87b03e5Sespie 
332c87b03e5Sespie struct stmt_status GTY(())
333c87b03e5Sespie {
334c87b03e5Sespie   /* Chain of all pending binding contours.  */
335c87b03e5Sespie   struct nesting * x_block_stack;
336c87b03e5Sespie 
337c87b03e5Sespie   /* If any new stacks are added here, add them to POPSTACKS too.  */
338c87b03e5Sespie 
339c87b03e5Sespie   /* Chain of all pending binding contours that restore stack levels
340c87b03e5Sespie      or have cleanups.  */
341c87b03e5Sespie   struct nesting * x_stack_block_stack;
342c87b03e5Sespie 
343c87b03e5Sespie   /* Chain of all pending conditional statements.  */
344c87b03e5Sespie   struct nesting * x_cond_stack;
345c87b03e5Sespie 
346c87b03e5Sespie   /* Chain of all pending loops.  */
347c87b03e5Sespie   struct nesting * x_loop_stack;
348c87b03e5Sespie 
349c87b03e5Sespie   /* Chain of all pending case or switch statements.  */
350c87b03e5Sespie   struct nesting * x_case_stack;
351c87b03e5Sespie 
352c87b03e5Sespie   /* Separate chain including all of the above,
353c87b03e5Sespie      chained through the `all' field.  */
354c87b03e5Sespie   struct nesting * x_nesting_stack;
355c87b03e5Sespie 
356c87b03e5Sespie   /* Number of entries on nesting_stack now.  */
357c87b03e5Sespie   int x_nesting_depth;
358c87b03e5Sespie 
359c87b03e5Sespie   /* Number of binding contours started so far in this function.  */
360c87b03e5Sespie   int x_block_start_count;
361c87b03e5Sespie 
362c87b03e5Sespie   /* Each time we expand an expression-statement,
363c87b03e5Sespie      record the expr's type and its RTL value here.  */
364c87b03e5Sespie   tree x_last_expr_type;
365c87b03e5Sespie   rtx x_last_expr_value;
366c87b03e5Sespie 
367c87b03e5Sespie   /* Nonzero if within a ({...}) grouping, in which case we must
368c87b03e5Sespie      always compute a value for each expr-stmt in case it is the last one.  */
369c87b03e5Sespie   int x_expr_stmts_for_value;
370c87b03e5Sespie 
371c87b03e5Sespie   /* Filename and line number of last line-number note,
372c87b03e5Sespie      whether we actually emitted it or not.  */
373c87b03e5Sespie   const char *x_emit_filename;
374c87b03e5Sespie   int x_emit_lineno;
375c87b03e5Sespie 
376c87b03e5Sespie   struct goto_fixup *x_goto_fixup_chain;
377c87b03e5Sespie };
378c87b03e5Sespie 
379c87b03e5Sespie #define block_stack (cfun->stmt->x_block_stack)
380c87b03e5Sespie #define stack_block_stack (cfun->stmt->x_stack_block_stack)
381c87b03e5Sespie #define cond_stack (cfun->stmt->x_cond_stack)
382c87b03e5Sespie #define loop_stack (cfun->stmt->x_loop_stack)
383c87b03e5Sespie #define case_stack (cfun->stmt->x_case_stack)
384c87b03e5Sespie #define nesting_stack (cfun->stmt->x_nesting_stack)
385c87b03e5Sespie #define nesting_depth (cfun->stmt->x_nesting_depth)
386c87b03e5Sespie #define current_block_start_count (cfun->stmt->x_block_start_count)
387c87b03e5Sespie #define last_expr_type (cfun->stmt->x_last_expr_type)
388c87b03e5Sespie #define last_expr_value (cfun->stmt->x_last_expr_value)
389c87b03e5Sespie #define expr_stmts_for_value (cfun->stmt->x_expr_stmts_for_value)
390c87b03e5Sespie #define emit_filename (cfun->stmt->x_emit_filename)
391c87b03e5Sespie #define emit_lineno (cfun->stmt->x_emit_lineno)
392c87b03e5Sespie #define goto_fixup_chain (cfun->stmt->x_goto_fixup_chain)
393c87b03e5Sespie 
394c87b03e5Sespie /* Non-zero if we are using EH to handle cleanups.  */
395c87b03e5Sespie static int using_eh_for_cleanups_p = 0;
396c87b03e5Sespie 
397c87b03e5Sespie static int n_occurrences		PARAMS ((int, const char *));
398c87b03e5Sespie static bool parse_input_constraint	PARAMS ((const char **, int, int, int,
399c87b03e5Sespie 						 int, const char * const *,
400c87b03e5Sespie 						 bool *, bool *));
401c87b03e5Sespie static bool decl_conflicts_with_clobbers_p PARAMS ((tree, const HARD_REG_SET));
402c87b03e5Sespie static void expand_goto_internal	PARAMS ((tree, rtx, rtx));
403c87b03e5Sespie static int expand_fixup			PARAMS ((tree, rtx, rtx));
404c87b03e5Sespie static rtx expand_nl_handler_label	PARAMS ((rtx, rtx));
405c87b03e5Sespie static void expand_nl_goto_receiver	PARAMS ((void));
406c87b03e5Sespie static void expand_nl_goto_receivers	PARAMS ((struct nesting *));
407c87b03e5Sespie static void fixup_gotos			PARAMS ((struct nesting *, rtx, tree,
408c87b03e5Sespie 					       rtx, int));
409c87b03e5Sespie static bool check_operand_nalternatives	PARAMS ((tree, tree));
410c87b03e5Sespie static bool check_unique_operand_names	PARAMS ((tree, tree));
411c87b03e5Sespie static tree resolve_operand_names	PARAMS ((tree, tree, tree,
412c87b03e5Sespie 						 const char **));
413c87b03e5Sespie static char *resolve_operand_name_1	PARAMS ((char *, tree, tree));
414c87b03e5Sespie static void expand_null_return_1	PARAMS ((rtx));
415c87b03e5Sespie static enum br_predictor return_prediction PARAMS ((rtx));
416c87b03e5Sespie static void expand_value_return		PARAMS ((rtx));
417c87b03e5Sespie static int tail_recursion_args		PARAMS ((tree, tree));
418c87b03e5Sespie static void expand_cleanups		PARAMS ((tree, tree, int, int));
419c87b03e5Sespie static void check_seenlabel		PARAMS ((void));
420c87b03e5Sespie static void do_jump_if_equal		PARAMS ((rtx, rtx, rtx, int));
421c87b03e5Sespie static int estimate_case_costs		PARAMS ((case_node_ptr));
422c87b03e5Sespie static void group_case_nodes		PARAMS ((case_node_ptr));
423c87b03e5Sespie static void balance_case_nodes		PARAMS ((case_node_ptr *,
424c87b03e5Sespie 					       case_node_ptr));
425c87b03e5Sespie static int node_has_low_bound		PARAMS ((case_node_ptr, tree));
426c87b03e5Sespie static int node_has_high_bound		PARAMS ((case_node_ptr, tree));
427c87b03e5Sespie static int node_is_bounded		PARAMS ((case_node_ptr, tree));
428c87b03e5Sespie static void emit_jump_if_reachable	PARAMS ((rtx));
429c87b03e5Sespie static void emit_case_nodes		PARAMS ((rtx, case_node_ptr, rtx, tree));
430c87b03e5Sespie static struct case_node *case_tree2list	PARAMS ((case_node *, case_node *));
431c87b03e5Sespie 
432c87b03e5Sespie void
using_eh_for_cleanups()433c87b03e5Sespie using_eh_for_cleanups ()
434c87b03e5Sespie {
435c87b03e5Sespie   using_eh_for_cleanups_p = 1;
436c87b03e5Sespie }
437c87b03e5Sespie 
438c87b03e5Sespie void
init_stmt_for_function()439c87b03e5Sespie init_stmt_for_function ()
440c87b03e5Sespie {
441c87b03e5Sespie   cfun->stmt = ((struct stmt_status *)ggc_alloc (sizeof (struct stmt_status)));
442c87b03e5Sespie 
443c87b03e5Sespie   /* We are not currently within any block, conditional, loop or case.  */
444c87b03e5Sespie   block_stack = 0;
445c87b03e5Sespie   stack_block_stack = 0;
446c87b03e5Sespie   loop_stack = 0;
447c87b03e5Sespie   case_stack = 0;
448c87b03e5Sespie   cond_stack = 0;
449c87b03e5Sespie   nesting_stack = 0;
450c87b03e5Sespie   nesting_depth = 0;
451c87b03e5Sespie 
452c87b03e5Sespie   current_block_start_count = 0;
453c87b03e5Sespie 
454c87b03e5Sespie   /* No gotos have been expanded yet.  */
455c87b03e5Sespie   goto_fixup_chain = 0;
456c87b03e5Sespie 
457c87b03e5Sespie   /* We are not processing a ({...}) grouping.  */
458c87b03e5Sespie   expr_stmts_for_value = 0;
459c87b03e5Sespie   clear_last_expr ();
460c87b03e5Sespie }
461c87b03e5Sespie 
462c87b03e5Sespie /* Return nonzero if anything is pushed on the loop, condition, or case
463c87b03e5Sespie    stack.  */
464c87b03e5Sespie int
in_control_zone_p()465c87b03e5Sespie in_control_zone_p ()
466c87b03e5Sespie {
467c87b03e5Sespie   return cond_stack || loop_stack || case_stack;
468c87b03e5Sespie }
469c87b03e5Sespie 
470c87b03e5Sespie /* Record the current file and line.  Called from emit_line_note.  */
471c87b03e5Sespie void
set_file_and_line_for_stmt(file,line)472c87b03e5Sespie set_file_and_line_for_stmt (file, line)
473c87b03e5Sespie      const char *file;
474c87b03e5Sespie      int line;
475c87b03e5Sespie {
476c87b03e5Sespie   /* If we're outputting an inline function, and we add a line note,
477c87b03e5Sespie      there may be no CFUN->STMT information.  So, there's no need to
478c87b03e5Sespie      update it.  */
479c87b03e5Sespie   if (cfun->stmt)
480c87b03e5Sespie     {
481c87b03e5Sespie       emit_filename = file;
482c87b03e5Sespie       emit_lineno = line;
483c87b03e5Sespie     }
484c87b03e5Sespie }
485c87b03e5Sespie 
486c87b03e5Sespie /* Emit a no-op instruction.  */
487c87b03e5Sespie 
488c87b03e5Sespie void
emit_nop()489c87b03e5Sespie emit_nop ()
490c87b03e5Sespie {
491c87b03e5Sespie   rtx last_insn;
492c87b03e5Sespie 
493c87b03e5Sespie   last_insn = get_last_insn ();
494c87b03e5Sespie   if (!optimize
495c87b03e5Sespie       && (GET_CODE (last_insn) == CODE_LABEL
496c87b03e5Sespie 	  || (GET_CODE (last_insn) == NOTE
497c87b03e5Sespie 	      && prev_real_insn (last_insn) == 0)))
498c87b03e5Sespie     emit_insn (gen_nop ());
499c87b03e5Sespie }
500c87b03e5Sespie 
501c87b03e5Sespie /* Return the rtx-label that corresponds to a LABEL_DECL,
502c87b03e5Sespie    creating it if necessary.  */
503c87b03e5Sespie 
504c87b03e5Sespie rtx
label_rtx(label)505c87b03e5Sespie label_rtx (label)
506c87b03e5Sespie      tree label;
507c87b03e5Sespie {
508c87b03e5Sespie   if (TREE_CODE (label) != LABEL_DECL)
509c87b03e5Sespie     abort ();
510c87b03e5Sespie 
511c87b03e5Sespie   if (!DECL_RTL_SET_P (label))
512c87b03e5Sespie     SET_DECL_RTL (label, gen_label_rtx ());
513c87b03e5Sespie 
514c87b03e5Sespie   return DECL_RTL (label);
515c87b03e5Sespie }
516c87b03e5Sespie 
517c87b03e5Sespie 
518c87b03e5Sespie /* Add an unconditional jump to LABEL as the next sequential instruction.  */
519c87b03e5Sespie 
520c87b03e5Sespie void
emit_jump(label)521c87b03e5Sespie emit_jump (label)
522c87b03e5Sespie      rtx label;
523c87b03e5Sespie {
524c87b03e5Sespie   do_pending_stack_adjust ();
525c87b03e5Sespie   emit_jump_insn (gen_jump (label));
526c87b03e5Sespie   emit_barrier ();
527c87b03e5Sespie }
528c87b03e5Sespie 
529c87b03e5Sespie /* Emit code to jump to the address
530c87b03e5Sespie    specified by the pointer expression EXP.  */
531c87b03e5Sespie 
532c87b03e5Sespie void
expand_computed_goto(exp)533c87b03e5Sespie expand_computed_goto (exp)
534c87b03e5Sespie      tree exp;
535c87b03e5Sespie {
536c87b03e5Sespie   rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
537c87b03e5Sespie 
538c87b03e5Sespie #ifdef POINTERS_EXTEND_UNSIGNED
539c87b03e5Sespie   if (GET_MODE (x) != Pmode)
540c87b03e5Sespie     x = convert_memory_address (Pmode, x);
541c87b03e5Sespie #endif
542c87b03e5Sespie 
543c87b03e5Sespie   emit_queue ();
544c87b03e5Sespie 
545c87b03e5Sespie   if (! cfun->computed_goto_common_label)
546c87b03e5Sespie     {
547c87b03e5Sespie       cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
548c87b03e5Sespie       cfun->computed_goto_common_label = gen_label_rtx ();
549c87b03e5Sespie 
550c87b03e5Sespie       do_pending_stack_adjust ();
5514e43c760Sespie       emit_label (cfun->computed_goto_common_label);
552c87b03e5Sespie       emit_indirect_jump (cfun->computed_goto_common_reg);
553c87b03e5Sespie 
554c87b03e5Sespie       current_function_has_computed_jump = 1;
555c87b03e5Sespie     }
556c87b03e5Sespie   else
557c87b03e5Sespie     {
558c87b03e5Sespie       emit_move_insn (cfun->computed_goto_common_reg, x);
559c87b03e5Sespie       emit_jump (cfun->computed_goto_common_label);
560c87b03e5Sespie     }
561c87b03e5Sespie }
562c87b03e5Sespie 
563c87b03e5Sespie /* Handle goto statements and the labels that they can go to.  */
564c87b03e5Sespie 
565c87b03e5Sespie /* Specify the location in the RTL code of a label LABEL,
566c87b03e5Sespie    which is a LABEL_DECL tree node.
567c87b03e5Sespie 
568c87b03e5Sespie    This is used for the kind of label that the user can jump to with a
569c87b03e5Sespie    goto statement, and for alternatives of a switch or case statement.
570c87b03e5Sespie    RTL labels generated for loops and conditionals don't go through here;
571c87b03e5Sespie    they are generated directly at the RTL level, by other functions below.
572c87b03e5Sespie 
573c87b03e5Sespie    Note that this has nothing to do with defining label *names*.
574c87b03e5Sespie    Languages vary in how they do that and what that even means.  */
575c87b03e5Sespie 
576c87b03e5Sespie void
expand_label(label)577c87b03e5Sespie expand_label (label)
578c87b03e5Sespie      tree label;
579c87b03e5Sespie {
580c87b03e5Sespie   struct label_chain *p;
581c87b03e5Sespie 
582c87b03e5Sespie   do_pending_stack_adjust ();
583c87b03e5Sespie   emit_label (label_rtx (label));
584c87b03e5Sespie   if (DECL_NAME (label))
585c87b03e5Sespie     LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label));
586c87b03e5Sespie 
587c87b03e5Sespie   if (stack_block_stack != 0)
588c87b03e5Sespie     {
589c87b03e5Sespie       p = (struct label_chain *) ggc_alloc (sizeof (struct label_chain));
590c87b03e5Sespie       p->next = stack_block_stack->data.block.label_chain;
591c87b03e5Sespie       stack_block_stack->data.block.label_chain = p;
592c87b03e5Sespie       p->label = label;
593c87b03e5Sespie     }
594c87b03e5Sespie }
595c87b03e5Sespie 
596c87b03e5Sespie /* Declare that LABEL (a LABEL_DECL) may be used for nonlocal gotos
597c87b03e5Sespie    from nested functions.  */
598c87b03e5Sespie 
599c87b03e5Sespie void
declare_nonlocal_label(label)600c87b03e5Sespie declare_nonlocal_label (label)
601c87b03e5Sespie      tree label;
602c87b03e5Sespie {
603c87b03e5Sespie   rtx slot = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
604c87b03e5Sespie 
605c87b03e5Sespie   nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);
606c87b03e5Sespie   LABEL_PRESERVE_P (label_rtx (label)) = 1;
607c87b03e5Sespie   if (nonlocal_goto_handler_slots == 0)
608c87b03e5Sespie     {
609c87b03e5Sespie       emit_stack_save (SAVE_NONLOCAL,
610c87b03e5Sespie 		       &nonlocal_goto_stack_level,
611c87b03e5Sespie 		       PREV_INSN (tail_recursion_reentry));
612c87b03e5Sespie     }
613c87b03e5Sespie   nonlocal_goto_handler_slots
614c87b03e5Sespie     = gen_rtx_EXPR_LIST (VOIDmode, slot, nonlocal_goto_handler_slots);
615c87b03e5Sespie }
616c87b03e5Sespie 
617c87b03e5Sespie /* Generate RTL code for a `goto' statement with target label LABEL.
618c87b03e5Sespie    LABEL should be a LABEL_DECL tree node that was or will later be
619c87b03e5Sespie    defined with `expand_label'.  */
620c87b03e5Sespie 
621c87b03e5Sespie void
expand_goto(label)622c87b03e5Sespie expand_goto (label)
623c87b03e5Sespie      tree label;
624c87b03e5Sespie {
625c87b03e5Sespie   tree context;
626c87b03e5Sespie 
627c87b03e5Sespie   /* Check for a nonlocal goto to a containing function.  */
628c87b03e5Sespie   context = decl_function_context (label);
629c87b03e5Sespie   if (context != 0 && context != current_function_decl)
630c87b03e5Sespie     {
631c87b03e5Sespie       struct function *p = find_function_data (context);
632c87b03e5Sespie       rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
633c87b03e5Sespie       rtx handler_slot, static_chain, save_area, insn;
634c87b03e5Sespie       tree link;
635c87b03e5Sespie 
636c87b03e5Sespie       /* Find the corresponding handler slot for this label.  */
637c87b03e5Sespie       handler_slot = p->x_nonlocal_goto_handler_slots;
638c87b03e5Sespie       for (link = p->x_nonlocal_labels; TREE_VALUE (link) != label;
639c87b03e5Sespie 	   link = TREE_CHAIN (link))
640c87b03e5Sespie 	handler_slot = XEXP (handler_slot, 1);
641c87b03e5Sespie       handler_slot = XEXP (handler_slot, 0);
642c87b03e5Sespie 
643c87b03e5Sespie       p->has_nonlocal_label = 1;
644c87b03e5Sespie       current_function_has_nonlocal_goto = 1;
645c87b03e5Sespie       LABEL_REF_NONLOCAL_P (label_ref) = 1;
646c87b03e5Sespie 
647c87b03e5Sespie       /* Copy the rtl for the slots so that they won't be shared in
648c87b03e5Sespie 	 case the virtual stack vars register gets instantiated differently
649c87b03e5Sespie 	 in the parent than in the child.  */
650c87b03e5Sespie 
651c87b03e5Sespie       static_chain = copy_to_reg (lookup_static_chain (label));
652c87b03e5Sespie 
653c87b03e5Sespie       /* Get addr of containing function's current nonlocal goto handler,
654c87b03e5Sespie 	 which will do any cleanups and then jump to the label.  */
655c87b03e5Sespie       handler_slot = copy_to_reg (replace_rtx (copy_rtx (handler_slot),
656c87b03e5Sespie 					       virtual_stack_vars_rtx,
657c87b03e5Sespie 					       static_chain));
658c87b03e5Sespie 
659c87b03e5Sespie       /* Get addr of containing function's nonlocal save area.  */
660c87b03e5Sespie       save_area = p->x_nonlocal_goto_stack_level;
661c87b03e5Sespie       if (save_area)
662c87b03e5Sespie 	save_area = replace_rtx (copy_rtx (save_area),
663c87b03e5Sespie 				 virtual_stack_vars_rtx, static_chain);
664c87b03e5Sespie 
665c87b03e5Sespie #if HAVE_nonlocal_goto
666c87b03e5Sespie       if (HAVE_nonlocal_goto)
667c87b03e5Sespie 	emit_insn (gen_nonlocal_goto (static_chain, handler_slot,
668c87b03e5Sespie 				      save_area, label_ref));
669c87b03e5Sespie       else
670c87b03e5Sespie #endif
671c87b03e5Sespie 	{
672c87b03e5Sespie 	  /* Restore frame pointer for containing function.
673c87b03e5Sespie 	     This sets the actual hard register used for the frame pointer
674c87b03e5Sespie 	     to the location of the function's incoming static chain info.
675c87b03e5Sespie 	     The non-local goto handler will then adjust it to contain the
676c87b03e5Sespie 	     proper value and reload the argument pointer, if needed.  */
677c87b03e5Sespie 	  emit_move_insn (hard_frame_pointer_rtx, static_chain);
678c87b03e5Sespie 	  emit_stack_restore (SAVE_NONLOCAL, save_area, NULL_RTX);
679c87b03e5Sespie 
680c87b03e5Sespie 	  /* USE of hard_frame_pointer_rtx added for consistency;
681c87b03e5Sespie 	     not clear if really needed.  */
682c87b03e5Sespie 	  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
683c87b03e5Sespie 	  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
684c87b03e5Sespie 	  emit_indirect_jump (handler_slot);
685c87b03e5Sespie 	}
686c87b03e5Sespie 
687c87b03e5Sespie       /* Search backwards to the jump insn and mark it as a
688c87b03e5Sespie 	 non-local goto.  */
689c87b03e5Sespie       for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
690c87b03e5Sespie 	{
691c87b03e5Sespie 	  if (GET_CODE (insn) == JUMP_INSN)
692c87b03e5Sespie 	    {
693c87b03e5Sespie 	      REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
694c87b03e5Sespie 						  const0_rtx, REG_NOTES (insn));
695c87b03e5Sespie 	      break;
696c87b03e5Sespie 	    }
697c87b03e5Sespie 	  else if (GET_CODE (insn) == CALL_INSN)
698c87b03e5Sespie 	      break;
699c87b03e5Sespie 	}
700c87b03e5Sespie     }
701c87b03e5Sespie   else
702c87b03e5Sespie     expand_goto_internal (label, label_rtx (label), NULL_RTX);
703c87b03e5Sespie }
704c87b03e5Sespie 
705c87b03e5Sespie /* Generate RTL code for a `goto' statement with target label BODY.
706c87b03e5Sespie    LABEL should be a LABEL_REF.
707c87b03e5Sespie    LAST_INSN, if non-0, is the rtx we should consider as the last
708c87b03e5Sespie    insn emitted (for the purposes of cleaning up a return).  */
709c87b03e5Sespie 
710c87b03e5Sespie static void
expand_goto_internal(body,label,last_insn)711c87b03e5Sespie expand_goto_internal (body, label, last_insn)
712c87b03e5Sespie      tree body;
713c87b03e5Sespie      rtx label;
714c87b03e5Sespie      rtx last_insn;
715c87b03e5Sespie {
716c87b03e5Sespie   struct nesting *block;
717c87b03e5Sespie   rtx stack_level = 0;
718c87b03e5Sespie 
719c87b03e5Sespie   if (GET_CODE (label) != CODE_LABEL)
720c87b03e5Sespie     abort ();
721c87b03e5Sespie 
722c87b03e5Sespie   /* If label has already been defined, we can tell now
723c87b03e5Sespie      whether and how we must alter the stack level.  */
724c87b03e5Sespie 
725c87b03e5Sespie   if (PREV_INSN (label) != 0)
726c87b03e5Sespie     {
727c87b03e5Sespie       /* Find the innermost pending block that contains the label.
728c87b03e5Sespie 	 (Check containment by comparing insn-uids.)
729c87b03e5Sespie 	 Then restore the outermost stack level within that block,
730c87b03e5Sespie 	 and do cleanups of all blocks contained in it.  */
731c87b03e5Sespie       for (block = block_stack; block; block = block->next)
732c87b03e5Sespie 	{
733c87b03e5Sespie 	  if (INSN_UID (block->data.block.first_insn) < INSN_UID (label))
734c87b03e5Sespie 	    break;
735c87b03e5Sespie 	  if (block->data.block.stack_level != 0)
736c87b03e5Sespie 	    stack_level = block->data.block.stack_level;
737c87b03e5Sespie 	  /* Execute the cleanups for blocks we are exiting.  */
738c87b03e5Sespie 	  if (block->data.block.cleanups != 0)
739c87b03e5Sespie 	    {
740c87b03e5Sespie 	      expand_cleanups (block->data.block.cleanups, NULL_TREE, 1, 1);
741c87b03e5Sespie 	      do_pending_stack_adjust ();
742c87b03e5Sespie 	    }
743c87b03e5Sespie 	}
744c87b03e5Sespie 
745c87b03e5Sespie       if (stack_level)
746c87b03e5Sespie 	{
747c87b03e5Sespie 	  /* Ensure stack adjust isn't done by emit_jump, as this
748c87b03e5Sespie 	     would clobber the stack pointer.  This one should be
749c87b03e5Sespie 	     deleted as dead by flow.  */
750c87b03e5Sespie 	  clear_pending_stack_adjust ();
751c87b03e5Sespie 	  do_pending_stack_adjust ();
752c87b03e5Sespie 
753c87b03e5Sespie 	  /* Don't do this adjust if it's to the end label and this function
754c87b03e5Sespie 	     is to return with a depressed stack pointer.  */
755c87b03e5Sespie 	  if (label == return_label
756c87b03e5Sespie 	      && (((TREE_CODE (TREE_TYPE (current_function_decl))
757c87b03e5Sespie 		   == FUNCTION_TYPE)
758c87b03e5Sespie 		   && (TYPE_RETURNS_STACK_DEPRESSED
759c87b03e5Sespie 		       (TREE_TYPE (current_function_decl))))))
760c87b03e5Sespie 	    ;
761c87b03e5Sespie 	  else
762c87b03e5Sespie 	    emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
763c87b03e5Sespie 	}
764c87b03e5Sespie 
765c87b03e5Sespie       if (body != 0 && DECL_TOO_LATE (body))
766c87b03e5Sespie 	error ("jump to `%s' invalidly jumps into binding contour",
767c87b03e5Sespie 	       IDENTIFIER_POINTER (DECL_NAME (body)));
768c87b03e5Sespie     }
769c87b03e5Sespie   /* Label not yet defined: may need to put this goto
770c87b03e5Sespie      on the fixup list.  */
771c87b03e5Sespie   else if (! expand_fixup (body, label, last_insn))
772c87b03e5Sespie     {
773c87b03e5Sespie       /* No fixup needed.  Record that the label is the target
774c87b03e5Sespie 	 of at least one goto that has no fixup.  */
775c87b03e5Sespie       if (body != 0)
776c87b03e5Sespie 	TREE_ADDRESSABLE (body) = 1;
777c87b03e5Sespie     }
778c87b03e5Sespie 
779c87b03e5Sespie   emit_jump (label);
780c87b03e5Sespie }
781c87b03e5Sespie 
782c87b03e5Sespie /* Generate if necessary a fixup for a goto
783c87b03e5Sespie    whose target label in tree structure (if any) is TREE_LABEL
784c87b03e5Sespie    and whose target in rtl is RTL_LABEL.
785c87b03e5Sespie 
786c87b03e5Sespie    If LAST_INSN is nonzero, we pretend that the jump appears
787c87b03e5Sespie    after insn LAST_INSN instead of at the current point in the insn stream.
788c87b03e5Sespie 
789c87b03e5Sespie    The fixup will be used later to insert insns just before the goto.
790c87b03e5Sespie    Those insns will restore the stack level as appropriate for the
791c87b03e5Sespie    target label, and will (in the case of C++) also invoke any object
792c87b03e5Sespie    destructors which have to be invoked when we exit the scopes which
793c87b03e5Sespie    are exited by the goto.
794c87b03e5Sespie 
795c87b03e5Sespie    Value is nonzero if a fixup is made.  */
796c87b03e5Sespie 
797c87b03e5Sespie static int
expand_fixup(tree_label,rtl_label,last_insn)798c87b03e5Sespie expand_fixup (tree_label, rtl_label, last_insn)
799c87b03e5Sespie      tree tree_label;
800c87b03e5Sespie      rtx rtl_label;
801c87b03e5Sespie      rtx last_insn;
802c87b03e5Sespie {
803c87b03e5Sespie   struct nesting *block, *end_block;
804c87b03e5Sespie 
805c87b03e5Sespie   /* See if we can recognize which block the label will be output in.
806c87b03e5Sespie      This is possible in some very common cases.
807c87b03e5Sespie      If we succeed, set END_BLOCK to that block.
808c87b03e5Sespie      Otherwise, set it to 0.  */
809c87b03e5Sespie 
810c87b03e5Sespie   if (cond_stack
811c87b03e5Sespie       && (rtl_label == cond_stack->data.cond.endif_label
812c87b03e5Sespie 	  || rtl_label == cond_stack->data.cond.next_label))
813c87b03e5Sespie     end_block = cond_stack;
814c87b03e5Sespie   /* If we are in a loop, recognize certain labels which
815c87b03e5Sespie      are likely targets.  This reduces the number of fixups
816c87b03e5Sespie      we need to create.  */
817c87b03e5Sespie   else if (loop_stack
818c87b03e5Sespie       && (rtl_label == loop_stack->data.loop.start_label
819c87b03e5Sespie 	  || rtl_label == loop_stack->data.loop.end_label
820c87b03e5Sespie 	  || rtl_label == loop_stack->data.loop.continue_label))
821c87b03e5Sespie     end_block = loop_stack;
822c87b03e5Sespie   else
823c87b03e5Sespie     end_block = 0;
824c87b03e5Sespie 
825c87b03e5Sespie   /* Now set END_BLOCK to the binding level to which we will return.  */
826c87b03e5Sespie 
827c87b03e5Sespie   if (end_block)
828c87b03e5Sespie     {
829c87b03e5Sespie       struct nesting *next_block = end_block->all;
830c87b03e5Sespie       block = block_stack;
831c87b03e5Sespie 
832c87b03e5Sespie       /* First see if the END_BLOCK is inside the innermost binding level.
833c87b03e5Sespie 	 If so, then no cleanups or stack levels are relevant.  */
834c87b03e5Sespie       while (next_block && next_block != block)
835c87b03e5Sespie 	next_block = next_block->all;
836c87b03e5Sespie 
837c87b03e5Sespie       if (next_block)
838c87b03e5Sespie 	return 0;
839c87b03e5Sespie 
840c87b03e5Sespie       /* Otherwise, set END_BLOCK to the innermost binding level
841c87b03e5Sespie 	 which is outside the relevant control-structure nesting.  */
842c87b03e5Sespie       next_block = block_stack->next;
843c87b03e5Sespie       for (block = block_stack; block != end_block; block = block->all)
844c87b03e5Sespie 	if (block == next_block)
845c87b03e5Sespie 	  next_block = next_block->next;
846c87b03e5Sespie       end_block = next_block;
847c87b03e5Sespie     }
848c87b03e5Sespie 
849c87b03e5Sespie   /* Does any containing block have a stack level or cleanups?
850c87b03e5Sespie      If not, no fixup is needed, and that is the normal case
851c87b03e5Sespie      (the only case, for standard C).  */
852c87b03e5Sespie   for (block = block_stack; block != end_block; block = block->next)
853c87b03e5Sespie     if (block->data.block.stack_level != 0
854c87b03e5Sespie 	|| block->data.block.cleanups != 0)
855c87b03e5Sespie       break;
856c87b03e5Sespie 
857c87b03e5Sespie   if (block != end_block)
858c87b03e5Sespie     {
859c87b03e5Sespie       /* Ok, a fixup is needed.  Add a fixup to the list of such.  */
860c87b03e5Sespie       struct goto_fixup *fixup
861c87b03e5Sespie 	= (struct goto_fixup *) ggc_alloc (sizeof (struct goto_fixup));
862c87b03e5Sespie       /* In case an old stack level is restored, make sure that comes
863c87b03e5Sespie 	 after any pending stack adjust.  */
864c87b03e5Sespie       /* ?? If the fixup isn't to come at the present position,
865c87b03e5Sespie 	 doing the stack adjust here isn't useful.  Doing it with our
866c87b03e5Sespie 	 settings at that location isn't useful either.  Let's hope
867c87b03e5Sespie 	 someone does it!  */
868c87b03e5Sespie       if (last_insn == 0)
869c87b03e5Sespie 	do_pending_stack_adjust ();
870c87b03e5Sespie       fixup->target = tree_label;
871c87b03e5Sespie       fixup->target_rtl = rtl_label;
872c87b03e5Sespie 
873c87b03e5Sespie       /* Create a BLOCK node and a corresponding matched set of
874c87b03e5Sespie 	 NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes at
875c87b03e5Sespie 	 this point.  The notes will encapsulate any and all fixup
876c87b03e5Sespie 	 code which we might later insert at this point in the insn
877c87b03e5Sespie 	 stream.  Also, the BLOCK node will be the parent (i.e. the
878c87b03e5Sespie 	 `SUPERBLOCK') of any other BLOCK nodes which we might create
879c87b03e5Sespie 	 later on when we are expanding the fixup code.
880c87b03e5Sespie 
881c87b03e5Sespie 	 Note that optimization passes (including expand_end_loop)
882c87b03e5Sespie 	 might move the *_BLOCK notes away, so we use a NOTE_INSN_DELETED
883c87b03e5Sespie 	 as a placeholder.  */
884c87b03e5Sespie 
885c87b03e5Sespie       {
886c87b03e5Sespie 	rtx original_before_jump
887c87b03e5Sespie 	  = last_insn ? last_insn : get_last_insn ();
888c87b03e5Sespie 	rtx start;
889c87b03e5Sespie 	rtx end;
890c87b03e5Sespie 	tree block;
891c87b03e5Sespie 
892c87b03e5Sespie 	block = make_node (BLOCK);
893c87b03e5Sespie 	TREE_USED (block) = 1;
894c87b03e5Sespie 
895c87b03e5Sespie 	if (!cfun->x_whole_function_mode_p)
896c87b03e5Sespie 	  (*lang_hooks.decls.insert_block) (block);
897c87b03e5Sespie 	else
898c87b03e5Sespie 	  {
899c87b03e5Sespie 	    BLOCK_CHAIN (block)
900c87b03e5Sespie 	      = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
901c87b03e5Sespie 	    BLOCK_CHAIN (DECL_INITIAL (current_function_decl))
902c87b03e5Sespie 	      = block;
903c87b03e5Sespie 	  }
904c87b03e5Sespie 
905c87b03e5Sespie 	start_sequence ();
906c87b03e5Sespie 	start = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
907c87b03e5Sespie 	if (cfun->x_whole_function_mode_p)
908c87b03e5Sespie 	  NOTE_BLOCK (start) = block;
909c87b03e5Sespie 	fixup->before_jump = emit_note (NULL, NOTE_INSN_DELETED);
910c87b03e5Sespie 	end = emit_note (NULL, NOTE_INSN_BLOCK_END);
911c87b03e5Sespie 	if (cfun->x_whole_function_mode_p)
912c87b03e5Sespie 	  NOTE_BLOCK (end) = block;
913c87b03e5Sespie 	fixup->context = block;
914c87b03e5Sespie 	end_sequence ();
915c87b03e5Sespie 	emit_insn_after (start, original_before_jump);
916c87b03e5Sespie       }
917c87b03e5Sespie 
918c87b03e5Sespie       fixup->block_start_count = current_block_start_count;
919c87b03e5Sespie       fixup->stack_level = 0;
920c87b03e5Sespie       fixup->cleanup_list_list
921c87b03e5Sespie 	= ((block->data.block.outer_cleanups
922c87b03e5Sespie 	    || block->data.block.cleanups)
923c87b03e5Sespie 	   ? tree_cons (NULL_TREE, block->data.block.cleanups,
924c87b03e5Sespie 			block->data.block.outer_cleanups)
925c87b03e5Sespie 	   : 0);
926c87b03e5Sespie       fixup->next = goto_fixup_chain;
927c87b03e5Sespie       goto_fixup_chain = fixup;
928c87b03e5Sespie     }
929c87b03e5Sespie 
930c87b03e5Sespie   return block != 0;
931c87b03e5Sespie }
932c87b03e5Sespie 
933c87b03e5Sespie /* Expand any needed fixups in the outputmost binding level of the
934c87b03e5Sespie    function.  FIRST_INSN is the first insn in the function.  */
935c87b03e5Sespie 
936c87b03e5Sespie void
expand_fixups(first_insn)937c87b03e5Sespie expand_fixups (first_insn)
938c87b03e5Sespie      rtx first_insn;
939c87b03e5Sespie {
940c87b03e5Sespie   fixup_gotos (NULL, NULL_RTX, NULL_TREE, first_insn, 0);
941c87b03e5Sespie }
942c87b03e5Sespie 
943c87b03e5Sespie /* When exiting a binding contour, process all pending gotos requiring fixups.
944c87b03e5Sespie    THISBLOCK is the structure that describes the block being exited.
945c87b03e5Sespie    STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
946c87b03e5Sespie    CLEANUP_LIST is a list of expressions to evaluate on exiting this contour.
947c87b03e5Sespie    FIRST_INSN is the insn that began this contour.
948c87b03e5Sespie 
949c87b03e5Sespie    Gotos that jump out of this contour must restore the
950c87b03e5Sespie    stack level and do the cleanups before actually jumping.
951c87b03e5Sespie 
952c87b03e5Sespie    DONT_JUMP_IN nonzero means report error there is a jump into this
953c87b03e5Sespie    contour from before the beginning of the contour.
954c87b03e5Sespie    This is also done if STACK_LEVEL is nonzero.  */
955c87b03e5Sespie 
956c87b03e5Sespie static void
fixup_gotos(thisblock,stack_level,cleanup_list,first_insn,dont_jump_in)957c87b03e5Sespie fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
958c87b03e5Sespie      struct nesting *thisblock;
959c87b03e5Sespie      rtx stack_level;
960c87b03e5Sespie      tree cleanup_list;
961c87b03e5Sespie      rtx first_insn;
962c87b03e5Sespie      int dont_jump_in;
963c87b03e5Sespie {
964c87b03e5Sespie   struct goto_fixup *f, *prev;
965c87b03e5Sespie 
966c87b03e5Sespie   /* F is the fixup we are considering; PREV is the previous one.  */
967c87b03e5Sespie   /* We run this loop in two passes so that cleanups of exited blocks
968c87b03e5Sespie      are run first, and blocks that are exited are marked so
969c87b03e5Sespie      afterwards.  */
970c87b03e5Sespie 
971c87b03e5Sespie   for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
972c87b03e5Sespie     {
973c87b03e5Sespie       /* Test for a fixup that is inactive because it is already handled.  */
974c87b03e5Sespie       if (f->before_jump == 0)
975c87b03e5Sespie 	{
976c87b03e5Sespie 	  /* Delete inactive fixup from the chain, if that is easy to do.  */
977c87b03e5Sespie 	  if (prev != 0)
978c87b03e5Sespie 	    prev->next = f->next;
979c87b03e5Sespie 	}
980c87b03e5Sespie       /* Has this fixup's target label been defined?
981c87b03e5Sespie 	 If so, we can finalize it.  */
982c87b03e5Sespie       else if (PREV_INSN (f->target_rtl) != 0)
983c87b03e5Sespie 	{
984c87b03e5Sespie 	  rtx cleanup_insns;
985c87b03e5Sespie 
986c87b03e5Sespie 	  /* If this fixup jumped into this contour from before the beginning
987c87b03e5Sespie 	     of this contour, report an error.   This code used to use
988c87b03e5Sespie 	     the first non-label insn after f->target_rtl, but that's
989c87b03e5Sespie 	     wrong since such can be added, by things like put_var_into_stack
990c87b03e5Sespie 	     and have INSN_UIDs that are out of the range of the block.  */
991c87b03e5Sespie 	  /* ??? Bug: this does not detect jumping in through intermediate
992c87b03e5Sespie 	     blocks that have stack levels or cleanups.
993c87b03e5Sespie 	     It detects only a problem with the innermost block
994c87b03e5Sespie 	     around the label.  */
995c87b03e5Sespie 	  if (f->target != 0
996c87b03e5Sespie 	      && (dont_jump_in || stack_level || cleanup_list)
997c87b03e5Sespie 	      && INSN_UID (first_insn) < INSN_UID (f->target_rtl)
998c87b03e5Sespie 	      && INSN_UID (first_insn) > INSN_UID (f->before_jump)
999c87b03e5Sespie 	      && ! DECL_ERROR_ISSUED (f->target))
1000c87b03e5Sespie 	    {
1001c87b03e5Sespie 	      error_with_decl (f->target,
1002c87b03e5Sespie 			       "label `%s' used before containing binding contour");
1003c87b03e5Sespie 	      /* Prevent multiple errors for one label.  */
1004c87b03e5Sespie 	      DECL_ERROR_ISSUED (f->target) = 1;
1005c87b03e5Sespie 	    }
1006c87b03e5Sespie 
1007c87b03e5Sespie 	  /* We will expand the cleanups into a sequence of their own and
1008c87b03e5Sespie 	     then later on we will attach this new sequence to the insn
1009c87b03e5Sespie 	     stream just ahead of the actual jump insn.  */
1010c87b03e5Sespie 
1011c87b03e5Sespie 	  start_sequence ();
1012c87b03e5Sespie 
1013c87b03e5Sespie 	  /* Temporarily restore the lexical context where we will
1014c87b03e5Sespie 	     logically be inserting the fixup code.  We do this for the
1015c87b03e5Sespie 	     sake of getting the debugging information right.  */
1016c87b03e5Sespie 
1017c87b03e5Sespie 	  (*lang_hooks.decls.pushlevel) (0);
1018c87b03e5Sespie 	  (*lang_hooks.decls.set_block) (f->context);
1019c87b03e5Sespie 
1020c87b03e5Sespie 	  /* Expand the cleanups for blocks this jump exits.  */
1021c87b03e5Sespie 	  if (f->cleanup_list_list)
1022c87b03e5Sespie 	    {
1023c87b03e5Sespie 	      tree lists;
1024c87b03e5Sespie 	      for (lists = f->cleanup_list_list; lists; lists = TREE_CHAIN (lists))
1025c87b03e5Sespie 		/* Marked elements correspond to blocks that have been closed.
1026c87b03e5Sespie 		   Do their cleanups.  */
1027c87b03e5Sespie 		if (TREE_ADDRESSABLE (lists)
1028c87b03e5Sespie 		    && TREE_VALUE (lists) != 0)
1029c87b03e5Sespie 		  {
1030c87b03e5Sespie 		    expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);
1031c87b03e5Sespie 		    /* Pop any pushes done in the cleanups,
1032c87b03e5Sespie 		       in case function is about to return.  */
1033c87b03e5Sespie 		    do_pending_stack_adjust ();
1034c87b03e5Sespie 		  }
1035c87b03e5Sespie 	    }
1036c87b03e5Sespie 
1037c87b03e5Sespie 	  /* Restore stack level for the biggest contour that this
1038c87b03e5Sespie 	     jump jumps out of.  */
1039c87b03e5Sespie 	  if (f->stack_level
1040c87b03e5Sespie 	      && ! (f->target_rtl == return_label
1041c87b03e5Sespie 		    && ((TREE_CODE (TREE_TYPE (current_function_decl))
1042c87b03e5Sespie 			 == FUNCTION_TYPE)
1043c87b03e5Sespie 			&& (TYPE_RETURNS_STACK_DEPRESSED
1044c87b03e5Sespie 			    (TREE_TYPE (current_function_decl))))))
1045c87b03e5Sespie 	    emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
1046c87b03e5Sespie 
1047c87b03e5Sespie 	  /* Finish up the sequence containing the insns which implement the
1048c87b03e5Sespie 	     necessary cleanups, and then attach that whole sequence to the
1049c87b03e5Sespie 	     insn stream just ahead of the actual jump insn.  Attaching it
1050c87b03e5Sespie 	     at that point insures that any cleanups which are in fact
1051c87b03e5Sespie 	     implicit C++ object destructions (which must be executed upon
1052c87b03e5Sespie 	     leaving the block) appear (to the debugger) to be taking place
1053c87b03e5Sespie 	     in an area of the generated code where the object(s) being
1054c87b03e5Sespie 	     destructed are still "in scope".  */
1055c87b03e5Sespie 
1056c87b03e5Sespie 	  cleanup_insns = get_insns ();
1057c87b03e5Sespie 	  (*lang_hooks.decls.poplevel) (1, 0, 0);
1058c87b03e5Sespie 
1059c87b03e5Sespie 	  end_sequence ();
1060c87b03e5Sespie 	  emit_insn_after (cleanup_insns, f->before_jump);
1061c87b03e5Sespie 
1062c87b03e5Sespie 	  f->before_jump = 0;
1063c87b03e5Sespie 	}
1064c87b03e5Sespie     }
1065c87b03e5Sespie 
1066c87b03e5Sespie   /* For any still-undefined labels, do the cleanups for this block now.
1067c87b03e5Sespie      We must do this now since items in the cleanup list may go out
1068c87b03e5Sespie      of scope when the block ends.  */
1069c87b03e5Sespie   for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
1070c87b03e5Sespie     if (f->before_jump != 0
1071c87b03e5Sespie 	&& PREV_INSN (f->target_rtl) == 0
1072c87b03e5Sespie 	/* Label has still not appeared.  If we are exiting a block with
1073c87b03e5Sespie 	   a stack level to restore, that started before the fixup,
1074c87b03e5Sespie 	   mark this stack level as needing restoration
1075c87b03e5Sespie 	   when the fixup is later finalized.  */
1076c87b03e5Sespie 	&& thisblock != 0
1077c87b03e5Sespie 	/* Note: if THISBLOCK == 0 and we have a label that hasn't appeared, it
1078c87b03e5Sespie 	   means the label is undefined.  That's erroneous, but possible.  */
1079c87b03e5Sespie 	&& (thisblock->data.block.block_start_count
1080c87b03e5Sespie 	    <= f->block_start_count))
1081c87b03e5Sespie       {
1082c87b03e5Sespie 	tree lists = f->cleanup_list_list;
1083c87b03e5Sespie 	rtx cleanup_insns;
1084c87b03e5Sespie 
1085c87b03e5Sespie 	for (; lists; lists = TREE_CHAIN (lists))
1086c87b03e5Sespie 	  /* If the following elt. corresponds to our containing block
1087c87b03e5Sespie 	     then the elt. must be for this block.  */
1088c87b03e5Sespie 	  if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)
1089c87b03e5Sespie 	    {
1090c87b03e5Sespie 	      start_sequence ();
1091c87b03e5Sespie 	      (*lang_hooks.decls.pushlevel) (0);
1092c87b03e5Sespie 	      (*lang_hooks.decls.set_block) (f->context);
1093c87b03e5Sespie 	      expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);
1094c87b03e5Sespie 	      do_pending_stack_adjust ();
1095c87b03e5Sespie 	      cleanup_insns = get_insns ();
1096c87b03e5Sespie 	      (*lang_hooks.decls.poplevel) (1, 0, 0);
1097c87b03e5Sespie 	      end_sequence ();
1098c87b03e5Sespie 	      if (cleanup_insns != 0)
1099c87b03e5Sespie 		f->before_jump
1100c87b03e5Sespie 		  = emit_insn_after (cleanup_insns, f->before_jump);
1101c87b03e5Sespie 
1102c87b03e5Sespie 	      f->cleanup_list_list = TREE_CHAIN (lists);
1103c87b03e5Sespie 	    }
1104c87b03e5Sespie 
1105c87b03e5Sespie 	if (stack_level)
1106c87b03e5Sespie 	  f->stack_level = stack_level;
1107c87b03e5Sespie       }
1108c87b03e5Sespie }
1109c87b03e5Sespie 
1110c87b03e5Sespie /* Return the number of times character C occurs in string S.  */
1111c87b03e5Sespie static int
n_occurrences(c,s)1112c87b03e5Sespie n_occurrences (c, s)
1113c87b03e5Sespie      int c;
1114c87b03e5Sespie      const char *s;
1115c87b03e5Sespie {
1116c87b03e5Sespie   int n = 0;
1117c87b03e5Sespie   while (*s)
1118c87b03e5Sespie     n += (*s++ == c);
1119c87b03e5Sespie   return n;
1120c87b03e5Sespie }
1121c87b03e5Sespie 
1122c87b03e5Sespie /* Generate RTL for an asm statement (explicit assembler code).
1123c87b03e5Sespie    STRING is a STRING_CST node containing the assembler code text,
1124c87b03e5Sespie    or an ADDR_EXPR containing a STRING_CST.  VOL nonzero means the
1125c87b03e5Sespie    insn is volatile; don't optimize it.  */
1126c87b03e5Sespie 
1127c87b03e5Sespie void
expand_asm(string,vol)1128c87b03e5Sespie expand_asm (string, vol)
1129c87b03e5Sespie      tree string;
1130c87b03e5Sespie      int vol;
1131c87b03e5Sespie {
1132c87b03e5Sespie   rtx body;
1133c87b03e5Sespie 
1134c87b03e5Sespie   if (TREE_CODE (string) == ADDR_EXPR)
1135c87b03e5Sespie     string = TREE_OPERAND (string, 0);
1136c87b03e5Sespie 
1137c87b03e5Sespie   body = gen_rtx_ASM_INPUT (VOIDmode, TREE_STRING_POINTER (string));
1138c87b03e5Sespie 
1139c87b03e5Sespie   MEM_VOLATILE_P (body) = vol;
1140c87b03e5Sespie 
1141c87b03e5Sespie   emit_insn (body);
1142c87b03e5Sespie 
1143c87b03e5Sespie   clear_last_expr ();
1144c87b03e5Sespie }
1145c87b03e5Sespie 
1146c87b03e5Sespie /* Parse the output constraint pointed to by *CONSTRAINT_P.  It is the
1147c87b03e5Sespie    OPERAND_NUMth output operand, indexed from zero.  There are NINPUTS
1148c87b03e5Sespie    inputs and NOUTPUTS outputs to this extended-asm.  Upon return,
1149c87b03e5Sespie    *ALLOWS_MEM will be TRUE iff the constraint allows the use of a
1150c87b03e5Sespie    memory operand.  Similarly, *ALLOWS_REG will be TRUE iff the
1151c87b03e5Sespie    constraint allows the use of a register operand.  And, *IS_INOUT
1152c87b03e5Sespie    will be true if the operand is read-write, i.e., if it is used as
1153c87b03e5Sespie    an input as well as an output.  If *CONSTRAINT_P is not in
1154c87b03e5Sespie    canonical form, it will be made canonical.  (Note that `+' will be
1155c87b03e5Sespie    rpelaced with `=' as part of this process.)
1156c87b03e5Sespie 
1157c87b03e5Sespie    Returns TRUE if all went well; FALSE if an error occurred.  */
1158c87b03e5Sespie 
1159c87b03e5Sespie bool
parse_output_constraint(constraint_p,operand_num,ninputs,noutputs,allows_mem,allows_reg,is_inout)1160c87b03e5Sespie parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
1161c87b03e5Sespie 			 allows_mem, allows_reg, is_inout)
1162c87b03e5Sespie      const char **constraint_p;
1163c87b03e5Sespie      int operand_num;
1164c87b03e5Sespie      int ninputs;
1165c87b03e5Sespie      int noutputs;
1166c87b03e5Sespie      bool *allows_mem;
1167c87b03e5Sespie      bool *allows_reg;
1168c87b03e5Sespie      bool *is_inout;
1169c87b03e5Sespie {
1170c87b03e5Sespie   const char *constraint = *constraint_p;
1171c87b03e5Sespie   const char *p;
1172c87b03e5Sespie 
1173c87b03e5Sespie   /* Assume the constraint doesn't allow the use of either a register
1174c87b03e5Sespie      or memory.  */
1175c87b03e5Sespie   *allows_mem = false;
1176c87b03e5Sespie   *allows_reg = false;
1177c87b03e5Sespie 
1178c87b03e5Sespie   /* Allow the `=' or `+' to not be at the beginning of the string,
1179c87b03e5Sespie      since it wasn't explicitly documented that way, and there is a
1180c87b03e5Sespie      large body of code that puts it last.  Swap the character to
1181c87b03e5Sespie      the front, so as not to uglify any place else.  */
1182c87b03e5Sespie   p = strchr (constraint, '=');
1183c87b03e5Sespie   if (!p)
1184c87b03e5Sespie     p = strchr (constraint, '+');
1185c87b03e5Sespie 
1186c87b03e5Sespie   /* If the string doesn't contain an `=', issue an error
1187c87b03e5Sespie      message.  */
1188c87b03e5Sespie   if (!p)
1189c87b03e5Sespie     {
1190c87b03e5Sespie       error ("output operand constraint lacks `='");
1191c87b03e5Sespie       return false;
1192c87b03e5Sespie     }
1193c87b03e5Sespie 
1194c87b03e5Sespie   /* If the constraint begins with `+', then the operand is both read
1195c87b03e5Sespie      from and written to.  */
1196c87b03e5Sespie   *is_inout = (*p == '+');
1197c87b03e5Sespie 
1198c87b03e5Sespie   /* Canonicalize the output constraint so that it begins with `='.  */
1199c87b03e5Sespie   if (p != constraint || is_inout)
1200c87b03e5Sespie     {
1201c87b03e5Sespie       char *buf;
1202c87b03e5Sespie       size_t c_len = strlen (constraint);
1203c87b03e5Sespie 
1204c87b03e5Sespie       if (p != constraint)
1205c87b03e5Sespie 	warning ("output constraint `%c' for operand %d is not at the beginning",
1206c87b03e5Sespie 		 *p, operand_num);
1207c87b03e5Sespie 
1208c87b03e5Sespie       /* Make a copy of the constraint.  */
1209c87b03e5Sespie       buf = alloca (c_len + 1);
1210c87b03e5Sespie       strcpy (buf, constraint);
1211c87b03e5Sespie       /* Swap the first character and the `=' or `+'.  */
1212c87b03e5Sespie       buf[p - constraint] = buf[0];
1213c87b03e5Sespie       /* Make sure the first character is an `='.  (Until we do this,
1214c87b03e5Sespie 	 it might be a `+'.)  */
1215c87b03e5Sespie       buf[0] = '=';
1216c87b03e5Sespie       /* Replace the constraint with the canonicalized string.  */
1217c87b03e5Sespie       *constraint_p = ggc_alloc_string (buf, c_len);
1218c87b03e5Sespie       constraint = *constraint_p;
1219c87b03e5Sespie     }
1220c87b03e5Sespie 
1221c87b03e5Sespie   /* Loop through the constraint string.  */
1222c87b03e5Sespie   for (p = constraint + 1; *p; ++p)
1223c87b03e5Sespie     switch (*p)
1224c87b03e5Sespie       {
1225c87b03e5Sespie       case '+':
1226c87b03e5Sespie       case '=':
1227c87b03e5Sespie 	error ("operand constraint contains incorrectly positioned '+' or '='");
1228c87b03e5Sespie 	return false;
1229c87b03e5Sespie 
1230c87b03e5Sespie       case '%':
1231c87b03e5Sespie 	if (operand_num + 1 == ninputs + noutputs)
1232c87b03e5Sespie 	  {
1233c87b03e5Sespie 	    error ("`%%' constraint used with last operand");
1234c87b03e5Sespie 	    return false;
1235c87b03e5Sespie 	  }
1236c87b03e5Sespie 	break;
1237c87b03e5Sespie 
1238c87b03e5Sespie       case 'V':  case 'm':  case 'o':
1239c87b03e5Sespie 	*allows_mem = true;
1240c87b03e5Sespie 	break;
1241c87b03e5Sespie 
1242c87b03e5Sespie       case '?':  case '!':  case '*':  case '&':  case '#':
1243c87b03e5Sespie       case 'E':  case 'F':  case 'G':  case 'H':
1244c87b03e5Sespie       case 's':  case 'i':  case 'n':
1245c87b03e5Sespie       case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
1246c87b03e5Sespie       case 'N':  case 'O':  case 'P':  case ',':
1247c87b03e5Sespie 	break;
1248c87b03e5Sespie 
1249c87b03e5Sespie       case '0':  case '1':  case '2':  case '3':  case '4':
1250c87b03e5Sespie       case '5':  case '6':  case '7':  case '8':  case '9':
1251c87b03e5Sespie       case '[':
1252c87b03e5Sespie 	error ("matching constraint not valid in output operand");
1253c87b03e5Sespie 	return false;
1254c87b03e5Sespie 
1255c87b03e5Sespie       case '<':  case '>':
1256c87b03e5Sespie 	/* ??? Before flow, auto inc/dec insns are not supposed to exist,
1257c87b03e5Sespie 	   excepting those that expand_call created.  So match memory
1258c87b03e5Sespie 	   and hope.  */
1259c87b03e5Sespie 	*allows_mem = true;
1260c87b03e5Sespie 	break;
1261c87b03e5Sespie 
1262c87b03e5Sespie       case 'g':  case 'X':
1263c87b03e5Sespie 	*allows_reg = true;
1264c87b03e5Sespie 	*allows_mem = true;
1265c87b03e5Sespie 	break;
1266c87b03e5Sespie 
1267c87b03e5Sespie       case 'p': case 'r':
1268c87b03e5Sespie 	*allows_reg = true;
1269c87b03e5Sespie 	break;
1270c87b03e5Sespie 
1271c87b03e5Sespie       default:
1272c87b03e5Sespie 	if (!ISALPHA (*p))
1273c87b03e5Sespie 	  break;
1274c87b03e5Sespie 	if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
1275c87b03e5Sespie 	  *allows_reg = true;
1276c87b03e5Sespie #ifdef EXTRA_CONSTRAINT
1277c87b03e5Sespie 	else if (EXTRA_ADDRESS_CONSTRAINT (*p))
1278c87b03e5Sespie 	  *allows_reg = true;
1279c87b03e5Sespie 	else if (EXTRA_MEMORY_CONSTRAINT (*p))
1280c87b03e5Sespie 	  *allows_mem = true;
1281c87b03e5Sespie 	else
1282c87b03e5Sespie 	  {
1283c87b03e5Sespie 	    /* Otherwise we can't assume anything about the nature of
1284c87b03e5Sespie 	       the constraint except that it isn't purely registers.
1285c87b03e5Sespie 	       Treat it like "g" and hope for the best.  */
1286c87b03e5Sespie 	    *allows_reg = true;
1287c87b03e5Sespie 	    *allows_mem = true;
1288c87b03e5Sespie 	  }
1289c87b03e5Sespie #endif
1290c87b03e5Sespie 	break;
1291c87b03e5Sespie       }
1292c87b03e5Sespie 
1293c87b03e5Sespie   return true;
1294c87b03e5Sespie }
1295c87b03e5Sespie 
1296c87b03e5Sespie /* Similar, but for input constraints.  */
1297c87b03e5Sespie 
1298c87b03e5Sespie static bool
parse_input_constraint(constraint_p,input_num,ninputs,noutputs,ninout,constraints,allows_mem,allows_reg)1299c87b03e5Sespie parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
1300c87b03e5Sespie 			constraints, allows_mem, allows_reg)
1301c87b03e5Sespie      const char **constraint_p;
1302c87b03e5Sespie      int input_num;
1303c87b03e5Sespie      int ninputs;
1304c87b03e5Sespie      int noutputs;
1305c87b03e5Sespie      int ninout;
1306c87b03e5Sespie      const char * const * constraints;
1307c87b03e5Sespie      bool *allows_mem;
1308c87b03e5Sespie      bool *allows_reg;
1309c87b03e5Sespie {
1310c87b03e5Sespie   const char *constraint = *constraint_p;
1311c87b03e5Sespie   const char *orig_constraint = constraint;
1312c87b03e5Sespie   size_t c_len = strlen (constraint);
1313c87b03e5Sespie   size_t j;
1314c87b03e5Sespie 
1315c87b03e5Sespie   /* Assume the constraint doesn't allow the use of either
1316c87b03e5Sespie      a register or memory.  */
1317c87b03e5Sespie   *allows_mem = false;
1318c87b03e5Sespie   *allows_reg = false;
1319c87b03e5Sespie 
1320c87b03e5Sespie   /* Make sure constraint has neither `=', `+', nor '&'.  */
1321c87b03e5Sespie 
1322c87b03e5Sespie   for (j = 0; j < c_len; j++)
1323c87b03e5Sespie     switch (constraint[j])
1324c87b03e5Sespie       {
1325c87b03e5Sespie       case '+':  case '=':  case '&':
1326c87b03e5Sespie 	if (constraint == orig_constraint)
1327c87b03e5Sespie 	  {
1328c87b03e5Sespie 	    error ("input operand constraint contains `%c'", constraint[j]);
1329c87b03e5Sespie 	    return false;
1330c87b03e5Sespie 	  }
1331c87b03e5Sespie 	break;
1332c87b03e5Sespie 
1333c87b03e5Sespie       case '%':
1334c87b03e5Sespie 	if (constraint == orig_constraint
1335c87b03e5Sespie 	    && input_num + 1 == ninputs - ninout)
1336c87b03e5Sespie 	  {
1337c87b03e5Sespie 	    error ("`%%' constraint used with last operand");
1338c87b03e5Sespie 	    return false;
1339c87b03e5Sespie 	  }
1340c87b03e5Sespie 	break;
1341c87b03e5Sespie 
1342c87b03e5Sespie       case 'V':  case 'm':  case 'o':
1343c87b03e5Sespie 	*allows_mem = true;
1344c87b03e5Sespie 	break;
1345c87b03e5Sespie 
1346c87b03e5Sespie       case '<':  case '>':
1347c87b03e5Sespie       case '?':  case '!':  case '*':  case '#':
1348c87b03e5Sespie       case 'E':  case 'F':  case 'G':  case 'H':
1349c87b03e5Sespie       case 's':  case 'i':  case 'n':
1350c87b03e5Sespie       case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
1351c87b03e5Sespie       case 'N':  case 'O':  case 'P':  case ',':
1352c87b03e5Sespie 	break;
1353c87b03e5Sespie 
1354c87b03e5Sespie 	/* Whether or not a numeric constraint allows a register is
1355c87b03e5Sespie 	   decided by the matching constraint, and so there is no need
1356c87b03e5Sespie 	   to do anything special with them.  We must handle them in
1357c87b03e5Sespie 	   the default case, so that we don't unnecessarily force
1358c87b03e5Sespie 	   operands to memory.  */
1359c87b03e5Sespie       case '0':  case '1':  case '2':  case '3':  case '4':
1360c87b03e5Sespie       case '5':  case '6':  case '7':  case '8':  case '9':
1361c87b03e5Sespie 	{
1362c87b03e5Sespie 	  char *end;
1363c87b03e5Sespie 	  unsigned long match;
1364c87b03e5Sespie 
1365c87b03e5Sespie 	  match = strtoul (constraint + j, &end, 10);
1366c87b03e5Sespie 	  if (match >= (unsigned long) noutputs)
1367c87b03e5Sespie 	    {
1368c87b03e5Sespie 	      error ("matching constraint references invalid operand number");
1369c87b03e5Sespie 	      return false;
1370c87b03e5Sespie 	    }
1371c87b03e5Sespie 
1372c87b03e5Sespie 	  /* Try and find the real constraint for this dup.  Only do this
1373c87b03e5Sespie 	     if the matching constraint is the only alternative.  */
1374c87b03e5Sespie 	  if (*end == '\0'
1375c87b03e5Sespie 	      && (j == 0 || (j == 1 && constraint[0] == '%')))
1376c87b03e5Sespie 	    {
1377c87b03e5Sespie 	      constraint = constraints[match];
1378c87b03e5Sespie 	      *constraint_p = constraint;
1379c87b03e5Sespie 	      c_len = strlen (constraint);
1380c87b03e5Sespie 	      j = 0;
1381c87b03e5Sespie 	      break;
1382c87b03e5Sespie 	    }
1383c87b03e5Sespie 	  else
1384c87b03e5Sespie 	    j = end - constraint;
1385c87b03e5Sespie 	}
1386c87b03e5Sespie 	/* Fall through.  */
1387c87b03e5Sespie 
1388c87b03e5Sespie       case 'p':  case 'r':
1389c87b03e5Sespie 	*allows_reg = true;
1390c87b03e5Sespie 	break;
1391c87b03e5Sespie 
1392c87b03e5Sespie       case 'g':  case 'X':
1393c87b03e5Sespie 	*allows_reg = true;
1394c87b03e5Sespie 	*allows_mem = true;
1395c87b03e5Sespie 	break;
1396c87b03e5Sespie 
1397c87b03e5Sespie       default:
1398c87b03e5Sespie 	if (! ISALPHA (constraint[j]))
1399c87b03e5Sespie 	  {
1400c87b03e5Sespie 	    error ("invalid punctuation `%c' in constraint", constraint[j]);
1401c87b03e5Sespie 	    return false;
1402c87b03e5Sespie 	  }
1403c87b03e5Sespie 	if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
1404c87b03e5Sespie 	  *allows_reg = true;
1405c87b03e5Sespie #ifdef EXTRA_CONSTRAINT
1406c87b03e5Sespie 	else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
1407c87b03e5Sespie 	  *allows_reg = true;
1408c87b03e5Sespie 	else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
1409c87b03e5Sespie 	  *allows_mem = true;
1410c87b03e5Sespie 	else
1411c87b03e5Sespie 	  {
1412c87b03e5Sespie 	    /* Otherwise we can't assume anything about the nature of
1413c87b03e5Sespie 	       the constraint except that it isn't purely registers.
1414c87b03e5Sespie 	       Treat it like "g" and hope for the best.  */
1415c87b03e5Sespie 	    *allows_reg = true;
1416c87b03e5Sespie 	    *allows_mem = true;
1417c87b03e5Sespie 	  }
1418c87b03e5Sespie #endif
1419c87b03e5Sespie 	break;
1420c87b03e5Sespie       }
1421c87b03e5Sespie 
1422c87b03e5Sespie   return true;
1423c87b03e5Sespie }
1424c87b03e5Sespie 
1425c87b03e5Sespie /* Check for overlap between registers marked in CLOBBERED_REGS and
1426c87b03e5Sespie    anything inappropriate in DECL.  Emit error and return TRUE for error,
1427c87b03e5Sespie    FALSE for ok.  */
1428c87b03e5Sespie 
1429c87b03e5Sespie static bool
decl_conflicts_with_clobbers_p(decl,clobbered_regs)1430c87b03e5Sespie decl_conflicts_with_clobbers_p (decl, clobbered_regs)
1431c87b03e5Sespie      tree decl;
1432c87b03e5Sespie      const HARD_REG_SET clobbered_regs;
1433c87b03e5Sespie {
1434c87b03e5Sespie   /* Conflicts between asm-declared register variables and the clobber
1435c87b03e5Sespie      list are not allowed.  */
1436c87b03e5Sespie   if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
1437c87b03e5Sespie       && DECL_REGISTER (decl)
1438c87b03e5Sespie       && REG_P (DECL_RTL (decl))
1439c87b03e5Sespie       && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
1440c87b03e5Sespie     {
1441c87b03e5Sespie       rtx reg = DECL_RTL (decl);
1442c87b03e5Sespie       unsigned int regno;
1443c87b03e5Sespie 
1444c87b03e5Sespie       for (regno = REGNO (reg);
1445c87b03e5Sespie 	   regno < (REGNO (reg)
1446c87b03e5Sespie 		    + HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)));
1447c87b03e5Sespie 	   regno++)
1448c87b03e5Sespie 	if (TEST_HARD_REG_BIT (clobbered_regs, regno))
1449c87b03e5Sespie 	  {
1450c87b03e5Sespie 	    error ("asm-specifier for variable `%s' conflicts with asm clobber list",
1451c87b03e5Sespie 		   IDENTIFIER_POINTER (DECL_NAME (decl)));
1452c87b03e5Sespie 
1453c87b03e5Sespie 	    /* Reset registerness to stop multiple errors emitted for a
1454c87b03e5Sespie 	       single variable.  */
1455c87b03e5Sespie 	    DECL_REGISTER (decl) = 0;
1456c87b03e5Sespie 	    return true;
1457c87b03e5Sespie 	  }
1458c87b03e5Sespie     }
1459c87b03e5Sespie   return false;
1460c87b03e5Sespie }
1461c87b03e5Sespie 
1462c87b03e5Sespie /* Generate RTL for an asm statement with arguments.
1463c87b03e5Sespie    STRING is the instruction template.
1464c87b03e5Sespie    OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
1465c87b03e5Sespie    Each output or input has an expression in the TREE_VALUE and
1466c87b03e5Sespie    and a tree list in TREE_PURPOSE which in turn contains a constraint
1467c87b03e5Sespie    name in TREE_VALUE (or NULL_TREE) and a constraint string
1468c87b03e5Sespie    in TREE_PURPOSE.
1469c87b03e5Sespie    CLOBBERS is a list of STRING_CST nodes each naming a hard register
1470c87b03e5Sespie    that is clobbered by this insn.
1471c87b03e5Sespie 
1472c87b03e5Sespie    Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
1473c87b03e5Sespie    Some elements of OUTPUTS may be replaced with trees representing temporary
1474c87b03e5Sespie    values.  The caller should copy those temporary values to the originally
1475c87b03e5Sespie    specified lvalues.
1476c87b03e5Sespie 
1477c87b03e5Sespie    VOL nonzero means the insn is volatile; don't optimize it.  */
1478c87b03e5Sespie 
1479c87b03e5Sespie void
expand_asm_operands(string,outputs,inputs,clobbers,vol,filename,line)1480c87b03e5Sespie expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
1481c87b03e5Sespie      tree string, outputs, inputs, clobbers;
1482c87b03e5Sespie      int vol;
1483c87b03e5Sespie      const char *filename;
1484c87b03e5Sespie      int line;
1485c87b03e5Sespie {
1486c87b03e5Sespie   rtvec argvec, constraintvec;
1487c87b03e5Sespie   rtx body;
1488c87b03e5Sespie   int ninputs = list_length (inputs);
1489c87b03e5Sespie   int noutputs = list_length (outputs);
1490c87b03e5Sespie   int ninout;
1491c87b03e5Sespie   int nclobbers;
1492c87b03e5Sespie   HARD_REG_SET clobbered_regs;
1493c87b03e5Sespie   int clobber_conflict_found = 0;
1494c87b03e5Sespie   tree tail;
1495c87b03e5Sespie   int i;
1496c87b03e5Sespie   /* Vector of RTX's of evaluated output operands.  */
1497c87b03e5Sespie   rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
1498c87b03e5Sespie   int *inout_opnum = (int *) alloca (noutputs * sizeof (int));
1499c87b03e5Sespie   rtx *real_output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
1500c87b03e5Sespie   enum machine_mode *inout_mode
1501c87b03e5Sespie     = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
1502c87b03e5Sespie   const char **constraints
1503c87b03e5Sespie     = (const char **) alloca ((noutputs + ninputs) * sizeof (const char *));
1504c87b03e5Sespie   /* The insn we have emitted.  */
1505c87b03e5Sespie   rtx insn;
1506c87b03e5Sespie   int old_generating_concat_p = generating_concat_p;
1507c87b03e5Sespie 
1508c87b03e5Sespie   /* An ASM with no outputs needs to be treated as volatile, for now.  */
1509c87b03e5Sespie   if (noutputs == 0)
1510c87b03e5Sespie     vol = 1;
1511c87b03e5Sespie 
1512c87b03e5Sespie   if (! check_operand_nalternatives (outputs, inputs))
1513c87b03e5Sespie     return;
1514c87b03e5Sespie 
1515c87b03e5Sespie   if (! check_unique_operand_names (outputs, inputs))
1516c87b03e5Sespie     return;
1517c87b03e5Sespie 
1518c87b03e5Sespie   string = resolve_operand_names (string, outputs, inputs, constraints);
1519c87b03e5Sespie 
1520c87b03e5Sespie #ifdef MD_ASM_CLOBBERS
1521c87b03e5Sespie   /* Sometimes we wish to automatically clobber registers across an asm.
1522c87b03e5Sespie      Case in point is when the i386 backend moved from cc0 to a hard reg --
1523c87b03e5Sespie      maintaining source-level compatibility means automatically clobbering
1524c87b03e5Sespie      the flags register.  */
1525c87b03e5Sespie   MD_ASM_CLOBBERS (clobbers);
1526c87b03e5Sespie #endif
1527c87b03e5Sespie 
1528c87b03e5Sespie   /* Count the number of meaningful clobbered registers, ignoring what
1529c87b03e5Sespie      we would ignore later.  */
1530c87b03e5Sespie   nclobbers = 0;
1531c87b03e5Sespie   CLEAR_HARD_REG_SET (clobbered_regs);
1532c87b03e5Sespie   for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
1533c87b03e5Sespie     {
1534c87b03e5Sespie       const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
1535c87b03e5Sespie 
1536c87b03e5Sespie       i = decode_reg_name (regname);
1537c87b03e5Sespie       if (i >= 0 || i == -4)
1538c87b03e5Sespie 	++nclobbers;
1539c87b03e5Sespie       else if (i == -2)
1540c87b03e5Sespie 	error ("unknown register name `%s' in `asm'", regname);
1541c87b03e5Sespie 
1542c87b03e5Sespie       /* Mark clobbered registers.  */
1543c87b03e5Sespie       if (i >= 0)
1544c87b03e5Sespie 	SET_HARD_REG_BIT (clobbered_regs, i);
1545c87b03e5Sespie     }
1546c87b03e5Sespie 
1547c87b03e5Sespie   clear_last_expr ();
1548c87b03e5Sespie 
1549c87b03e5Sespie   /* First pass over inputs and outputs checks validity and sets
1550c87b03e5Sespie      mark_addressable if needed.  */
1551c87b03e5Sespie 
1552c87b03e5Sespie   ninout = 0;
1553c87b03e5Sespie   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1554c87b03e5Sespie     {
1555c87b03e5Sespie       tree val = TREE_VALUE (tail);
1556c87b03e5Sespie       tree type = TREE_TYPE (val);
1557c87b03e5Sespie       const char *constraint;
1558c87b03e5Sespie       bool is_inout;
1559c87b03e5Sespie       bool allows_reg;
1560c87b03e5Sespie       bool allows_mem;
1561c87b03e5Sespie 
1562c87b03e5Sespie       /* If there's an erroneous arg, emit no insn.  */
1563c87b03e5Sespie       if (type == error_mark_node)
1564c87b03e5Sespie 	return;
1565c87b03e5Sespie 
1566c87b03e5Sespie       /* Try to parse the output constraint.  If that fails, there's
1567c87b03e5Sespie 	 no point in going further.  */
1568c87b03e5Sespie       constraint = constraints[i];
1569c87b03e5Sespie       if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
1570c87b03e5Sespie 				    &allows_mem, &allows_reg, &is_inout))
1571c87b03e5Sespie 	return;
1572c87b03e5Sespie 
1573c87b03e5Sespie       if (! allows_reg
1574c87b03e5Sespie 	  && (allows_mem
1575c87b03e5Sespie 	      || is_inout
1576c87b03e5Sespie 	      || (DECL_P (val)
1577c87b03e5Sespie 		  && GET_CODE (DECL_RTL (val)) == REG
1578c87b03e5Sespie 		  && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
1579c87b03e5Sespie 	(*lang_hooks.mark_addressable) (val);
1580c87b03e5Sespie 
1581c87b03e5Sespie       if (is_inout)
1582c87b03e5Sespie 	ninout++;
1583c87b03e5Sespie     }
1584c87b03e5Sespie 
1585c87b03e5Sespie   ninputs += ninout;
1586c87b03e5Sespie   if (ninputs + noutputs > MAX_RECOG_OPERANDS)
1587c87b03e5Sespie     {
1588c87b03e5Sespie       error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
1589c87b03e5Sespie       return;
1590c87b03e5Sespie     }
1591c87b03e5Sespie 
1592c87b03e5Sespie   for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
1593c87b03e5Sespie     {
1594c87b03e5Sespie       bool allows_reg, allows_mem;
1595c87b03e5Sespie       const char *constraint;
1596c87b03e5Sespie 
1597c87b03e5Sespie       /* If there's an erroneous arg, emit no insn, because the ASM_INPUT
1598c87b03e5Sespie 	 would get VOIDmode and that could cause a crash in reload.  */
1599c87b03e5Sespie       if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
1600c87b03e5Sespie 	return;
1601c87b03e5Sespie 
1602c87b03e5Sespie       constraint = constraints[i + noutputs];
1603c87b03e5Sespie       if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
1604c87b03e5Sespie 				    constraints, &allows_mem, &allows_reg))
1605c87b03e5Sespie 	return;
1606c87b03e5Sespie 
1607c87b03e5Sespie       if (! allows_reg && allows_mem)
1608c87b03e5Sespie 	(*lang_hooks.mark_addressable) (TREE_VALUE (tail));
1609c87b03e5Sespie     }
1610c87b03e5Sespie 
1611c87b03e5Sespie   /* Second pass evaluates arguments.  */
1612c87b03e5Sespie 
1613c87b03e5Sespie   ninout = 0;
1614c87b03e5Sespie   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1615c87b03e5Sespie     {
1616c87b03e5Sespie       tree val = TREE_VALUE (tail);
1617c87b03e5Sespie       tree type = TREE_TYPE (val);
1618c87b03e5Sespie       bool is_inout;
1619c87b03e5Sespie       bool allows_reg;
1620c87b03e5Sespie       bool allows_mem;
1621c87b03e5Sespie       rtx op;
1622c87b03e5Sespie 
1623c87b03e5Sespie       if (!parse_output_constraint (&constraints[i], i, ninputs,
1624c87b03e5Sespie 				    noutputs, &allows_mem, &allows_reg,
1625c87b03e5Sespie 				    &is_inout))
1626c87b03e5Sespie 	abort ();
1627c87b03e5Sespie 
1628c87b03e5Sespie       /* If an output operand is not a decl or indirect ref and our constraint
1629c87b03e5Sespie 	 allows a register, make a temporary to act as an intermediate.
1630c87b03e5Sespie 	 Make the asm insn write into that, then our caller will copy it to
1631c87b03e5Sespie 	 the real output operand.  Likewise for promoted variables.  */
1632c87b03e5Sespie 
1633c87b03e5Sespie       generating_concat_p = 0;
1634c87b03e5Sespie 
1635c87b03e5Sespie       real_output_rtx[i] = NULL_RTX;
1636c87b03e5Sespie       if ((TREE_CODE (val) == INDIRECT_REF
1637c87b03e5Sespie 	   && allows_mem)
1638c87b03e5Sespie 	  || (DECL_P (val)
1639c87b03e5Sespie 	      && (allows_mem || GET_CODE (DECL_RTL (val)) == REG)
1640c87b03e5Sespie 	      && ! (GET_CODE (DECL_RTL (val)) == REG
1641c87b03e5Sespie 		    && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
1642c87b03e5Sespie 	  || ! allows_reg
1643c87b03e5Sespie 	  || is_inout)
1644c87b03e5Sespie 	{
1645c87b03e5Sespie 	  op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
1646c87b03e5Sespie 	  if (GET_CODE (op) == MEM)
1647c87b03e5Sespie 	    op = validize_mem (op);
1648c87b03e5Sespie 
1649c87b03e5Sespie 	  if (! allows_reg && GET_CODE (op) != MEM)
1650c87b03e5Sespie 	    error ("output number %d not directly addressable", i);
1651c87b03e5Sespie 	  if ((! allows_mem && GET_CODE (op) == MEM)
1652c87b03e5Sespie 	      || GET_CODE (op) == CONCAT)
1653c87b03e5Sespie 	    {
1654c87b03e5Sespie 	      real_output_rtx[i] = protect_from_queue (op, 1);
1655c87b03e5Sespie 	      op = gen_reg_rtx (GET_MODE (op));
1656c87b03e5Sespie 	      if (is_inout)
1657c87b03e5Sespie 		emit_move_insn (op, real_output_rtx[i]);
1658c87b03e5Sespie 	    }
1659c87b03e5Sespie 	}
1660c87b03e5Sespie       else
1661c87b03e5Sespie 	{
1662c87b03e5Sespie 	  op = assign_temp (type, 0, 0, 1);
1663c87b03e5Sespie 	  op = validize_mem (op);
1664c87b03e5Sespie 	  TREE_VALUE (tail) = make_tree (type, op);
1665c87b03e5Sespie 	}
1666c87b03e5Sespie       output_rtx[i] = op;
1667c87b03e5Sespie 
1668c87b03e5Sespie       generating_concat_p = old_generating_concat_p;
1669c87b03e5Sespie 
1670c87b03e5Sespie       if (is_inout)
1671c87b03e5Sespie 	{
1672c87b03e5Sespie 	  inout_mode[ninout] = TYPE_MODE (type);
1673c87b03e5Sespie 	  inout_opnum[ninout++] = i;
1674c87b03e5Sespie 	}
1675c87b03e5Sespie 
1676c87b03e5Sespie       if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
1677c87b03e5Sespie 	clobber_conflict_found = 1;
1678c87b03e5Sespie     }
1679c87b03e5Sespie 
1680c87b03e5Sespie   /* Make vectors for the expression-rtx, constraint strings,
1681c87b03e5Sespie      and named operands.  */
1682c87b03e5Sespie 
1683c87b03e5Sespie   argvec = rtvec_alloc (ninputs);
1684c87b03e5Sespie   constraintvec = rtvec_alloc (ninputs);
1685c87b03e5Sespie 
1686c87b03e5Sespie   body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
1687c87b03e5Sespie 				: GET_MODE (output_rtx[0])),
1688c87b03e5Sespie 			       TREE_STRING_POINTER (string),
1689c87b03e5Sespie 			       empty_string, 0, argvec, constraintvec,
1690c87b03e5Sespie 			       filename, line);
1691c87b03e5Sespie 
1692c87b03e5Sespie   MEM_VOLATILE_P (body) = vol;
1693c87b03e5Sespie 
1694c87b03e5Sespie   /* Eval the inputs and put them into ARGVEC.
1695c87b03e5Sespie      Put their constraints into ASM_INPUTs and store in CONSTRAINTS.  */
1696c87b03e5Sespie 
1697c87b03e5Sespie   for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
1698c87b03e5Sespie     {
1699c87b03e5Sespie       bool allows_reg, allows_mem;
1700c87b03e5Sespie       const char *constraint;
1701c87b03e5Sespie       tree val, type;
1702c87b03e5Sespie       rtx op;
1703c87b03e5Sespie 
1704c87b03e5Sespie       constraint = constraints[i + noutputs];
1705c87b03e5Sespie       if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
1706c87b03e5Sespie 				    constraints, &allows_mem, &allows_reg))
1707c87b03e5Sespie 	abort ();
1708c87b03e5Sespie 
1709c87b03e5Sespie       generating_concat_p = 0;
1710c87b03e5Sespie 
1711c87b03e5Sespie       val = TREE_VALUE (tail);
1712c87b03e5Sespie       type = TREE_TYPE (val);
1713c87b03e5Sespie       op = expand_expr (val, NULL_RTX, VOIDmode,
1714c87b03e5Sespie 			(allows_mem && !allows_reg
1715c87b03e5Sespie 			 ? EXPAND_MEMORY : EXPAND_NORMAL));
1716c87b03e5Sespie 
1717c87b03e5Sespie       /* Never pass a CONCAT to an ASM.  */
1718c87b03e5Sespie       if (GET_CODE (op) == CONCAT)
1719c87b03e5Sespie 	op = force_reg (GET_MODE (op), op);
1720c87b03e5Sespie       else if (GET_CODE (op) == MEM)
1721c87b03e5Sespie 	op = validize_mem (op);
1722c87b03e5Sespie 
1723c87b03e5Sespie       if (asm_operand_ok (op, constraint) <= 0)
1724c87b03e5Sespie 	{
1725c87b03e5Sespie 	  if (allows_reg)
1726c87b03e5Sespie 	    op = force_reg (TYPE_MODE (type), op);
1727c87b03e5Sespie 	  else if (!allows_mem)
1728c87b03e5Sespie 	    warning ("asm operand %d probably doesn't match constraints",
1729c87b03e5Sespie 		     i + noutputs);
1730c87b03e5Sespie 	  else if (GET_CODE (op) == MEM)
1731c87b03e5Sespie 	    {
1732c87b03e5Sespie 	      /* We won't recognize either volatile memory or memory
1733c87b03e5Sespie 		 with a queued address as available a memory_operand
1734c87b03e5Sespie 		 at this point.  Ignore it: clearly this *is* a memory.  */
1735c87b03e5Sespie 	    }
1736c87b03e5Sespie 	  else
1737c87b03e5Sespie 	    {
1738c87b03e5Sespie 	      warning ("use of memory input without lvalue in asm operand %d is deprecated",
1739c87b03e5Sespie 		       i + noutputs);
1740c87b03e5Sespie 
1741c87b03e5Sespie 	      if (CONSTANT_P (op))
1742c87b03e5Sespie 		{
1743c87b03e5Sespie 		  op = force_const_mem (TYPE_MODE (type), op);
1744c87b03e5Sespie 		  op = validize_mem (op);
1745c87b03e5Sespie 		}
1746c87b03e5Sespie 	      else if (GET_CODE (op) == REG
1747c87b03e5Sespie 		       || GET_CODE (op) == SUBREG
1748c87b03e5Sespie 		       || GET_CODE (op) == ADDRESSOF
1749c87b03e5Sespie 		       || GET_CODE (op) == CONCAT)
1750c87b03e5Sespie 		{
1751c87b03e5Sespie 		  tree qual_type = build_qualified_type (type,
1752c87b03e5Sespie 							 (TYPE_QUALS (type)
1753c87b03e5Sespie 							  | TYPE_QUAL_CONST));
1754c87b03e5Sespie 		  rtx memloc = assign_temp (qual_type, 1, 1, 1);
1755c87b03e5Sespie 		  memloc = validize_mem (memloc);
1756c87b03e5Sespie 		  emit_move_insn (memloc, op);
1757c87b03e5Sespie 		  op = memloc;
1758c87b03e5Sespie 		}
1759c87b03e5Sespie 	    }
1760c87b03e5Sespie 	}
1761c87b03e5Sespie 
1762c87b03e5Sespie       generating_concat_p = old_generating_concat_p;
1763c87b03e5Sespie       ASM_OPERANDS_INPUT (body, i) = op;
1764c87b03e5Sespie 
1765c87b03e5Sespie       ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
1766c87b03e5Sespie 	= gen_rtx_ASM_INPUT (TYPE_MODE (type), constraints[i + noutputs]);
1767c87b03e5Sespie 
1768c87b03e5Sespie       if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
1769c87b03e5Sespie 	clobber_conflict_found = 1;
1770c87b03e5Sespie     }
1771c87b03e5Sespie 
1772c87b03e5Sespie   /* Protect all the operands from the queue now that they have all been
1773c87b03e5Sespie      evaluated.  */
1774c87b03e5Sespie 
1775c87b03e5Sespie   generating_concat_p = 0;
1776c87b03e5Sespie 
1777c87b03e5Sespie   for (i = 0; i < ninputs - ninout; i++)
1778c87b03e5Sespie     ASM_OPERANDS_INPUT (body, i)
1779c87b03e5Sespie       = protect_from_queue (ASM_OPERANDS_INPUT (body, i), 0);
1780c87b03e5Sespie 
1781c87b03e5Sespie   for (i = 0; i < noutputs; i++)
1782c87b03e5Sespie     output_rtx[i] = protect_from_queue (output_rtx[i], 1);
1783c87b03e5Sespie 
1784c87b03e5Sespie   /* For in-out operands, copy output rtx to input rtx.  */
1785c87b03e5Sespie   for (i = 0; i < ninout; i++)
1786c87b03e5Sespie     {
1787c87b03e5Sespie       int j = inout_opnum[i];
1788c87b03e5Sespie       char buffer[16];
1789c87b03e5Sespie 
1790c87b03e5Sespie       ASM_OPERANDS_INPUT (body, ninputs - ninout + i)
1791c87b03e5Sespie 	= output_rtx[j];
1792c87b03e5Sespie 
1793c87b03e5Sespie       sprintf (buffer, "%d", j);
1794c87b03e5Sespie       ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
1795c87b03e5Sespie 	= gen_rtx_ASM_INPUT (inout_mode[i], ggc_alloc_string (buffer, -1));
1796c87b03e5Sespie     }
1797c87b03e5Sespie 
1798c87b03e5Sespie   generating_concat_p = old_generating_concat_p;
1799c87b03e5Sespie 
1800c87b03e5Sespie   /* Now, for each output, construct an rtx
1801c87b03e5Sespie      (set OUTPUT (asm_operands INSN OUTPUTCONSTRAINT OUTPUTNUMBER
1802c87b03e5Sespie 			       ARGVEC CONSTRAINTS OPNAMES))
1803c87b03e5Sespie      If there is more than one, put them inside a PARALLEL.  */
1804c87b03e5Sespie 
1805c87b03e5Sespie   if (noutputs == 1 && nclobbers == 0)
1806c87b03e5Sespie     {
1807c87b03e5Sespie       ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
1808c87b03e5Sespie       insn = emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
1809c87b03e5Sespie     }
1810c87b03e5Sespie 
1811c87b03e5Sespie   else if (noutputs == 0 && nclobbers == 0)
1812c87b03e5Sespie     {
1813c87b03e5Sespie       /* No output operands: put in a raw ASM_OPERANDS rtx.  */
1814c87b03e5Sespie       insn = emit_insn (body);
1815c87b03e5Sespie     }
1816c87b03e5Sespie 
1817c87b03e5Sespie   else
1818c87b03e5Sespie     {
1819c87b03e5Sespie       rtx obody = body;
1820c87b03e5Sespie       int num = noutputs;
1821c87b03e5Sespie 
1822c87b03e5Sespie       if (num == 0)
1823c87b03e5Sespie 	num = 1;
1824c87b03e5Sespie 
1825c87b03e5Sespie       body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
1826c87b03e5Sespie 
1827c87b03e5Sespie       /* For each output operand, store a SET.  */
1828c87b03e5Sespie       for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1829c87b03e5Sespie 	{
1830c87b03e5Sespie 	  XVECEXP (body, 0, i)
1831c87b03e5Sespie 	    = gen_rtx_SET (VOIDmode,
1832c87b03e5Sespie 			   output_rtx[i],
1833c87b03e5Sespie 			   gen_rtx_ASM_OPERANDS
1834c87b03e5Sespie 			   (GET_MODE (output_rtx[i]),
1835c87b03e5Sespie 			    TREE_STRING_POINTER (string),
1836c87b03e5Sespie 			    constraints[i], i, argvec, constraintvec,
1837c87b03e5Sespie 			    filename, line));
1838c87b03e5Sespie 
1839c87b03e5Sespie 	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
1840c87b03e5Sespie 	}
1841c87b03e5Sespie 
1842c87b03e5Sespie       /* If there are no outputs (but there are some clobbers)
1843c87b03e5Sespie 	 store the bare ASM_OPERANDS into the PARALLEL.  */
1844c87b03e5Sespie 
1845c87b03e5Sespie       if (i == 0)
1846c87b03e5Sespie 	XVECEXP (body, 0, i++) = obody;
1847c87b03e5Sespie 
1848c87b03e5Sespie       /* Store (clobber REG) for each clobbered register specified.  */
1849c87b03e5Sespie 
1850c87b03e5Sespie       for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
1851c87b03e5Sespie 	{
1852c87b03e5Sespie 	  const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
1853c87b03e5Sespie 	  int j = decode_reg_name (regname);
1854c87b03e5Sespie 	  rtx clobbered_reg;
1855c87b03e5Sespie 
1856c87b03e5Sespie 	  if (j < 0)
1857c87b03e5Sespie 	    {
1858c87b03e5Sespie 	      if (j == -3)	/* `cc', which is not a register */
1859c87b03e5Sespie 		continue;
1860c87b03e5Sespie 
1861c87b03e5Sespie 	      if (j == -4)	/* `memory', don't cache memory across asm */
1862c87b03e5Sespie 		{
1863c87b03e5Sespie 		  XVECEXP (body, 0, i++)
1864c87b03e5Sespie 		    = gen_rtx_CLOBBER (VOIDmode,
1865c87b03e5Sespie 				       gen_rtx_MEM
1866c87b03e5Sespie 				       (BLKmode,
1867c87b03e5Sespie 					gen_rtx_SCRATCH (VOIDmode)));
1868c87b03e5Sespie 		  continue;
1869c87b03e5Sespie 		}
1870c87b03e5Sespie 
1871c87b03e5Sespie 	      /* Ignore unknown register, error already signaled.  */
1872c87b03e5Sespie 	      continue;
1873c87b03e5Sespie 	    }
1874c87b03e5Sespie 
1875c87b03e5Sespie 	  /* Use QImode since that's guaranteed to clobber just one reg.  */
1876c87b03e5Sespie 	  clobbered_reg = gen_rtx_REG (QImode, j);
1877c87b03e5Sespie 
1878c87b03e5Sespie 	  /* Do sanity check for overlap between clobbers and respectively
1879c87b03e5Sespie 	     input and outputs that hasn't been handled.  Such overlap
1880c87b03e5Sespie 	     should have been detected and reported above.  */
1881c87b03e5Sespie 	  if (!clobber_conflict_found)
1882c87b03e5Sespie 	    {
1883c87b03e5Sespie 	      int opno;
1884c87b03e5Sespie 
1885c87b03e5Sespie 	      /* We test the old body (obody) contents to avoid tripping
1886c87b03e5Sespie 		 over the under-construction body.  */
1887c87b03e5Sespie 	      for (opno = 0; opno < noutputs; opno++)
1888c87b03e5Sespie 		if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
1889c87b03e5Sespie 		  internal_error ("asm clobber conflict with output operand");
1890c87b03e5Sespie 
1891c87b03e5Sespie 	      for (opno = 0; opno < ninputs - ninout; opno++)
1892c87b03e5Sespie 		if (reg_overlap_mentioned_p (clobbered_reg,
1893c87b03e5Sespie 					     ASM_OPERANDS_INPUT (obody, opno)))
1894c87b03e5Sespie 		  internal_error ("asm clobber conflict with input operand");
1895c87b03e5Sespie 	    }
1896c87b03e5Sespie 
1897c87b03e5Sespie 	  XVECEXP (body, 0, i++)
1898c87b03e5Sespie 	    = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
1899c87b03e5Sespie 	}
1900c87b03e5Sespie 
1901c87b03e5Sespie       insn = emit_insn (body);
1902c87b03e5Sespie     }
1903c87b03e5Sespie 
1904c87b03e5Sespie   /* For any outputs that needed reloading into registers, spill them
1905c87b03e5Sespie      back to where they belong.  */
1906c87b03e5Sespie   for (i = 0; i < noutputs; ++i)
1907c87b03e5Sespie     if (real_output_rtx[i])
1908c87b03e5Sespie       emit_move_insn (real_output_rtx[i], output_rtx[i]);
1909c87b03e5Sespie 
1910c87b03e5Sespie   free_temp_slots ();
1911c87b03e5Sespie }
1912c87b03e5Sespie 
1913c87b03e5Sespie /* A subroutine of expand_asm_operands.  Check that all operands have
1914c87b03e5Sespie    the same number of alternatives.  Return true if so.  */
1915c87b03e5Sespie 
1916c87b03e5Sespie static bool
check_operand_nalternatives(outputs,inputs)1917c87b03e5Sespie check_operand_nalternatives (outputs, inputs)
1918c87b03e5Sespie      tree outputs, inputs;
1919c87b03e5Sespie {
1920c87b03e5Sespie   if (outputs || inputs)
1921c87b03e5Sespie     {
1922c87b03e5Sespie       tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
1923c87b03e5Sespie       int nalternatives
1924c87b03e5Sespie 	= n_occurrences (',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
1925c87b03e5Sespie       tree next = inputs;
1926c87b03e5Sespie 
1927c87b03e5Sespie       if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
1928c87b03e5Sespie 	{
1929c87b03e5Sespie 	  error ("too many alternatives in `asm'");
1930c87b03e5Sespie 	  return false;
1931c87b03e5Sespie 	}
1932c87b03e5Sespie 
1933c87b03e5Sespie       tmp = outputs;
1934c87b03e5Sespie       while (tmp)
1935c87b03e5Sespie 	{
1936c87b03e5Sespie 	  const char *constraint
1937c87b03e5Sespie 	    = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tmp)));
1938c87b03e5Sespie 
1939c87b03e5Sespie 	  if (n_occurrences (',', constraint) != nalternatives)
1940c87b03e5Sespie 	    {
1941c87b03e5Sespie 	      error ("operand constraints for `asm' differ in number of alternatives");
1942c87b03e5Sespie 	      return false;
1943c87b03e5Sespie 	    }
1944c87b03e5Sespie 
1945c87b03e5Sespie 	  if (TREE_CHAIN (tmp))
1946c87b03e5Sespie 	    tmp = TREE_CHAIN (tmp);
1947c87b03e5Sespie 	  else
1948c87b03e5Sespie 	    tmp = next, next = 0;
1949c87b03e5Sespie 	}
1950c87b03e5Sespie     }
1951c87b03e5Sespie 
1952c87b03e5Sespie   return true;
1953c87b03e5Sespie }
1954c87b03e5Sespie 
1955c87b03e5Sespie /* A subroutine of expand_asm_operands.  Check that all operand names
1956c87b03e5Sespie    are unique.  Return true if so.  We rely on the fact that these names
1957c87b03e5Sespie    are identifiers, and so have been canonicalized by get_identifier,
1958c87b03e5Sespie    so all we need are pointer comparisons.  */
1959c87b03e5Sespie 
1960c87b03e5Sespie static bool
check_unique_operand_names(outputs,inputs)1961c87b03e5Sespie check_unique_operand_names (outputs, inputs)
1962c87b03e5Sespie      tree outputs, inputs;
1963c87b03e5Sespie {
1964c87b03e5Sespie   tree i, j;
1965c87b03e5Sespie 
1966c87b03e5Sespie   for (i = outputs; i ; i = TREE_CHAIN (i))
1967c87b03e5Sespie     {
1968c87b03e5Sespie       tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
1969c87b03e5Sespie       if (! i_name)
1970c87b03e5Sespie 	continue;
1971c87b03e5Sespie 
1972c87b03e5Sespie       for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
1973c87b03e5Sespie 	if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
1974c87b03e5Sespie 	  goto failure;
1975c87b03e5Sespie     }
1976c87b03e5Sespie 
1977c87b03e5Sespie   for (i = inputs; i ; i = TREE_CHAIN (i))
1978c87b03e5Sespie     {
1979c87b03e5Sespie       tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
1980c87b03e5Sespie       if (! i_name)
1981c87b03e5Sespie 	continue;
1982c87b03e5Sespie 
1983c87b03e5Sespie       for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
1984c87b03e5Sespie 	if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
1985c87b03e5Sespie 	  goto failure;
1986c87b03e5Sespie       for (j = outputs; j ; j = TREE_CHAIN (j))
1987c87b03e5Sespie 	if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
1988c87b03e5Sespie 	  goto failure;
1989c87b03e5Sespie     }
1990c87b03e5Sespie 
1991c87b03e5Sespie   return true;
1992c87b03e5Sespie 
1993c87b03e5Sespie  failure:
1994c87b03e5Sespie   error ("duplicate asm operand name '%s'",
1995c87b03e5Sespie 	 TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
1996c87b03e5Sespie   return false;
1997c87b03e5Sespie }
1998c87b03e5Sespie 
1999c87b03e5Sespie /* A subroutine of expand_asm_operands.  Resolve the names of the operands
2000c87b03e5Sespie    in *POUTPUTS and *PINPUTS to numbers, and replace the name expansions in
2001c87b03e5Sespie    STRING and in the constraints to those numbers.  */
2002c87b03e5Sespie 
2003c87b03e5Sespie static tree
resolve_operand_names(string,outputs,inputs,pconstraints)2004c87b03e5Sespie resolve_operand_names (string, outputs, inputs, pconstraints)
2005c87b03e5Sespie      tree string;
2006c87b03e5Sespie      tree outputs, inputs;
2007c87b03e5Sespie      const char **pconstraints;
2008c87b03e5Sespie {
2009c87b03e5Sespie   char *buffer = xstrdup (TREE_STRING_POINTER (string));
2010c87b03e5Sespie   char *p;
2011c87b03e5Sespie   tree t;
2012c87b03e5Sespie 
2013c87b03e5Sespie   /* Assume that we will not need extra space to perform the substitution.
2014c87b03e5Sespie      This because we get to remove '[' and ']', which means we cannot have
2015c87b03e5Sespie      a problem until we have more than 999 operands.  */
2016c87b03e5Sespie 
2017c87b03e5Sespie   p = buffer;
2018c87b03e5Sespie   while ((p = strchr (p, '%')) != NULL)
2019c87b03e5Sespie     {
2020c87b03e5Sespie       if (p[1] == '[')
2021c87b03e5Sespie 	p += 1;
2022c87b03e5Sespie       else if (ISALPHA (p[1]) && p[2] == '[')
2023c87b03e5Sespie 	p += 2;
2024c87b03e5Sespie       else
2025c87b03e5Sespie 	{
2026c87b03e5Sespie 	  p += 1;
2027c87b03e5Sespie 	  continue;
2028c87b03e5Sespie 	}
2029c87b03e5Sespie 
2030c87b03e5Sespie       p = resolve_operand_name_1 (p, outputs, inputs);
2031c87b03e5Sespie     }
2032c87b03e5Sespie 
2033c87b03e5Sespie   string = build_string (strlen (buffer), buffer);
2034c87b03e5Sespie   free (buffer);
2035c87b03e5Sespie 
2036c87b03e5Sespie   /* Collect output constraints here because it's convenient.
2037c87b03e5Sespie      There should be no named operands here; this is verified
2038c87b03e5Sespie      in expand_asm_operand.  */
2039c87b03e5Sespie   for (t = outputs; t ; t = TREE_CHAIN (t), pconstraints++)
2040c87b03e5Sespie     *pconstraints = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
2041c87b03e5Sespie 
2042c87b03e5Sespie   /* Substitute [<name>] in input constraint strings.  */
2043c87b03e5Sespie   for (t = inputs; t ; t = TREE_CHAIN (t), pconstraints++)
2044c87b03e5Sespie     {
2045c87b03e5Sespie       const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
2046c87b03e5Sespie       if (strchr (c, '[') == NULL)
2047c87b03e5Sespie 	*pconstraints = c;
2048c87b03e5Sespie       else
2049c87b03e5Sespie 	{
2050c87b03e5Sespie 	  p = buffer = xstrdup (c);
2051c87b03e5Sespie 	  while ((p = strchr (p, '[')) != NULL)
2052c87b03e5Sespie 	    p = resolve_operand_name_1 (p, outputs, inputs);
2053c87b03e5Sespie 
2054c87b03e5Sespie 	  *pconstraints = ggc_alloc_string (buffer, -1);
2055c87b03e5Sespie 	  free (buffer);
2056c87b03e5Sespie 	}
2057c87b03e5Sespie     }
2058c87b03e5Sespie 
2059c87b03e5Sespie   return string;
2060c87b03e5Sespie }
2061c87b03e5Sespie 
2062c87b03e5Sespie /* A subroutine of resolve_operand_names.  P points to the '[' for a
2063c87b03e5Sespie    potential named operand of the form [<name>].  In place, replace
2064c87b03e5Sespie    the name and brackets with a number.  Return a pointer to the
2065c87b03e5Sespie    balance of the string after substitution.  */
2066c87b03e5Sespie 
2067c87b03e5Sespie static char *
resolve_operand_name_1(p,outputs,inputs)2068c87b03e5Sespie resolve_operand_name_1 (p, outputs, inputs)
2069c87b03e5Sespie      char *p;
2070c87b03e5Sespie      tree outputs, inputs;
2071c87b03e5Sespie {
2072c87b03e5Sespie   char *q;
2073c87b03e5Sespie   int op;
2074c87b03e5Sespie   tree t;
2075c87b03e5Sespie   size_t len;
2076c87b03e5Sespie 
2077c87b03e5Sespie   /* Collect the operand name.  */
2078c87b03e5Sespie   q = strchr (p, ']');
2079c87b03e5Sespie   if (!q)
2080c87b03e5Sespie     {
2081c87b03e5Sespie       error ("missing close brace for named operand");
2082c87b03e5Sespie       return strchr (p, '\0');
2083c87b03e5Sespie     }
2084c87b03e5Sespie   len = q - p - 1;
2085c87b03e5Sespie 
2086c87b03e5Sespie   /* Resolve the name to a number.  */
2087c87b03e5Sespie   for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
2088c87b03e5Sespie     {
2089c87b03e5Sespie       tree name = TREE_PURPOSE (TREE_PURPOSE (t));
2090c87b03e5Sespie       if (name)
2091c87b03e5Sespie 	{
2092c87b03e5Sespie 	  const char *c = TREE_STRING_POINTER (name);
2093c87b03e5Sespie 	  if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
2094c87b03e5Sespie 	    goto found;
2095c87b03e5Sespie 	}
2096c87b03e5Sespie     }
2097c87b03e5Sespie   for (t = inputs; t ; t = TREE_CHAIN (t), op++)
2098c87b03e5Sespie     {
2099c87b03e5Sespie       tree name = TREE_PURPOSE (TREE_PURPOSE (t));
2100c87b03e5Sespie       if (name)
2101c87b03e5Sespie 	{
2102c87b03e5Sespie 	  const char *c = TREE_STRING_POINTER (name);
2103c87b03e5Sespie 	  if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
2104c87b03e5Sespie 	    goto found;
2105c87b03e5Sespie 	}
2106c87b03e5Sespie     }
2107c87b03e5Sespie 
2108c87b03e5Sespie   *q = '\0';
2109c87b03e5Sespie   error ("undefined named operand '%s'", p + 1);
2110c87b03e5Sespie   op = 0;
2111c87b03e5Sespie  found:
2112c87b03e5Sespie 
2113c87b03e5Sespie   /* Replace the name with the number.  Unfortunately, not all libraries
2114c87b03e5Sespie      get the return value of sprintf correct, so search for the end of the
2115c87b03e5Sespie      generated string by hand.  */
2116c87b03e5Sespie   sprintf (p, "%d", op);
2117c87b03e5Sespie   p = strchr (p, '\0');
2118c87b03e5Sespie 
2119c87b03e5Sespie   /* Verify the no extra buffer space assumption.  */
2120c87b03e5Sespie   if (p > q)
2121c87b03e5Sespie     abort ();
2122c87b03e5Sespie 
2123c87b03e5Sespie   /* Shift the rest of the buffer down to fill the gap.  */
2124c87b03e5Sespie   memmove (p, q + 1, strlen (q + 1) + 1);
2125c87b03e5Sespie 
2126c87b03e5Sespie   return p;
2127c87b03e5Sespie }
2128c87b03e5Sespie 
2129c87b03e5Sespie /* Generate RTL to evaluate the expression EXP
2130c87b03e5Sespie    and remember it in case this is the VALUE in a ({... VALUE; }) constr.
2131c87b03e5Sespie    Provided just for backward-compatibility.  expand_expr_stmt_value()
2132c87b03e5Sespie    should be used for new code.  */
2133c87b03e5Sespie 
2134c87b03e5Sespie void
expand_expr_stmt(exp)2135c87b03e5Sespie expand_expr_stmt (exp)
2136c87b03e5Sespie      tree exp;
2137c87b03e5Sespie {
2138c87b03e5Sespie   expand_expr_stmt_value (exp, -1, 1);
2139c87b03e5Sespie }
2140c87b03e5Sespie 
2141c87b03e5Sespie /* Generate RTL to evaluate the expression EXP.  WANT_VALUE tells
2142c87b03e5Sespie    whether to (1) save the value of the expression, (0) discard it or
2143c87b03e5Sespie    (-1) use expr_stmts_for_value to tell.  The use of -1 is
2144c87b03e5Sespie    deprecated, and retained only for backward compatibility.  */
2145c87b03e5Sespie 
2146c87b03e5Sespie void
expand_expr_stmt_value(exp,want_value,maybe_last)2147c87b03e5Sespie expand_expr_stmt_value (exp, want_value, maybe_last)
2148c87b03e5Sespie      tree exp;
2149c87b03e5Sespie      int want_value, maybe_last;
2150c87b03e5Sespie {
2151c87b03e5Sespie   rtx value;
2152c87b03e5Sespie   tree type;
2153c87b03e5Sespie 
2154c87b03e5Sespie   if (want_value == -1)
2155c87b03e5Sespie     want_value = expr_stmts_for_value != 0;
2156c87b03e5Sespie 
2157c87b03e5Sespie   /* If -W, warn about statements with no side effects,
2158c87b03e5Sespie      except for an explicit cast to void (e.g. for assert()), and
2159c87b03e5Sespie      except for last statement in ({...}) where they may be useful.  */
2160c87b03e5Sespie   if (! want_value
2161c87b03e5Sespie       && (expr_stmts_for_value == 0 || ! maybe_last)
2162c87b03e5Sespie       && exp != error_mark_node)
2163c87b03e5Sespie     {
2164c87b03e5Sespie       if (! TREE_SIDE_EFFECTS (exp))
2165c87b03e5Sespie 	{
2166c87b03e5Sespie 	  if ((extra_warnings || warn_unused_value)
2167c87b03e5Sespie 	      && !(TREE_CODE (exp) == CONVERT_EXPR
2168c87b03e5Sespie 		   && VOID_TYPE_P (TREE_TYPE (exp))))
2169c87b03e5Sespie 	    warning_with_file_and_line (emit_filename, emit_lineno,
2170c87b03e5Sespie 				        "statement with no effect");
2171c87b03e5Sespie 	}
2172c87b03e5Sespie       else if (warn_unused_value)
2173c87b03e5Sespie 	warn_if_unused_value (exp);
2174c87b03e5Sespie     }
2175c87b03e5Sespie 
2176c87b03e5Sespie   /* If EXP is of function type and we are expanding statements for
2177c87b03e5Sespie      value, convert it to pointer-to-function.  */
2178c87b03e5Sespie   if (want_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
2179c87b03e5Sespie     exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
2180c87b03e5Sespie 
2181c87b03e5Sespie   /* The call to `expand_expr' could cause last_expr_type and
2182c87b03e5Sespie      last_expr_value to get reset.  Therefore, we set last_expr_value
2183c87b03e5Sespie      and last_expr_type *after* calling expand_expr.  */
2184c87b03e5Sespie   value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
2185c87b03e5Sespie 		       VOIDmode, 0);
2186c87b03e5Sespie   type = TREE_TYPE (exp);
2187c87b03e5Sespie 
2188c87b03e5Sespie   /* If all we do is reference a volatile value in memory,
2189c87b03e5Sespie      copy it to a register to be sure it is actually touched.  */
2190c87b03e5Sespie   if (value && GET_CODE (value) == MEM && TREE_THIS_VOLATILE (exp))
2191c87b03e5Sespie     {
2192c87b03e5Sespie       if (TYPE_MODE (type) == VOIDmode)
2193c87b03e5Sespie 	;
2194c87b03e5Sespie       else if (TYPE_MODE (type) != BLKmode)
2195c87b03e5Sespie 	value = copy_to_reg (value);
2196c87b03e5Sespie       else
2197c87b03e5Sespie 	{
2198c87b03e5Sespie 	  rtx lab = gen_label_rtx ();
2199c87b03e5Sespie 
2200c87b03e5Sespie 	  /* Compare the value with itself to reference it.  */
2201c87b03e5Sespie 	  emit_cmp_and_jump_insns (value, value, EQ,
2202c87b03e5Sespie 				   expand_expr (TYPE_SIZE (type),
2203c87b03e5Sespie 						NULL_RTX, VOIDmode, 0),
2204c87b03e5Sespie 				   BLKmode, 0, lab);
2205c87b03e5Sespie 	  emit_label (lab);
2206c87b03e5Sespie 	}
2207c87b03e5Sespie     }
2208c87b03e5Sespie 
2209c87b03e5Sespie   /* If this expression is part of a ({...}) and is in memory, we may have
2210c87b03e5Sespie      to preserve temporaries.  */
2211c87b03e5Sespie   preserve_temp_slots (value);
2212c87b03e5Sespie 
2213c87b03e5Sespie   /* Free any temporaries used to evaluate this expression.  Any temporary
2214c87b03e5Sespie      used as a result of this expression will already have been preserved
2215c87b03e5Sespie      above.  */
2216c87b03e5Sespie   free_temp_slots ();
2217c87b03e5Sespie 
2218c87b03e5Sespie   if (want_value)
2219c87b03e5Sespie     {
2220c87b03e5Sespie       last_expr_value = value;
2221c87b03e5Sespie       last_expr_type = type;
2222c87b03e5Sespie     }
2223c87b03e5Sespie 
2224c87b03e5Sespie   emit_queue ();
2225c87b03e5Sespie }
2226c87b03e5Sespie 
2227c87b03e5Sespie /* Warn if EXP contains any computations whose results are not used.
2228c87b03e5Sespie    Return 1 if a warning is printed; 0 otherwise.  */
2229c87b03e5Sespie 
2230c87b03e5Sespie int
warn_if_unused_value(exp)2231c87b03e5Sespie warn_if_unused_value (exp)
2232c87b03e5Sespie      tree exp;
2233c87b03e5Sespie {
2234c87b03e5Sespie   if (TREE_USED (exp))
2235c87b03e5Sespie     return 0;
2236c87b03e5Sespie 
2237c87b03e5Sespie   /* Don't warn about void constructs.  This includes casting to void,
2238c87b03e5Sespie      void function calls, and statement expressions with a final cast
2239c87b03e5Sespie      to void.  */
2240c87b03e5Sespie   if (VOID_TYPE_P (TREE_TYPE (exp)))
2241c87b03e5Sespie     return 0;
2242c87b03e5Sespie 
2243c87b03e5Sespie   switch (TREE_CODE (exp))
2244c87b03e5Sespie     {
2245c87b03e5Sespie     case PREINCREMENT_EXPR:
2246c87b03e5Sespie     case POSTINCREMENT_EXPR:
2247c87b03e5Sespie     case PREDECREMENT_EXPR:
2248c87b03e5Sespie     case POSTDECREMENT_EXPR:
2249c87b03e5Sespie     case MODIFY_EXPR:
2250c87b03e5Sespie     case INIT_EXPR:
2251c87b03e5Sespie     case TARGET_EXPR:
2252c87b03e5Sespie     case CALL_EXPR:
2253c87b03e5Sespie     case METHOD_CALL_EXPR:
2254c87b03e5Sespie     case RTL_EXPR:
2255c87b03e5Sespie     case TRY_CATCH_EXPR:
2256c87b03e5Sespie     case WITH_CLEANUP_EXPR:
2257c87b03e5Sespie     case EXIT_EXPR:
2258c87b03e5Sespie       return 0;
2259c87b03e5Sespie 
2260c87b03e5Sespie     case BIND_EXPR:
2261c87b03e5Sespie       /* For a binding, warn if no side effect within it.  */
2262c87b03e5Sespie       return warn_if_unused_value (TREE_OPERAND (exp, 1));
2263c87b03e5Sespie 
2264c87b03e5Sespie     case SAVE_EXPR:
2265c87b03e5Sespie       return warn_if_unused_value (TREE_OPERAND (exp, 1));
2266c87b03e5Sespie 
2267c87b03e5Sespie     case TRUTH_ORIF_EXPR:
2268c87b03e5Sespie     case TRUTH_ANDIF_EXPR:
2269c87b03e5Sespie       /* In && or ||, warn if 2nd operand has no side effect.  */
2270c87b03e5Sespie       return warn_if_unused_value (TREE_OPERAND (exp, 1));
2271c87b03e5Sespie 
2272c87b03e5Sespie     case COMPOUND_EXPR:
2273c87b03e5Sespie       if (TREE_NO_UNUSED_WARNING (exp))
2274c87b03e5Sespie 	return 0;
2275c87b03e5Sespie       if (warn_if_unused_value (TREE_OPERAND (exp, 0)))
2276c87b03e5Sespie 	return 1;
2277c87b03e5Sespie       /* Let people do `(foo (), 0)' without a warning.  */
2278c87b03e5Sespie       if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
2279c87b03e5Sespie 	return 0;
2280c87b03e5Sespie       return warn_if_unused_value (TREE_OPERAND (exp, 1));
2281c87b03e5Sespie 
2282c87b03e5Sespie     case NOP_EXPR:
2283c87b03e5Sespie     case CONVERT_EXPR:
2284c87b03e5Sespie     case NON_LVALUE_EXPR:
2285c87b03e5Sespie       /* Don't warn about conversions not explicit in the user's program.  */
2286c87b03e5Sespie       if (TREE_NO_UNUSED_WARNING (exp))
2287c87b03e5Sespie 	return 0;
2288c87b03e5Sespie       /* Assignment to a cast usually results in a cast of a modify.
2289c87b03e5Sespie 	 Don't complain about that.  There can be an arbitrary number of
2290c87b03e5Sespie 	 casts before the modify, so we must loop until we find the first
2291c87b03e5Sespie 	 non-cast expression and then test to see if that is a modify.  */
2292c87b03e5Sespie       {
2293c87b03e5Sespie 	tree tem = TREE_OPERAND (exp, 0);
2294c87b03e5Sespie 
2295c87b03e5Sespie 	while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR)
2296c87b03e5Sespie 	  tem = TREE_OPERAND (tem, 0);
2297c87b03e5Sespie 
2298c87b03e5Sespie 	if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR
2299c87b03e5Sespie 	    || TREE_CODE (tem) == CALL_EXPR)
2300c87b03e5Sespie 	  return 0;
2301c87b03e5Sespie       }
2302c87b03e5Sespie       goto maybe_warn;
2303c87b03e5Sespie 
2304c87b03e5Sespie     case INDIRECT_REF:
2305c87b03e5Sespie       /* Don't warn about automatic dereferencing of references, since
2306c87b03e5Sespie 	 the user cannot control it.  */
2307c87b03e5Sespie       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
2308c87b03e5Sespie 	return warn_if_unused_value (TREE_OPERAND (exp, 0));
2309c87b03e5Sespie       /* Fall through.  */
2310c87b03e5Sespie 
2311c87b03e5Sespie     default:
2312c87b03e5Sespie       /* Referencing a volatile value is a side effect, so don't warn.  */
2313c87b03e5Sespie       if ((DECL_P (exp)
2314c87b03e5Sespie 	   || TREE_CODE_CLASS (TREE_CODE (exp)) == 'r')
2315c87b03e5Sespie 	  && TREE_THIS_VOLATILE (exp))
2316c87b03e5Sespie 	return 0;
2317c87b03e5Sespie 
2318c87b03e5Sespie       /* If this is an expression which has no operands, there is no value
2319c87b03e5Sespie 	 to be unused.  There are no such language-independent codes,
2320c87b03e5Sespie 	 but front ends may define such.  */
2321c87b03e5Sespie       if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'e'
2322c87b03e5Sespie 	  && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0)
2323c87b03e5Sespie 	return 0;
2324c87b03e5Sespie 
2325c87b03e5Sespie     maybe_warn:
2326c87b03e5Sespie       /* If this is an expression with side effects, don't warn.  */
2327c87b03e5Sespie       if (TREE_SIDE_EFFECTS (exp))
2328c87b03e5Sespie 	return 0;
2329c87b03e5Sespie 
2330c87b03e5Sespie       warning_with_file_and_line (emit_filename, emit_lineno,
2331c87b03e5Sespie 				  "value computed is not used");
2332c87b03e5Sespie       return 1;
2333c87b03e5Sespie     }
2334c87b03e5Sespie }
2335c87b03e5Sespie 
2336c87b03e5Sespie /* Clear out the memory of the last expression evaluated.  */
2337c87b03e5Sespie 
2338c87b03e5Sespie void
clear_last_expr()2339c87b03e5Sespie clear_last_expr ()
2340c87b03e5Sespie {
2341c87b03e5Sespie   last_expr_type = NULL_TREE;
2342c87b03e5Sespie   last_expr_value = NULL_RTX;
2343c87b03e5Sespie }
2344c87b03e5Sespie 
2345c87b03e5Sespie /* Begin a statement-expression, i.e., a series of statements which
2346c87b03e5Sespie    may return a value.  Return the RTL_EXPR for this statement expr.
2347c87b03e5Sespie    The caller must save that value and pass it to
2348c87b03e5Sespie    expand_end_stmt_expr.  If HAS_SCOPE is nonzero, temporaries created
2349c87b03e5Sespie    in the statement-expression are deallocated at the end of the
2350c87b03e5Sespie    expression.  */
2351c87b03e5Sespie 
2352c87b03e5Sespie tree
expand_start_stmt_expr(has_scope)2353c87b03e5Sespie expand_start_stmt_expr (has_scope)
2354c87b03e5Sespie      int has_scope;
2355c87b03e5Sespie {
2356c87b03e5Sespie   tree t;
2357c87b03e5Sespie 
2358c87b03e5Sespie   /* Make the RTL_EXPR node temporary, not momentary,
2359c87b03e5Sespie      so that rtl_expr_chain doesn't become garbage.  */
2360c87b03e5Sespie   t = make_node (RTL_EXPR);
2361c87b03e5Sespie   do_pending_stack_adjust ();
2362c87b03e5Sespie   if (has_scope)
2363c87b03e5Sespie     start_sequence_for_rtl_expr (t);
2364c87b03e5Sespie   else
2365c87b03e5Sespie     start_sequence ();
2366c87b03e5Sespie   NO_DEFER_POP;
2367c87b03e5Sespie   expr_stmts_for_value++;
2368c87b03e5Sespie   return t;
2369c87b03e5Sespie }
2370c87b03e5Sespie 
2371c87b03e5Sespie /* Restore the previous state at the end of a statement that returns a value.
2372c87b03e5Sespie    Returns a tree node representing the statement's value and the
2373c87b03e5Sespie    insns to compute the value.
2374c87b03e5Sespie 
2375c87b03e5Sespie    The nodes of that expression have been freed by now, so we cannot use them.
2376c87b03e5Sespie    But we don't want to do that anyway; the expression has already been
2377c87b03e5Sespie    evaluated and now we just want to use the value.  So generate a RTL_EXPR
2378c87b03e5Sespie    with the proper type and RTL value.
2379c87b03e5Sespie 
2380c87b03e5Sespie    If the last substatement was not an expression,
2381c87b03e5Sespie    return something with type `void'.  */
2382c87b03e5Sespie 
2383c87b03e5Sespie tree
expand_end_stmt_expr(t)2384c87b03e5Sespie expand_end_stmt_expr (t)
2385c87b03e5Sespie      tree t;
2386c87b03e5Sespie {
2387c87b03e5Sespie   OK_DEFER_POP;
2388c87b03e5Sespie 
2389c87b03e5Sespie   if (! last_expr_value || ! last_expr_type)
2390c87b03e5Sespie     {
2391c87b03e5Sespie       last_expr_value = const0_rtx;
2392c87b03e5Sespie       last_expr_type = void_type_node;
2393c87b03e5Sespie     }
2394c87b03e5Sespie   else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))
2395c87b03e5Sespie     /* Remove any possible QUEUED.  */
2396c87b03e5Sespie     last_expr_value = protect_from_queue (last_expr_value, 0);
2397c87b03e5Sespie 
2398c87b03e5Sespie   emit_queue ();
2399c87b03e5Sespie 
2400c87b03e5Sespie   TREE_TYPE (t) = last_expr_type;
2401c87b03e5Sespie   RTL_EXPR_RTL (t) = last_expr_value;
2402c87b03e5Sespie   RTL_EXPR_SEQUENCE (t) = get_insns ();
2403c87b03e5Sespie 
2404c87b03e5Sespie   rtl_expr_chain = tree_cons (NULL_TREE, t, rtl_expr_chain);
2405c87b03e5Sespie 
2406c87b03e5Sespie   end_sequence ();
2407c87b03e5Sespie 
2408c87b03e5Sespie   /* Don't consider deleting this expr or containing exprs at tree level.  */
2409c87b03e5Sespie   TREE_SIDE_EFFECTS (t) = 1;
2410c87b03e5Sespie   /* Propagate volatility of the actual RTL expr.  */
2411c87b03e5Sespie   TREE_THIS_VOLATILE (t) = volatile_refs_p (last_expr_value);
2412c87b03e5Sespie 
2413c87b03e5Sespie   clear_last_expr ();
2414c87b03e5Sespie   expr_stmts_for_value--;
2415c87b03e5Sespie 
2416c87b03e5Sespie   return t;
2417c87b03e5Sespie }
2418c87b03e5Sespie 
2419c87b03e5Sespie /* Generate RTL for the start of an if-then.  COND is the expression
2420c87b03e5Sespie    whose truth should be tested.
2421c87b03e5Sespie 
2422c87b03e5Sespie    If EXITFLAG is nonzero, this conditional is visible to
2423c87b03e5Sespie    `exit_something'.  */
2424c87b03e5Sespie 
2425c87b03e5Sespie void
expand_start_cond(cond,exitflag)2426c87b03e5Sespie expand_start_cond (cond, exitflag)
2427c87b03e5Sespie      tree cond;
2428c87b03e5Sespie      int exitflag;
2429c87b03e5Sespie {
2430c87b03e5Sespie   struct nesting *thiscond = ALLOC_NESTING ();
2431c87b03e5Sespie 
2432c87b03e5Sespie   /* Make an entry on cond_stack for the cond we are entering.  */
2433c87b03e5Sespie 
2434c87b03e5Sespie   thiscond->desc = COND_NESTING;
2435c87b03e5Sespie   thiscond->next = cond_stack;
2436c87b03e5Sespie   thiscond->all = nesting_stack;
2437c87b03e5Sespie   thiscond->depth = ++nesting_depth;
2438c87b03e5Sespie   thiscond->data.cond.next_label = gen_label_rtx ();
2439c87b03e5Sespie   /* Before we encounter an `else', we don't need a separate exit label
2440c87b03e5Sespie      unless there are supposed to be exit statements
2441c87b03e5Sespie      to exit this conditional.  */
2442c87b03e5Sespie   thiscond->exit_label = exitflag ? gen_label_rtx () : 0;
2443c87b03e5Sespie   thiscond->data.cond.endif_label = thiscond->exit_label;
2444c87b03e5Sespie   cond_stack = thiscond;
2445c87b03e5Sespie   nesting_stack = thiscond;
2446c87b03e5Sespie 
2447c87b03e5Sespie   do_jump (cond, thiscond->data.cond.next_label, NULL_RTX);
2448c87b03e5Sespie }
2449c87b03e5Sespie 
2450c87b03e5Sespie /* Generate RTL between then-clause and the elseif-clause
2451c87b03e5Sespie    of an if-then-elseif-....  */
2452c87b03e5Sespie 
2453c87b03e5Sespie void
expand_start_elseif(cond)2454c87b03e5Sespie expand_start_elseif (cond)
2455c87b03e5Sespie      tree cond;
2456c87b03e5Sespie {
2457c87b03e5Sespie   if (cond_stack->data.cond.endif_label == 0)
2458c87b03e5Sespie     cond_stack->data.cond.endif_label = gen_label_rtx ();
2459c87b03e5Sespie   emit_jump (cond_stack->data.cond.endif_label);
2460c87b03e5Sespie   emit_label (cond_stack->data.cond.next_label);
2461c87b03e5Sespie   cond_stack->data.cond.next_label = gen_label_rtx ();
2462c87b03e5Sespie   do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
2463c87b03e5Sespie }
2464c87b03e5Sespie 
2465c87b03e5Sespie /* Generate RTL between the then-clause and the else-clause
2466c87b03e5Sespie    of an if-then-else.  */
2467c87b03e5Sespie 
2468c87b03e5Sespie void
expand_start_else()2469c87b03e5Sespie expand_start_else ()
2470c87b03e5Sespie {
2471c87b03e5Sespie   if (cond_stack->data.cond.endif_label == 0)
2472c87b03e5Sespie     cond_stack->data.cond.endif_label = gen_label_rtx ();
2473c87b03e5Sespie 
2474c87b03e5Sespie   emit_jump (cond_stack->data.cond.endif_label);
2475c87b03e5Sespie   emit_label (cond_stack->data.cond.next_label);
2476c87b03e5Sespie   cond_stack->data.cond.next_label = 0;  /* No more _else or _elseif calls.  */
2477c87b03e5Sespie }
2478c87b03e5Sespie 
2479c87b03e5Sespie /* After calling expand_start_else, turn this "else" into an "else if"
2480c87b03e5Sespie    by providing another condition.  */
2481c87b03e5Sespie 
2482c87b03e5Sespie void
expand_elseif(cond)2483c87b03e5Sespie expand_elseif (cond)
2484c87b03e5Sespie      tree cond;
2485c87b03e5Sespie {
2486c87b03e5Sespie   cond_stack->data.cond.next_label = gen_label_rtx ();
2487c87b03e5Sespie   do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
2488c87b03e5Sespie }
2489c87b03e5Sespie 
2490c87b03e5Sespie /* Generate RTL for the end of an if-then.
2491c87b03e5Sespie    Pop the record for it off of cond_stack.  */
2492c87b03e5Sespie 
2493c87b03e5Sespie void
expand_end_cond()2494c87b03e5Sespie expand_end_cond ()
2495c87b03e5Sespie {
2496c87b03e5Sespie   struct nesting *thiscond = cond_stack;
2497c87b03e5Sespie 
2498c87b03e5Sespie   do_pending_stack_adjust ();
2499c87b03e5Sespie   if (thiscond->data.cond.next_label)
2500c87b03e5Sespie     emit_label (thiscond->data.cond.next_label);
2501c87b03e5Sespie   if (thiscond->data.cond.endif_label)
2502c87b03e5Sespie     emit_label (thiscond->data.cond.endif_label);
2503c87b03e5Sespie 
2504c87b03e5Sespie   POPSTACK (cond_stack);
2505c87b03e5Sespie   clear_last_expr ();
2506c87b03e5Sespie }
2507c87b03e5Sespie 
2508c87b03e5Sespie /* Generate RTL for the start of a loop.  EXIT_FLAG is nonzero if this
2509c87b03e5Sespie    loop should be exited by `exit_something'.  This is a loop for which
2510c87b03e5Sespie    `expand_continue' will jump to the top of the loop.
2511c87b03e5Sespie 
2512c87b03e5Sespie    Make an entry on loop_stack to record the labels associated with
2513c87b03e5Sespie    this loop.  */
2514c87b03e5Sespie 
2515c87b03e5Sespie struct nesting *
expand_start_loop(exit_flag)2516c87b03e5Sespie expand_start_loop (exit_flag)
2517c87b03e5Sespie      int exit_flag;
2518c87b03e5Sespie {
2519c87b03e5Sespie   struct nesting *thisloop = ALLOC_NESTING ();
2520c87b03e5Sespie 
2521c87b03e5Sespie   /* Make an entry on loop_stack for the loop we are entering.  */
2522c87b03e5Sespie 
2523c87b03e5Sespie   thisloop->desc = LOOP_NESTING;
2524c87b03e5Sespie   thisloop->next = loop_stack;
2525c87b03e5Sespie   thisloop->all = nesting_stack;
2526c87b03e5Sespie   thisloop->depth = ++nesting_depth;
2527c87b03e5Sespie   thisloop->data.loop.start_label = gen_label_rtx ();
2528c87b03e5Sespie   thisloop->data.loop.end_label = gen_label_rtx ();
2529c87b03e5Sespie   thisloop->data.loop.alt_end_label = 0;
2530c87b03e5Sespie   thisloop->data.loop.continue_label = thisloop->data.loop.start_label;
2531c87b03e5Sespie   thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0;
2532c87b03e5Sespie   loop_stack = thisloop;
2533c87b03e5Sespie   nesting_stack = thisloop;
2534c87b03e5Sespie 
2535c87b03e5Sespie   do_pending_stack_adjust ();
2536c87b03e5Sespie   emit_queue ();
2537c87b03e5Sespie   emit_note (NULL, NOTE_INSN_LOOP_BEG);
2538c87b03e5Sespie   emit_label (thisloop->data.loop.start_label);
2539c87b03e5Sespie 
2540c87b03e5Sespie   return thisloop;
2541c87b03e5Sespie }
2542c87b03e5Sespie 
2543c87b03e5Sespie /* Like expand_start_loop but for a loop where the continuation point
2544c87b03e5Sespie    (for expand_continue_loop) will be specified explicitly.  */
2545c87b03e5Sespie 
2546c87b03e5Sespie struct nesting *
expand_start_loop_continue_elsewhere(exit_flag)2547c87b03e5Sespie expand_start_loop_continue_elsewhere (exit_flag)
2548c87b03e5Sespie      int exit_flag;
2549c87b03e5Sespie {
2550c87b03e5Sespie   struct nesting *thisloop = expand_start_loop (exit_flag);
2551c87b03e5Sespie   loop_stack->data.loop.continue_label = gen_label_rtx ();
2552c87b03e5Sespie   return thisloop;
2553c87b03e5Sespie }
2554c87b03e5Sespie 
2555c87b03e5Sespie /* Begin a null, aka do { } while (0) "loop".  But since the contents
2556c87b03e5Sespie    of said loop can still contain a break, we must frob the loop nest.  */
2557c87b03e5Sespie 
2558c87b03e5Sespie struct nesting *
expand_start_null_loop()2559c87b03e5Sespie expand_start_null_loop ()
2560c87b03e5Sespie {
2561c87b03e5Sespie   struct nesting *thisloop = ALLOC_NESTING ();
2562c87b03e5Sespie 
2563c87b03e5Sespie   /* Make an entry on loop_stack for the loop we are entering.  */
2564c87b03e5Sespie 
2565c87b03e5Sespie   thisloop->desc = LOOP_NESTING;
2566c87b03e5Sespie   thisloop->next = loop_stack;
2567c87b03e5Sespie   thisloop->all = nesting_stack;
2568c87b03e5Sespie   thisloop->depth = ++nesting_depth;
2569c87b03e5Sespie   thisloop->data.loop.start_label = emit_note (NULL, NOTE_INSN_DELETED);
2570c87b03e5Sespie   thisloop->data.loop.end_label = gen_label_rtx ();
2571c87b03e5Sespie   thisloop->data.loop.alt_end_label = NULL_RTX;
2572c87b03e5Sespie   thisloop->data.loop.continue_label = thisloop->data.loop.end_label;
2573c87b03e5Sespie   thisloop->exit_label = thisloop->data.loop.end_label;
2574c87b03e5Sespie   loop_stack = thisloop;
2575c87b03e5Sespie   nesting_stack = thisloop;
2576c87b03e5Sespie 
2577c87b03e5Sespie   return thisloop;
2578c87b03e5Sespie }
2579c87b03e5Sespie 
2580c87b03e5Sespie /* Specify the continuation point for a loop started with
2581c87b03e5Sespie    expand_start_loop_continue_elsewhere.
2582c87b03e5Sespie    Use this at the point in the code to which a continue statement
2583c87b03e5Sespie    should jump.  */
2584c87b03e5Sespie 
2585c87b03e5Sespie void
expand_loop_continue_here()2586c87b03e5Sespie expand_loop_continue_here ()
2587c87b03e5Sespie {
2588c87b03e5Sespie   do_pending_stack_adjust ();
2589c87b03e5Sespie   emit_note (NULL, NOTE_INSN_LOOP_CONT);
2590c87b03e5Sespie   emit_label (loop_stack->data.loop.continue_label);
2591c87b03e5Sespie }
2592c87b03e5Sespie 
2593c87b03e5Sespie /* Finish a loop.  Generate a jump back to the top and the loop-exit label.
2594c87b03e5Sespie    Pop the block off of loop_stack.  */
2595c87b03e5Sespie 
2596c87b03e5Sespie void
expand_end_loop()2597c87b03e5Sespie expand_end_loop ()
2598c87b03e5Sespie {
2599c87b03e5Sespie   rtx start_label = loop_stack->data.loop.start_label;
2600c87b03e5Sespie   rtx etc_note;
2601c87b03e5Sespie   int eh_regions, debug_blocks;
2602c87b03e5Sespie 
2603c87b03e5Sespie   /* Mark the continue-point at the top of the loop if none elsewhere.  */
2604c87b03e5Sespie   if (start_label == loop_stack->data.loop.continue_label)
2605c87b03e5Sespie     emit_note_before (NOTE_INSN_LOOP_CONT, start_label);
2606c87b03e5Sespie 
2607c87b03e5Sespie   do_pending_stack_adjust ();
2608c87b03e5Sespie 
2609c87b03e5Sespie   /* If the loop starts with a loop exit, roll that to the end where
2610c87b03e5Sespie      it will optimize together with the jump back.
2611c87b03e5Sespie 
2612c87b03e5Sespie      If the loop presently looks like this (in pseudo-C):
2613c87b03e5Sespie 
2614c87b03e5Sespie 	LOOP_BEG
2615c87b03e5Sespie 	start_label:
2616c87b03e5Sespie 	  if (test) goto end_label;
2617c87b03e5Sespie 	LOOP_END_TOP_COND
2618c87b03e5Sespie 	  body;
2619c87b03e5Sespie 	  goto start_label;
2620c87b03e5Sespie 	end_label:
2621c87b03e5Sespie 
2622c87b03e5Sespie      transform it to look like:
2623c87b03e5Sespie 
2624c87b03e5Sespie 	LOOP_BEG
2625c87b03e5Sespie 	  goto start_label;
2626c87b03e5Sespie 	top_label:
2627c87b03e5Sespie 	  body;
2628c87b03e5Sespie 	start_label:
2629c87b03e5Sespie 	  if (test) goto end_label;
2630c87b03e5Sespie 	  goto top_label;
2631c87b03e5Sespie 	end_label:
2632c87b03e5Sespie 
2633c87b03e5Sespie      We rely on the presence of NOTE_INSN_LOOP_END_TOP_COND to mark
2634c87b03e5Sespie      the end of the entry condtional.  Without this, our lexical scan
2635c87b03e5Sespie      can't tell the difference between an entry conditional and a
2636c87b03e5Sespie      body conditional that exits the loop.  Mistaking the two means
2637c87b03e5Sespie      that we can misplace the NOTE_INSN_LOOP_CONT note, which can
2638c87b03e5Sespie      screw up loop unrolling.
2639c87b03e5Sespie 
2640c87b03e5Sespie      Things will be oh so much better when loop optimization is done
2641c87b03e5Sespie      off of a proper control flow graph...  */
2642c87b03e5Sespie 
2643c87b03e5Sespie   /* Scan insns from the top of the loop looking for the END_TOP_COND note.  */
2644c87b03e5Sespie 
2645c87b03e5Sespie   eh_regions = debug_blocks = 0;
2646c87b03e5Sespie   for (etc_note = start_label; etc_note ; etc_note = NEXT_INSN (etc_note))
2647c87b03e5Sespie     if (GET_CODE (etc_note) == NOTE)
2648c87b03e5Sespie       {
2649c87b03e5Sespie 	if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_END_TOP_COND)
2650c87b03e5Sespie 	  break;
2651c87b03e5Sespie 
2652c87b03e5Sespie 	/* We must not walk into a nested loop.  */
2653c87b03e5Sespie 	else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_BEG)
2654c87b03e5Sespie 	  {
2655c87b03e5Sespie 	    etc_note = NULL_RTX;
2656c87b03e5Sespie 	    break;
2657c87b03e5Sespie 	  }
2658c87b03e5Sespie 
2659c87b03e5Sespie 	/* At the same time, scan for EH region notes, as we don't want
2660c87b03e5Sespie 	   to scrog region nesting.  This shouldn't happen, but...  */
2661c87b03e5Sespie 	else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_BEG)
2662c87b03e5Sespie 	  eh_regions++;
2663c87b03e5Sespie 	else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_END)
2664c87b03e5Sespie 	  {
2665c87b03e5Sespie 	    if (--eh_regions < 0)
2666c87b03e5Sespie 	      /* We've come to the end of an EH region, but never saw the
2667c87b03e5Sespie 		 beginning of that region.  That means that an EH region
2668c87b03e5Sespie 		 begins before the top of the loop, and ends in the middle
2669c87b03e5Sespie 		 of it.  The existence of such a situation violates a basic
2670c87b03e5Sespie 		 assumption in this code, since that would imply that even
2671c87b03e5Sespie 		 when EH_REGIONS is zero, we might move code out of an
2672c87b03e5Sespie 		 exception region.  */
2673c87b03e5Sespie 	      abort ();
2674c87b03e5Sespie 	  }
2675c87b03e5Sespie 
2676c87b03e5Sespie 	/* Likewise for debug scopes.  In this case we'll either (1) move
2677c87b03e5Sespie 	   all of the notes if they are properly nested or (2) leave the
2678c87b03e5Sespie 	   notes alone and only rotate the loop at high optimization
2679c87b03e5Sespie 	   levels when we expect to scrog debug info.  */
2680c87b03e5Sespie 	else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_BEG)
2681c87b03e5Sespie 	  debug_blocks++;
2682c87b03e5Sespie 	else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_END)
2683c87b03e5Sespie 	  debug_blocks--;
2684c87b03e5Sespie       }
2685c87b03e5Sespie 
2686c87b03e5Sespie   if (etc_note
2687c87b03e5Sespie       && optimize
2688c87b03e5Sespie       && eh_regions == 0
2689c87b03e5Sespie       && (debug_blocks == 0 || optimize >= 2)
2690c87b03e5Sespie       && NEXT_INSN (etc_note) != NULL_RTX
2691c87b03e5Sespie       && ! any_condjump_p (get_last_insn ()))
2692c87b03e5Sespie     {
2693c87b03e5Sespie       /* We found one.  Move everything from START to ETC to the end
2694c87b03e5Sespie 	 of the loop, and add a jump from the top of the loop.  */
2695c87b03e5Sespie       rtx top_label = gen_label_rtx ();
2696c87b03e5Sespie       rtx start_move = start_label;
2697c87b03e5Sespie 
2698c87b03e5Sespie       /* If the start label is preceded by a NOTE_INSN_LOOP_CONT note,
2699c87b03e5Sespie 	 then we want to move this note also.  */
2700c87b03e5Sespie       if (GET_CODE (PREV_INSN (start_move)) == NOTE
2701c87b03e5Sespie 	  && NOTE_LINE_NUMBER (PREV_INSN (start_move)) == NOTE_INSN_LOOP_CONT)
2702c87b03e5Sespie 	start_move = PREV_INSN (start_move);
2703c87b03e5Sespie 
2704c87b03e5Sespie       emit_label_before (top_label, start_move);
2705c87b03e5Sespie 
2706c87b03e5Sespie       /* Actually move the insns.  If the debug scopes are nested, we
2707c87b03e5Sespie 	 can move everything at once.  Otherwise we have to move them
2708c87b03e5Sespie 	 one by one and squeeze out the block notes.  */
2709c87b03e5Sespie       if (debug_blocks == 0)
2710c87b03e5Sespie 	reorder_insns (start_move, etc_note, get_last_insn ());
2711c87b03e5Sespie       else
2712c87b03e5Sespie 	{
2713c87b03e5Sespie 	  rtx insn, next_insn;
2714c87b03e5Sespie 	  for (insn = start_move; insn; insn = next_insn)
2715c87b03e5Sespie 	    {
2716c87b03e5Sespie 	      /* Figure out which insn comes after this one.  We have
2717c87b03e5Sespie 		 to do this before we move INSN.  */
2718c87b03e5Sespie 	      next_insn = (insn == etc_note ? NULL : NEXT_INSN (insn));
2719c87b03e5Sespie 
2720c87b03e5Sespie 	      if (GET_CODE (insn) == NOTE
2721c87b03e5Sespie 		  && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
2722c87b03e5Sespie 		      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
2723c87b03e5Sespie 		continue;
2724c87b03e5Sespie 
2725c87b03e5Sespie 	      reorder_insns (insn, insn, get_last_insn ());
2726c87b03e5Sespie 	    }
2727c87b03e5Sespie 	}
2728c87b03e5Sespie 
2729c87b03e5Sespie       /* Add the jump from the top of the loop.  */
2730c87b03e5Sespie       emit_jump_insn_before (gen_jump (start_label), top_label);
2731c87b03e5Sespie       emit_barrier_before (top_label);
2732c87b03e5Sespie       start_label = top_label;
2733c87b03e5Sespie     }
2734c87b03e5Sespie 
2735c87b03e5Sespie   emit_jump (start_label);
2736c87b03e5Sespie   emit_note (NULL, NOTE_INSN_LOOP_END);
2737c87b03e5Sespie   emit_label (loop_stack->data.loop.end_label);
2738c87b03e5Sespie 
2739c87b03e5Sespie   POPSTACK (loop_stack);
2740c87b03e5Sespie 
2741c87b03e5Sespie   clear_last_expr ();
2742c87b03e5Sespie }
2743c87b03e5Sespie 
2744c87b03e5Sespie /* Finish a null loop, aka do { } while (0).  */
2745c87b03e5Sespie 
2746c87b03e5Sespie void
expand_end_null_loop()2747c87b03e5Sespie expand_end_null_loop ()
2748c87b03e5Sespie {
2749c87b03e5Sespie   do_pending_stack_adjust ();
2750c87b03e5Sespie   emit_label (loop_stack->data.loop.end_label);
2751c87b03e5Sespie 
2752c87b03e5Sespie   POPSTACK (loop_stack);
2753c87b03e5Sespie 
2754c87b03e5Sespie   clear_last_expr ();
2755c87b03e5Sespie }
2756c87b03e5Sespie 
2757c87b03e5Sespie /* Generate a jump to the current loop's continue-point.
2758c87b03e5Sespie    This is usually the top of the loop, but may be specified
2759c87b03e5Sespie    explicitly elsewhere.  If not currently inside a loop,
2760c87b03e5Sespie    return 0 and do nothing; caller will print an error message.  */
2761c87b03e5Sespie 
2762c87b03e5Sespie int
expand_continue_loop(whichloop)2763c87b03e5Sespie expand_continue_loop (whichloop)
2764c87b03e5Sespie      struct nesting *whichloop;
2765c87b03e5Sespie {
2766c87b03e5Sespie   /* Emit information for branch prediction.  */
2767c87b03e5Sespie   rtx note;
2768c87b03e5Sespie 
2769c87b03e5Sespie   if (flag_guess_branch_prob)
2770c87b03e5Sespie     {
2771c87b03e5Sespie       note = emit_note (NULL, NOTE_INSN_PREDICTION);
2772c87b03e5Sespie       NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN);
2773c87b03e5Sespie     }
2774c87b03e5Sespie   clear_last_expr ();
2775c87b03e5Sespie   if (whichloop == 0)
2776c87b03e5Sespie     whichloop = loop_stack;
2777c87b03e5Sespie   if (whichloop == 0)
2778c87b03e5Sespie     return 0;
2779c87b03e5Sespie   expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label,
2780c87b03e5Sespie 			NULL_RTX);
2781c87b03e5Sespie   return 1;
2782c87b03e5Sespie }
2783c87b03e5Sespie 
2784c87b03e5Sespie /* Generate a jump to exit the current loop.  If not currently inside a loop,
2785c87b03e5Sespie    return 0 and do nothing; caller will print an error message.  */
2786c87b03e5Sespie 
2787c87b03e5Sespie int
expand_exit_loop(whichloop)2788c87b03e5Sespie expand_exit_loop (whichloop)
2789c87b03e5Sespie      struct nesting *whichloop;
2790c87b03e5Sespie {
2791c87b03e5Sespie   clear_last_expr ();
2792c87b03e5Sespie   if (whichloop == 0)
2793c87b03e5Sespie     whichloop = loop_stack;
2794c87b03e5Sespie   if (whichloop == 0)
2795c87b03e5Sespie     return 0;
2796c87b03e5Sespie   expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label, NULL_RTX);
2797c87b03e5Sespie   return 1;
2798c87b03e5Sespie }
2799c87b03e5Sespie 
2800c87b03e5Sespie /* Generate a conditional jump to exit the current loop if COND
2801c87b03e5Sespie    evaluates to zero.  If not currently inside a loop,
2802c87b03e5Sespie    return 0 and do nothing; caller will print an error message.  */
2803c87b03e5Sespie 
2804c87b03e5Sespie int
expand_exit_loop_if_false(whichloop,cond)2805c87b03e5Sespie expand_exit_loop_if_false (whichloop, cond)
2806c87b03e5Sespie      struct nesting *whichloop;
2807c87b03e5Sespie      tree cond;
2808c87b03e5Sespie {
2809c87b03e5Sespie   rtx label = gen_label_rtx ();
2810c87b03e5Sespie   rtx last_insn;
2811c87b03e5Sespie   clear_last_expr ();
2812c87b03e5Sespie 
2813c87b03e5Sespie   if (whichloop == 0)
2814c87b03e5Sespie     whichloop = loop_stack;
2815c87b03e5Sespie   if (whichloop == 0)
2816c87b03e5Sespie     return 0;
2817c87b03e5Sespie   /* In order to handle fixups, we actually create a conditional jump
2818c87b03e5Sespie      around an unconditional branch to exit the loop.  If fixups are
2819c87b03e5Sespie      necessary, they go before the unconditional branch.  */
2820c87b03e5Sespie 
2821c87b03e5Sespie   do_jump (cond, NULL_RTX, label);
2822c87b03e5Sespie   last_insn = get_last_insn ();
2823c87b03e5Sespie   if (GET_CODE (last_insn) == CODE_LABEL)
2824c87b03e5Sespie     whichloop->data.loop.alt_end_label = last_insn;
2825c87b03e5Sespie   expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label,
2826c87b03e5Sespie 			NULL_RTX);
2827c87b03e5Sespie   emit_label (label);
2828c87b03e5Sespie 
2829c87b03e5Sespie   return 1;
2830c87b03e5Sespie }
2831c87b03e5Sespie 
2832c87b03e5Sespie /* Like expand_exit_loop_if_false except also emit a note marking
2833c87b03e5Sespie    the end of the conditional.  Should only be used immediately
2834c87b03e5Sespie    after expand_loop_start.  */
2835c87b03e5Sespie 
2836c87b03e5Sespie int
expand_exit_loop_top_cond(whichloop,cond)2837c87b03e5Sespie expand_exit_loop_top_cond (whichloop, cond)
2838c87b03e5Sespie      struct nesting *whichloop;
2839c87b03e5Sespie      tree cond;
2840c87b03e5Sespie {
2841c87b03e5Sespie   if (! expand_exit_loop_if_false (whichloop, cond))
2842c87b03e5Sespie     return 0;
2843c87b03e5Sespie 
2844c87b03e5Sespie   emit_note (NULL, NOTE_INSN_LOOP_END_TOP_COND);
2845c87b03e5Sespie   return 1;
2846c87b03e5Sespie }
2847c87b03e5Sespie 
2848c87b03e5Sespie /* Return nonzero if the loop nest is empty.  Else return zero.  */
2849c87b03e5Sespie 
2850c87b03e5Sespie int
stmt_loop_nest_empty()2851c87b03e5Sespie stmt_loop_nest_empty ()
2852c87b03e5Sespie {
2853c87b03e5Sespie   /* cfun->stmt can be NULL if we are building a call to get the
2854c87b03e5Sespie      EH context for a setjmp/longjmp EH target and the current
2855c87b03e5Sespie      function was a deferred inline function.  */
2856c87b03e5Sespie   return (cfun->stmt == NULL || loop_stack == NULL);
2857c87b03e5Sespie }
2858c87b03e5Sespie 
2859c87b03e5Sespie /* Return nonzero if we should preserve sub-expressions as separate
2860c87b03e5Sespie    pseudos.  We never do so if we aren't optimizing.  We always do so
2861c87b03e5Sespie    if -fexpensive-optimizations.
2862c87b03e5Sespie 
2863c87b03e5Sespie    Otherwise, we only do so if we are in the "early" part of a loop.  I.e.,
2864c87b03e5Sespie    the loop may still be a small one.  */
2865c87b03e5Sespie 
2866c87b03e5Sespie int
preserve_subexpressions_p()2867c87b03e5Sespie preserve_subexpressions_p ()
2868c87b03e5Sespie {
2869c87b03e5Sespie   rtx insn;
2870c87b03e5Sespie 
2871c87b03e5Sespie   if (flag_expensive_optimizations)
2872c87b03e5Sespie     return 1;
2873c87b03e5Sespie 
2874c87b03e5Sespie   if (optimize == 0 || cfun == 0 || cfun->stmt == 0 || loop_stack == 0)
2875c87b03e5Sespie     return 0;
2876c87b03e5Sespie 
2877c87b03e5Sespie   insn = get_last_insn_anywhere ();
2878c87b03e5Sespie 
2879c87b03e5Sespie   return (insn
2880c87b03e5Sespie 	  && (INSN_UID (insn) - INSN_UID (loop_stack->data.loop.start_label)
2881c87b03e5Sespie 	      < n_non_fixed_regs * 3));
2882c87b03e5Sespie 
2883c87b03e5Sespie }
2884c87b03e5Sespie 
2885c87b03e5Sespie /* Generate a jump to exit the current loop, conditional, binding contour
2886c87b03e5Sespie    or case statement.  Not all such constructs are visible to this function,
2887c87b03e5Sespie    only those started with EXIT_FLAG nonzero.  Individual languages use
2888c87b03e5Sespie    the EXIT_FLAG parameter to control which kinds of constructs you can
2889c87b03e5Sespie    exit this way.
2890c87b03e5Sespie 
2891c87b03e5Sespie    If not currently inside anything that can be exited,
2892c87b03e5Sespie    return 0 and do nothing; caller will print an error message.  */
2893c87b03e5Sespie 
2894c87b03e5Sespie int
expand_exit_something()2895c87b03e5Sespie expand_exit_something ()
2896c87b03e5Sespie {
2897c87b03e5Sespie   struct nesting *n;
2898c87b03e5Sespie   clear_last_expr ();
2899c87b03e5Sespie   for (n = nesting_stack; n; n = n->all)
2900c87b03e5Sespie     if (n->exit_label != 0)
2901c87b03e5Sespie       {
2902c87b03e5Sespie 	expand_goto_internal (NULL_TREE, n->exit_label, NULL_RTX);
2903c87b03e5Sespie 	return 1;
2904c87b03e5Sespie       }
2905c87b03e5Sespie 
2906c87b03e5Sespie   return 0;
2907c87b03e5Sespie }
2908c87b03e5Sespie 
2909c87b03e5Sespie /* Generate RTL to return from the current function, with no value.
2910c87b03e5Sespie    (That is, we do not do anything about returning any value.)  */
2911c87b03e5Sespie 
2912c87b03e5Sespie void
expand_null_return()2913c87b03e5Sespie expand_null_return ()
2914c87b03e5Sespie {
2915c87b03e5Sespie   rtx last_insn;
2916c87b03e5Sespie 
2917c87b03e5Sespie   last_insn = get_last_insn ();
2918c87b03e5Sespie 
2919c87b03e5Sespie   /* If this function was declared to return a value, but we
2920c87b03e5Sespie      didn't, clobber the return registers so that they are not
2921c87b03e5Sespie      propagated live to the rest of the function.  */
2922c87b03e5Sespie   clobber_return_register ();
2923c87b03e5Sespie 
2924c87b03e5Sespie   expand_null_return_1 (last_insn);
2925c87b03e5Sespie }
2926c87b03e5Sespie 
2927c87b03e5Sespie /* Try to guess whether the value of return means error code.  */
2928c87b03e5Sespie static enum br_predictor
return_prediction(val)2929c87b03e5Sespie return_prediction (val)
2930c87b03e5Sespie      rtx val;
2931c87b03e5Sespie {
2932c87b03e5Sespie   /* Different heuristics for pointers and scalars.  */
2933c87b03e5Sespie   if (POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
2934c87b03e5Sespie     {
2935c87b03e5Sespie       /* NULL is usually not returned.  */
2936c87b03e5Sespie       if (val == const0_rtx)
2937c87b03e5Sespie 	return PRED_NULL_RETURN;
2938c87b03e5Sespie     }
2939c87b03e5Sespie   else
2940c87b03e5Sespie     {
2941c87b03e5Sespie       /* Negative return values are often used to indicate
2942c87b03e5Sespie          errors.  */
2943c87b03e5Sespie       if (GET_CODE (val) == CONST_INT
2944c87b03e5Sespie 	  && INTVAL (val) < 0)
2945c87b03e5Sespie 	return PRED_NEGATIVE_RETURN;
2946c87b03e5Sespie       /* Constant return values are also usually erors,
2947c87b03e5Sespie          zero/one often mean booleans so exclude them from the
2948c87b03e5Sespie 	 heuristics.  */
2949c87b03e5Sespie       if (CONSTANT_P (val)
2950c87b03e5Sespie 	  && (val != const0_rtx && val != const1_rtx))
2951c87b03e5Sespie 	return PRED_CONST_RETURN;
2952c87b03e5Sespie     }
2953c87b03e5Sespie   return PRED_NO_PREDICTION;
2954c87b03e5Sespie }
2955c87b03e5Sespie 
2956c87b03e5Sespie /* Generate RTL to return from the current function, with value VAL.  */
2957c87b03e5Sespie 
2958c87b03e5Sespie static void
expand_value_return(val)2959c87b03e5Sespie expand_value_return (val)
2960c87b03e5Sespie      rtx val;
2961c87b03e5Sespie {
2962c87b03e5Sespie   rtx last_insn;
2963c87b03e5Sespie   rtx return_reg;
2964c87b03e5Sespie   enum br_predictor pred;
2965c87b03e5Sespie 
2966c87b03e5Sespie   if (flag_guess_branch_prob
2967c87b03e5Sespie       && (pred = return_prediction (val)) != PRED_NO_PREDICTION)
2968c87b03e5Sespie     {
2969c87b03e5Sespie       /* Emit information for branch prediction.  */
2970c87b03e5Sespie       rtx note;
2971c87b03e5Sespie 
2972c87b03e5Sespie       note = emit_note (NULL, NOTE_INSN_PREDICTION);
2973c87b03e5Sespie 
2974c87b03e5Sespie       NOTE_PREDICTION (note) = NOTE_PREDICT (pred, NOT_TAKEN);
2975c87b03e5Sespie 
2976c87b03e5Sespie     }
2977c87b03e5Sespie 
2978c87b03e5Sespie   last_insn = get_last_insn ();
2979c87b03e5Sespie   return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
2980c87b03e5Sespie 
2981c87b03e5Sespie   /* Copy the value to the return location
2982c87b03e5Sespie      unless it's already there.  */
2983c87b03e5Sespie 
2984c87b03e5Sespie   if (return_reg != val)
2985c87b03e5Sespie     {
2986c87b03e5Sespie       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
2987c87b03e5Sespie #ifdef PROMOTE_FUNCTION_RETURN
2988c87b03e5Sespie       int unsignedp = TREE_UNSIGNED (type);
2989c87b03e5Sespie       enum machine_mode old_mode
2990c87b03e5Sespie 	= DECL_MODE (DECL_RESULT (current_function_decl));
2991c87b03e5Sespie       enum machine_mode mode
2992c87b03e5Sespie 	= promote_mode (type, old_mode, &unsignedp, 1);
2993c87b03e5Sespie 
2994c87b03e5Sespie       if (mode != old_mode)
2995c87b03e5Sespie 	val = convert_modes (mode, old_mode, val, unsignedp);
2996c87b03e5Sespie #endif
2997c87b03e5Sespie       if (GET_CODE (return_reg) == PARALLEL)
2998c87b03e5Sespie 	emit_group_load (return_reg, val, int_size_in_bytes (type));
2999c87b03e5Sespie       else
3000c87b03e5Sespie 	emit_move_insn (return_reg, val);
3001c87b03e5Sespie     }
3002c87b03e5Sespie 
3003c87b03e5Sespie   expand_null_return_1 (last_insn);
3004c87b03e5Sespie }
3005c87b03e5Sespie 
3006c87b03e5Sespie /* Output a return with no value.  If LAST_INSN is nonzero,
3007c87b03e5Sespie    pretend that the return takes place after LAST_INSN.  */
3008c87b03e5Sespie 
3009c87b03e5Sespie static void
expand_null_return_1(last_insn)3010c87b03e5Sespie expand_null_return_1 (last_insn)
3011c87b03e5Sespie      rtx last_insn;
3012c87b03e5Sespie {
3013c87b03e5Sespie   rtx end_label = cleanup_label ? cleanup_label : return_label;
3014c87b03e5Sespie 
3015c87b03e5Sespie   clear_pending_stack_adjust ();
3016c87b03e5Sespie   do_pending_stack_adjust ();
3017c87b03e5Sespie   clear_last_expr ();
3018c87b03e5Sespie 
3019c87b03e5Sespie   if (end_label == 0)
3020c87b03e5Sespie      end_label = return_label = gen_label_rtx ();
3021c87b03e5Sespie   expand_goto_internal (NULL_TREE, end_label, last_insn);
3022c87b03e5Sespie }
3023c87b03e5Sespie 
3024c87b03e5Sespie /* Generate RTL to evaluate the expression RETVAL and return it
3025c87b03e5Sespie    from the current function.  */
3026c87b03e5Sespie 
3027c87b03e5Sespie void
expand_return(retval)3028c87b03e5Sespie expand_return (retval)
3029c87b03e5Sespie      tree retval;
3030c87b03e5Sespie {
3031c87b03e5Sespie   /* If there are any cleanups to be performed, then they will
3032c87b03e5Sespie      be inserted following LAST_INSN.  It is desirable
3033c87b03e5Sespie      that the last_insn, for such purposes, should be the
3034c87b03e5Sespie      last insn before computing the return value.  Otherwise, cleanups
3035c87b03e5Sespie      which call functions can clobber the return value.  */
3036c87b03e5Sespie   /* ??? rms: I think that is erroneous, because in C++ it would
3037c87b03e5Sespie      run destructors on variables that might be used in the subsequent
3038c87b03e5Sespie      computation of the return value.  */
3039c87b03e5Sespie   rtx last_insn = 0;
3040c87b03e5Sespie   rtx result_rtl;
3041c87b03e5Sespie   rtx val = 0;
3042c87b03e5Sespie   tree retval_rhs;
3043c87b03e5Sespie 
3044c87b03e5Sespie   /* If function wants no value, give it none.  */
3045c87b03e5Sespie   if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
3046c87b03e5Sespie     {
3047c87b03e5Sespie       expand_expr (retval, NULL_RTX, VOIDmode, 0);
3048c87b03e5Sespie       emit_queue ();
3049c87b03e5Sespie       expand_null_return ();
3050c87b03e5Sespie       return;
3051c87b03e5Sespie     }
3052c87b03e5Sespie 
3053c87b03e5Sespie   if (retval == error_mark_node)
3054c87b03e5Sespie     {
3055c87b03e5Sespie       /* Treat this like a return of no value from a function that
3056c87b03e5Sespie 	 returns a value.  */
3057c87b03e5Sespie       expand_null_return ();
3058c87b03e5Sespie       return;
3059c87b03e5Sespie     }
3060c87b03e5Sespie   else if (TREE_CODE (retval) == RESULT_DECL)
3061c87b03e5Sespie     retval_rhs = retval;
3062c87b03e5Sespie   else if ((TREE_CODE (retval) == MODIFY_EXPR || TREE_CODE (retval) == INIT_EXPR)
3063c87b03e5Sespie 	   && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
3064c87b03e5Sespie     retval_rhs = TREE_OPERAND (retval, 1);
3065c87b03e5Sespie   else if (VOID_TYPE_P (TREE_TYPE (retval)))
3066c87b03e5Sespie     /* Recognize tail-recursive call to void function.  */
3067c87b03e5Sespie     retval_rhs = retval;
3068c87b03e5Sespie   else
3069c87b03e5Sespie     retval_rhs = NULL_TREE;
3070c87b03e5Sespie 
3071c87b03e5Sespie   last_insn = get_last_insn ();
3072c87b03e5Sespie 
3073c87b03e5Sespie   /* Distribute return down conditional expr if either of the sides
3074c87b03e5Sespie      may involve tail recursion (see test below).  This enhances the number
3075c87b03e5Sespie      of tail recursions we see.  Don't do this always since it can produce
3076c87b03e5Sespie      sub-optimal code in some cases and we distribute assignments into
3077c87b03e5Sespie      conditional expressions when it would help.  */
3078c87b03e5Sespie 
3079c87b03e5Sespie   if (optimize && retval_rhs != 0
3080c87b03e5Sespie       && frame_offset == 0
3081c87b03e5Sespie       && TREE_CODE (retval_rhs) == COND_EXPR
3082c87b03e5Sespie       && (TREE_CODE (TREE_OPERAND (retval_rhs, 1)) == CALL_EXPR
3083c87b03e5Sespie 	  || TREE_CODE (TREE_OPERAND (retval_rhs, 2)) == CALL_EXPR))
3084c87b03e5Sespie     {
3085c87b03e5Sespie       rtx label = gen_label_rtx ();
3086c87b03e5Sespie       tree expr;
3087c87b03e5Sespie 
3088c87b03e5Sespie       do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX);
3089c87b03e5Sespie       start_cleanup_deferral ();
3090c87b03e5Sespie       expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
3091c87b03e5Sespie 		    DECL_RESULT (current_function_decl),
3092c87b03e5Sespie 		    TREE_OPERAND (retval_rhs, 1));
3093c87b03e5Sespie       TREE_SIDE_EFFECTS (expr) = 1;
3094c87b03e5Sespie       expand_return (expr);
3095c87b03e5Sespie       emit_label (label);
3096c87b03e5Sespie 
3097c87b03e5Sespie       expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
3098c87b03e5Sespie 		    DECL_RESULT (current_function_decl),
3099c87b03e5Sespie 		    TREE_OPERAND (retval_rhs, 2));
3100c87b03e5Sespie       TREE_SIDE_EFFECTS (expr) = 1;
3101c87b03e5Sespie       expand_return (expr);
3102c87b03e5Sespie       end_cleanup_deferral ();
3103c87b03e5Sespie       return;
3104c87b03e5Sespie     }
3105c87b03e5Sespie 
3106c87b03e5Sespie   result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
3107c87b03e5Sespie 
3108c87b03e5Sespie   /* If the result is an aggregate that is being returned in one (or more)
3109c87b03e5Sespie      registers, load the registers here.  The compiler currently can't handle
3110c87b03e5Sespie      copying a BLKmode value into registers.  We could put this code in a
3111c87b03e5Sespie      more general area (for use by everyone instead of just function
3112c87b03e5Sespie      call/return), but until this feature is generally usable it is kept here
3113c87b03e5Sespie      (and in expand_call).  The value must go into a pseudo in case there
3114c87b03e5Sespie      are cleanups that will clobber the real return register.  */
3115c87b03e5Sespie 
3116c87b03e5Sespie   if (retval_rhs != 0
3117c87b03e5Sespie       && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
3118c87b03e5Sespie       && GET_CODE (result_rtl) == REG)
3119c87b03e5Sespie     {
3120c87b03e5Sespie       int i;
3121c87b03e5Sespie       unsigned HOST_WIDE_INT bitpos, xbitpos;
3122c87b03e5Sespie       unsigned HOST_WIDE_INT big_endian_correction = 0;
3123c87b03e5Sespie       unsigned HOST_WIDE_INT bytes
3124c87b03e5Sespie 	= int_size_in_bytes (TREE_TYPE (retval_rhs));
3125c87b03e5Sespie       int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
3126c87b03e5Sespie       unsigned int bitsize
3127c87b03e5Sespie 	= MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
3128c87b03e5Sespie       rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
3129c87b03e5Sespie       rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
3130c87b03e5Sespie       rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
3131c87b03e5Sespie       enum machine_mode tmpmode, result_reg_mode;
3132c87b03e5Sespie 
3133c87b03e5Sespie       if (bytes == 0)
3134c87b03e5Sespie 	{
3135c87b03e5Sespie 	  expand_null_return ();
3136c87b03e5Sespie 	  return;
3137c87b03e5Sespie 	}
3138c87b03e5Sespie 
3139c87b03e5Sespie       /* Structures whose size is not a multiple of a word are aligned
3140c87b03e5Sespie 	 to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
3141c87b03e5Sespie 	 machine, this means we must skip the empty high order bytes when
3142c87b03e5Sespie 	 calculating the bit offset.  */
3143c87b03e5Sespie       if (BYTES_BIG_ENDIAN
3144c87b03e5Sespie 	  && bytes % UNITS_PER_WORD)
3145c87b03e5Sespie 	big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
3146c87b03e5Sespie 						  * BITS_PER_UNIT));
3147c87b03e5Sespie 
3148c87b03e5Sespie       /* Copy the structure BITSIZE bits at a time.  */
3149c87b03e5Sespie       for (bitpos = 0, xbitpos = big_endian_correction;
3150c87b03e5Sespie 	   bitpos < bytes * BITS_PER_UNIT;
3151c87b03e5Sespie 	   bitpos += bitsize, xbitpos += bitsize)
3152c87b03e5Sespie 	{
3153c87b03e5Sespie 	  /* We need a new destination pseudo each time xbitpos is
3154c87b03e5Sespie 	     on a word boundary and when xbitpos == big_endian_correction
3155c87b03e5Sespie 	     (the first time through).  */
3156c87b03e5Sespie 	  if (xbitpos % BITS_PER_WORD == 0
3157c87b03e5Sespie 	      || xbitpos == big_endian_correction)
3158c87b03e5Sespie 	    {
3159c87b03e5Sespie 	      /* Generate an appropriate register.  */
3160c87b03e5Sespie 	      dst = gen_reg_rtx (word_mode);
3161c87b03e5Sespie 	      result_pseudos[xbitpos / BITS_PER_WORD] = dst;
3162c87b03e5Sespie 
3163c87b03e5Sespie 	      /* Clear the destination before we move anything into it.  */
3164c87b03e5Sespie 	      emit_move_insn (dst, CONST0_RTX (GET_MODE (dst)));
3165c87b03e5Sespie 	    }
3166c87b03e5Sespie 
3167c87b03e5Sespie 	  /* We need a new source operand each time bitpos is on a word
3168c87b03e5Sespie 	     boundary.  */
3169c87b03e5Sespie 	  if (bitpos % BITS_PER_WORD == 0)
3170c87b03e5Sespie 	    src = operand_subword_force (result_val,
3171c87b03e5Sespie 					 bitpos / BITS_PER_WORD,
3172c87b03e5Sespie 					 BLKmode);
3173c87b03e5Sespie 
3174c87b03e5Sespie 	  /* Use bitpos for the source extraction (left justified) and
3175c87b03e5Sespie 	     xbitpos for the destination store (right justified).  */
3176c87b03e5Sespie 	  store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
3177c87b03e5Sespie 			   extract_bit_field (src, bitsize,
3178c87b03e5Sespie 					      bitpos % BITS_PER_WORD, 1,
3179c87b03e5Sespie 					      NULL_RTX, word_mode, word_mode,
3180c87b03e5Sespie 					      BITS_PER_WORD),
3181c87b03e5Sespie 			   BITS_PER_WORD);
3182c87b03e5Sespie 	}
3183c87b03e5Sespie 
3184c87b03e5Sespie       /* Find the smallest integer mode large enough to hold the
3185c87b03e5Sespie 	 entire structure and use that mode instead of BLKmode
3186c87b03e5Sespie 	 on the USE insn for the return register.  */
3187c87b03e5Sespie       for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
3188c87b03e5Sespie 	   tmpmode != VOIDmode;
3189c87b03e5Sespie 	   tmpmode = GET_MODE_WIDER_MODE (tmpmode))
3190c87b03e5Sespie 	/* Have we found a large enough mode?  */
3191c87b03e5Sespie 	if (GET_MODE_SIZE (tmpmode) >= bytes)
3192c87b03e5Sespie 	  break;
3193c87b03e5Sespie 
3194c87b03e5Sespie       /* No suitable mode found.  */
3195c87b03e5Sespie       if (tmpmode == VOIDmode)
3196c87b03e5Sespie 	abort ();
3197c87b03e5Sespie 
3198c87b03e5Sespie       PUT_MODE (result_rtl, tmpmode);
3199c87b03e5Sespie 
3200c87b03e5Sespie       if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
3201c87b03e5Sespie 	result_reg_mode = word_mode;
3202c87b03e5Sespie       else
3203c87b03e5Sespie 	result_reg_mode = tmpmode;
3204c87b03e5Sespie       result_reg = gen_reg_rtx (result_reg_mode);
3205c87b03e5Sespie 
3206c87b03e5Sespie       emit_queue ();
3207c87b03e5Sespie       for (i = 0; i < n_regs; i++)
3208c87b03e5Sespie 	emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode),
3209c87b03e5Sespie 			result_pseudos[i]);
3210c87b03e5Sespie 
3211c87b03e5Sespie       if (tmpmode != result_reg_mode)
3212c87b03e5Sespie 	result_reg = gen_lowpart (tmpmode, result_reg);
3213c87b03e5Sespie 
3214c87b03e5Sespie       expand_value_return (result_reg);
3215c87b03e5Sespie     }
3216c87b03e5Sespie   else if (retval_rhs != 0
3217c87b03e5Sespie 	   && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
3218c87b03e5Sespie 	   && (GET_CODE (result_rtl) == REG
3219c87b03e5Sespie 	       || (GET_CODE (result_rtl) == PARALLEL)))
3220c87b03e5Sespie     {
3221c87b03e5Sespie       /* Calculate the return value into a temporary (usually a pseudo
3222c87b03e5Sespie          reg).  */
3223c87b03e5Sespie       tree ot = TREE_TYPE (DECL_RESULT (current_function_decl));
3224c87b03e5Sespie       tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
3225c87b03e5Sespie 
3226c87b03e5Sespie       val = assign_temp (nt, 0, 0, 1);
3227c87b03e5Sespie       val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
3228c87b03e5Sespie       val = force_not_mem (val);
3229c87b03e5Sespie       emit_queue ();
3230c87b03e5Sespie       /* Return the calculated value, doing cleanups first.  */
3231c87b03e5Sespie       expand_value_return (val);
3232c87b03e5Sespie     }
3233c87b03e5Sespie   else
3234c87b03e5Sespie     {
3235c87b03e5Sespie       /* No cleanups or no hard reg used;
3236c87b03e5Sespie 	 calculate value into hard return reg.  */
3237c87b03e5Sespie       expand_expr (retval, const0_rtx, VOIDmode, 0);
3238c87b03e5Sespie       emit_queue ();
3239c87b03e5Sespie       expand_value_return (result_rtl);
3240c87b03e5Sespie     }
3241c87b03e5Sespie }
3242c87b03e5Sespie 
3243c87b03e5Sespie /* Return 1 if the end of the generated RTX is not a barrier.
3244c87b03e5Sespie    This means code already compiled can drop through.  */
3245c87b03e5Sespie 
3246c87b03e5Sespie int
drop_through_at_end_p()3247c87b03e5Sespie drop_through_at_end_p ()
3248c87b03e5Sespie {
3249c87b03e5Sespie   rtx insn = get_last_insn ();
3250c87b03e5Sespie   while (insn && GET_CODE (insn) == NOTE)
3251c87b03e5Sespie     insn = PREV_INSN (insn);
3252c87b03e5Sespie   return insn && GET_CODE (insn) != BARRIER;
3253c87b03e5Sespie }
3254c87b03e5Sespie 
3255c87b03e5Sespie /* Attempt to optimize a potential tail recursion call into a goto.
3256c87b03e5Sespie    ARGUMENTS are the arguments to a CALL_EXPR; LAST_INSN indicates
3257c87b03e5Sespie    where to place the jump to the tail recursion label.
3258c87b03e5Sespie 
3259c87b03e5Sespie    Return TRUE if the call was optimized into a goto.  */
3260c87b03e5Sespie 
3261c87b03e5Sespie int
optimize_tail_recursion(arguments,last_insn)3262c87b03e5Sespie optimize_tail_recursion (arguments, last_insn)
3263c87b03e5Sespie      tree arguments;
3264c87b03e5Sespie      rtx last_insn;
3265c87b03e5Sespie {
3266c87b03e5Sespie   /* Finish checking validity, and if valid emit code to set the
3267c87b03e5Sespie      argument variables for the new call.  */
3268c87b03e5Sespie   if (tail_recursion_args (arguments, DECL_ARGUMENTS (current_function_decl)))
3269c87b03e5Sespie     {
3270c87b03e5Sespie       if (tail_recursion_label == 0)
3271c87b03e5Sespie 	{
3272c87b03e5Sespie 	  tail_recursion_label = gen_label_rtx ();
3273c87b03e5Sespie 	  emit_label_after (tail_recursion_label,
3274c87b03e5Sespie 			    tail_recursion_reentry);
3275c87b03e5Sespie 	}
3276c87b03e5Sespie       emit_queue ();
3277c87b03e5Sespie       expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn);
3278c87b03e5Sespie       emit_barrier ();
3279c87b03e5Sespie       return 1;
3280c87b03e5Sespie     }
3281c87b03e5Sespie   return 0;
3282c87b03e5Sespie }
3283c87b03e5Sespie 
3284c87b03e5Sespie /* Emit code to alter this function's formal parms for a tail-recursive call.
3285c87b03e5Sespie    ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs).
3286c87b03e5Sespie    FORMALS is the chain of decls of formals.
3287c87b03e5Sespie    Return 1 if this can be done;
3288c87b03e5Sespie    otherwise return 0 and do not emit any code.  */
3289c87b03e5Sespie 
3290c87b03e5Sespie static int
tail_recursion_args(actuals,formals)3291c87b03e5Sespie tail_recursion_args (actuals, formals)
3292c87b03e5Sespie      tree actuals, formals;
3293c87b03e5Sespie {
3294c87b03e5Sespie   tree a = actuals, f = formals;
3295c87b03e5Sespie   int i;
3296c87b03e5Sespie   rtx *argvec;
3297c87b03e5Sespie 
3298c87b03e5Sespie   /* Check that number and types of actuals are compatible
3299c87b03e5Sespie      with the formals.  This is not always true in valid C code.
3300c87b03e5Sespie      Also check that no formal needs to be addressable
3301c87b03e5Sespie      and that all formals are scalars.  */
3302c87b03e5Sespie 
3303c87b03e5Sespie   /* Also count the args.  */
3304c87b03e5Sespie 
3305c87b03e5Sespie   for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)
3306c87b03e5Sespie     {
3307c87b03e5Sespie       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (a)))
3308c87b03e5Sespie 	  != TYPE_MAIN_VARIANT (TREE_TYPE (f)))
3309c87b03e5Sespie 	return 0;
3310c87b03e5Sespie       if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)
3311c87b03e5Sespie 	return 0;
3312c87b03e5Sespie     }
3313c87b03e5Sespie   if (a != 0 || f != 0)
3314c87b03e5Sespie     return 0;
3315c87b03e5Sespie 
3316c87b03e5Sespie   /* Compute all the actuals.  */
3317c87b03e5Sespie 
3318c87b03e5Sespie   argvec = (rtx *) alloca (i * sizeof (rtx));
3319c87b03e5Sespie 
3320c87b03e5Sespie   for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
3321c87b03e5Sespie     argvec[i] = expand_expr (TREE_VALUE (a), NULL_RTX, VOIDmode, 0);
3322c87b03e5Sespie 
3323c87b03e5Sespie   /* Find which actual values refer to current values of previous formals.
3324c87b03e5Sespie      Copy each of them now, before any formal is changed.  */
3325c87b03e5Sespie 
3326c87b03e5Sespie   for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
3327c87b03e5Sespie     {
3328c87b03e5Sespie       int copy = 0;
3329c87b03e5Sespie       int j;
3330c87b03e5Sespie       for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++)
3331c87b03e5Sespie 	if (reg_mentioned_p (DECL_RTL (f), argvec[i]))
3332c87b03e5Sespie 	  {
3333c87b03e5Sespie 	    copy = 1;
3334c87b03e5Sespie 	    break;
3335c87b03e5Sespie 	  }
3336c87b03e5Sespie       if (copy)
3337c87b03e5Sespie 	argvec[i] = copy_to_reg (argvec[i]);
3338c87b03e5Sespie     }
3339c87b03e5Sespie 
3340c87b03e5Sespie   /* Store the values of the actuals into the formals.  */
3341c87b03e5Sespie 
3342c87b03e5Sespie   for (f = formals, a = actuals, i = 0; f;
3343c87b03e5Sespie        f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++)
3344c87b03e5Sespie     {
3345c87b03e5Sespie       if (GET_MODE (DECL_RTL (f)) == GET_MODE (argvec[i]))
3346c87b03e5Sespie 	emit_move_insn (DECL_RTL (f), argvec[i]);
3347c87b03e5Sespie       else
3348c87b03e5Sespie 	{
3349c87b03e5Sespie 	  rtx tmp = argvec[i];
3350c87b03e5Sespie 	  int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)));
3351c87b03e5Sespie 	  promote_mode(TREE_TYPE (TREE_VALUE (a)), GET_MODE (tmp),
3352c87b03e5Sespie 		       &unsignedp, 0);
3353c87b03e5Sespie 	  if (DECL_MODE (f) != GET_MODE (DECL_RTL (f)))
3354c87b03e5Sespie 	    {
3355c87b03e5Sespie 	      tmp = gen_reg_rtx (DECL_MODE (f));
3356c87b03e5Sespie 	      convert_move (tmp, argvec[i], unsignedp);
3357c87b03e5Sespie 	    }
3358c87b03e5Sespie 	  convert_move (DECL_RTL (f), tmp, unsignedp);
3359c87b03e5Sespie 	}
3360c87b03e5Sespie     }
3361c87b03e5Sespie 
3362c87b03e5Sespie   free_temp_slots ();
3363c87b03e5Sespie   return 1;
3364c87b03e5Sespie }
3365c87b03e5Sespie 
3366c87b03e5Sespie /* Generate the RTL code for entering a binding contour.
3367c87b03e5Sespie    The variables are declared one by one, by calls to `expand_decl'.
3368c87b03e5Sespie 
3369c87b03e5Sespie    FLAGS is a bitwise or of the following flags:
3370c87b03e5Sespie 
3371c87b03e5Sespie      1 - Nonzero if this construct should be visible to
3372c87b03e5Sespie          `exit_something'.
3373c87b03e5Sespie 
3374c87b03e5Sespie      2 - Nonzero if this contour does not require a
3375c87b03e5Sespie 	 NOTE_INSN_BLOCK_BEG note.  Virtually all calls from
3376c87b03e5Sespie 	 language-independent code should set this flag because they
3377c87b03e5Sespie 	 will not create corresponding BLOCK nodes.  (There should be
3378c87b03e5Sespie 	 a one-to-one correspondence between NOTE_INSN_BLOCK_BEG notes
3379c87b03e5Sespie 	 and BLOCKs.)  If this flag is set, MARK_ENDS should be zero
3380c87b03e5Sespie 	 when expand_end_bindings is called.
3381c87b03e5Sespie 
3382c87b03e5Sespie     If we are creating a NOTE_INSN_BLOCK_BEG note, a BLOCK may
3383c87b03e5Sespie     optionally be supplied.  If so, it becomes the NOTE_BLOCK for the
3384c87b03e5Sespie     note.  */
3385c87b03e5Sespie 
3386c87b03e5Sespie void
expand_start_bindings_and_block(flags,block)3387c87b03e5Sespie expand_start_bindings_and_block (flags, block)
3388c87b03e5Sespie      int flags;
3389c87b03e5Sespie      tree block;
3390c87b03e5Sespie {
3391c87b03e5Sespie   struct nesting *thisblock = ALLOC_NESTING ();
3392c87b03e5Sespie   rtx note;
3393c87b03e5Sespie   int exit_flag = ((flags & 1) != 0);
3394c87b03e5Sespie   int block_flag = ((flags & 2) == 0);
3395c87b03e5Sespie 
3396c87b03e5Sespie   /* If a BLOCK is supplied, then the caller should be requesting a
3397c87b03e5Sespie      NOTE_INSN_BLOCK_BEG note.  */
3398c87b03e5Sespie   if (!block_flag && block)
3399c87b03e5Sespie     abort ();
3400c87b03e5Sespie 
3401c87b03e5Sespie   /* Create a note to mark the beginning of the block.  */
3402c87b03e5Sespie   if (block_flag)
3403c87b03e5Sespie     {
3404c87b03e5Sespie       note = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
3405c87b03e5Sespie       NOTE_BLOCK (note) = block;
3406c87b03e5Sespie     }
3407c87b03e5Sespie   else
3408c87b03e5Sespie     note = emit_note (NULL, NOTE_INSN_DELETED);
3409c87b03e5Sespie 
3410c87b03e5Sespie   /* Make an entry on block_stack for the block we are entering.  */
3411c87b03e5Sespie 
3412c87b03e5Sespie   thisblock->desc = BLOCK_NESTING;
3413c87b03e5Sespie   thisblock->next = block_stack;
3414c87b03e5Sespie   thisblock->all = nesting_stack;
3415c87b03e5Sespie   thisblock->depth = ++nesting_depth;
3416c87b03e5Sespie   thisblock->data.block.stack_level = 0;
3417c87b03e5Sespie   thisblock->data.block.cleanups = 0;
3418c87b03e5Sespie   thisblock->data.block.n_function_calls = 0;
3419c87b03e5Sespie   thisblock->data.block.exception_region = 0;
3420c87b03e5Sespie   thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level;
3421c87b03e5Sespie 
3422c87b03e5Sespie   thisblock->data.block.conditional_code = 0;
3423c87b03e5Sespie   thisblock->data.block.last_unconditional_cleanup = note;
3424c87b03e5Sespie   /* When we insert instructions after the last unconditional cleanup,
3425c87b03e5Sespie      we don't adjust last_insn.  That means that a later add_insn will
3426c87b03e5Sespie      clobber the instructions we've just added.  The easiest way to
3427c87b03e5Sespie      fix this is to just insert another instruction here, so that the
3428c87b03e5Sespie      instructions inserted after the last unconditional cleanup are
3429c87b03e5Sespie      never the last instruction.  */
3430c87b03e5Sespie   emit_note (NULL, NOTE_INSN_DELETED);
3431c87b03e5Sespie 
3432c87b03e5Sespie   if (block_stack
3433c87b03e5Sespie       && !(block_stack->data.block.cleanups == NULL_TREE
3434c87b03e5Sespie 	   && block_stack->data.block.outer_cleanups == NULL_TREE))
3435c87b03e5Sespie     thisblock->data.block.outer_cleanups
3436c87b03e5Sespie       = tree_cons (NULL_TREE, block_stack->data.block.cleanups,
3437c87b03e5Sespie 		   block_stack->data.block.outer_cleanups);
3438c87b03e5Sespie   else
3439c87b03e5Sespie     thisblock->data.block.outer_cleanups = 0;
3440c87b03e5Sespie   thisblock->data.block.label_chain = 0;
3441c87b03e5Sespie   thisblock->data.block.innermost_stack_block = stack_block_stack;
3442c87b03e5Sespie   thisblock->data.block.first_insn = note;
3443c87b03e5Sespie   thisblock->data.block.block_start_count = ++current_block_start_count;
3444c87b03e5Sespie   thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
3445c87b03e5Sespie   block_stack = thisblock;
3446c87b03e5Sespie   nesting_stack = thisblock;
3447c87b03e5Sespie 
3448c87b03e5Sespie   /* Make a new level for allocating stack slots.  */
3449c87b03e5Sespie   push_temp_slots ();
3450c87b03e5Sespie }
3451c87b03e5Sespie 
3452c87b03e5Sespie /* Specify the scope of temporaries created by TARGET_EXPRs.  Similar
3453c87b03e5Sespie    to CLEANUP_POINT_EXPR, but handles cases when a series of calls to
3454c87b03e5Sespie    expand_expr are made.  After we end the region, we know that all
3455c87b03e5Sespie    space for all temporaries that were created by TARGET_EXPRs will be
3456c87b03e5Sespie    destroyed and their space freed for reuse.  */
3457c87b03e5Sespie 
3458c87b03e5Sespie void
expand_start_target_temps()3459c87b03e5Sespie expand_start_target_temps ()
3460c87b03e5Sespie {
3461c87b03e5Sespie   /* This is so that even if the result is preserved, the space
3462c87b03e5Sespie      allocated will be freed, as we know that it is no longer in use.  */
3463c87b03e5Sespie   push_temp_slots ();
3464c87b03e5Sespie 
3465c87b03e5Sespie   /* Start a new binding layer that will keep track of all cleanup
3466c87b03e5Sespie      actions to be performed.  */
3467c87b03e5Sespie   expand_start_bindings (2);
3468c87b03e5Sespie 
3469c87b03e5Sespie   target_temp_slot_level = temp_slot_level;
3470c87b03e5Sespie }
3471c87b03e5Sespie 
3472c87b03e5Sespie void
expand_end_target_temps()3473c87b03e5Sespie expand_end_target_temps ()
3474c87b03e5Sespie {
3475c87b03e5Sespie   expand_end_bindings (NULL_TREE, 0, 0);
3476c87b03e5Sespie 
3477c87b03e5Sespie   /* This is so that even if the result is preserved, the space
3478c87b03e5Sespie      allocated will be freed, as we know that it is no longer in use.  */
3479c87b03e5Sespie   pop_temp_slots ();
3480c87b03e5Sespie }
3481c87b03e5Sespie 
3482c87b03e5Sespie /* Given a pointer to a BLOCK node return nonzero if (and only if) the node
3483c87b03e5Sespie    in question represents the outermost pair of curly braces (i.e. the "body
3484c87b03e5Sespie    block") of a function or method.
3485c87b03e5Sespie 
3486c87b03e5Sespie    For any BLOCK node representing a "body block" of a function or method, the
3487c87b03e5Sespie    BLOCK_SUPERCONTEXT of the node will point to another BLOCK node which
3488c87b03e5Sespie    represents the outermost (function) scope for the function or method (i.e.
3489c87b03e5Sespie    the one which includes the formal parameters).  The BLOCK_SUPERCONTEXT of
3490c87b03e5Sespie    *that* node in turn will point to the relevant FUNCTION_DECL node.  */
3491c87b03e5Sespie 
3492c87b03e5Sespie int
is_body_block(stmt)3493c87b03e5Sespie is_body_block (stmt)
3494c87b03e5Sespie      tree stmt;
3495c87b03e5Sespie {
3496c87b03e5Sespie   if (TREE_CODE (stmt) == BLOCK)
3497c87b03e5Sespie     {
3498c87b03e5Sespie       tree parent = BLOCK_SUPERCONTEXT (stmt);
3499c87b03e5Sespie 
3500c87b03e5Sespie       if (parent && TREE_CODE (parent) == BLOCK)
3501c87b03e5Sespie 	{
3502c87b03e5Sespie 	  tree grandparent = BLOCK_SUPERCONTEXT (parent);
3503c87b03e5Sespie 
3504c87b03e5Sespie 	  if (grandparent && TREE_CODE (grandparent) == FUNCTION_DECL)
3505c87b03e5Sespie 	    return 1;
3506c87b03e5Sespie 	}
3507c87b03e5Sespie     }
3508c87b03e5Sespie 
3509c87b03e5Sespie   return 0;
3510c87b03e5Sespie }
3511c87b03e5Sespie 
3512c87b03e5Sespie /* True if we are currently emitting insns in an area of output code
3513c87b03e5Sespie    that is controlled by a conditional expression.  This is used by
3514c87b03e5Sespie    the cleanup handling code to generate conditional cleanup actions.  */
3515c87b03e5Sespie 
3516c87b03e5Sespie int
conditional_context()3517c87b03e5Sespie conditional_context ()
3518c87b03e5Sespie {
3519c87b03e5Sespie   return block_stack && block_stack->data.block.conditional_code;
3520c87b03e5Sespie }
3521c87b03e5Sespie 
3522c87b03e5Sespie /* Return an opaque pointer to the current nesting level, so frontend code
3523c87b03e5Sespie    can check its own sanity.  */
3524c87b03e5Sespie 
3525c87b03e5Sespie struct nesting *
current_nesting_level()3526c87b03e5Sespie current_nesting_level ()
3527c87b03e5Sespie {
3528c87b03e5Sespie   return cfun ? block_stack : 0;
3529c87b03e5Sespie }
3530c87b03e5Sespie 
3531c87b03e5Sespie /* Emit a handler label for a nonlocal goto handler.
3532c87b03e5Sespie    Also emit code to store the handler label in SLOT before BEFORE_INSN.  */
3533c87b03e5Sespie 
3534c87b03e5Sespie static rtx
expand_nl_handler_label(slot,before_insn)3535c87b03e5Sespie expand_nl_handler_label (slot, before_insn)
3536c87b03e5Sespie      rtx slot, before_insn;
3537c87b03e5Sespie {
3538c87b03e5Sespie   rtx insns;
3539c87b03e5Sespie   rtx handler_label = gen_label_rtx ();
3540c87b03e5Sespie 
3541c87b03e5Sespie   /* Don't let cleanup_cfg delete the handler.  */
3542c87b03e5Sespie   LABEL_PRESERVE_P (handler_label) = 1;
3543c87b03e5Sespie 
3544c87b03e5Sespie   start_sequence ();
3545c87b03e5Sespie   emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
3546c87b03e5Sespie   insns = get_insns ();
3547c87b03e5Sespie   end_sequence ();
3548c87b03e5Sespie   emit_insn_before (insns, before_insn);
3549c87b03e5Sespie 
3550c87b03e5Sespie   emit_label (handler_label);
3551c87b03e5Sespie 
3552c87b03e5Sespie   return handler_label;
3553c87b03e5Sespie }
3554c87b03e5Sespie 
3555c87b03e5Sespie /* Emit code to restore vital registers at the beginning of a nonlocal goto
3556c87b03e5Sespie    handler.  */
3557c87b03e5Sespie static void
expand_nl_goto_receiver()3558c87b03e5Sespie expand_nl_goto_receiver ()
3559c87b03e5Sespie {
3560c87b03e5Sespie #ifdef HAVE_nonlocal_goto
3561c87b03e5Sespie   if (! HAVE_nonlocal_goto)
3562c87b03e5Sespie #endif
3563c87b03e5Sespie     /* First adjust our frame pointer to its actual value.  It was
3564c87b03e5Sespie        previously set to the start of the virtual area corresponding to
3565c87b03e5Sespie        the stacked variables when we branched here and now needs to be
3566c87b03e5Sespie        adjusted to the actual hardware fp value.
3567c87b03e5Sespie 
3568c87b03e5Sespie        Assignments are to virtual registers are converted by
3569c87b03e5Sespie        instantiate_virtual_regs into the corresponding assignment
3570c87b03e5Sespie        to the underlying register (fp in this case) that makes
3571c87b03e5Sespie        the original assignment true.
3572c87b03e5Sespie        So the following insn will actually be
3573c87b03e5Sespie        decrementing fp by STARTING_FRAME_OFFSET.  */
3574c87b03e5Sespie     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
3575c87b03e5Sespie 
3576c87b03e5Sespie #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
3577c87b03e5Sespie   if (fixed_regs[ARG_POINTER_REGNUM])
3578c87b03e5Sespie     {
3579c87b03e5Sespie #ifdef ELIMINABLE_REGS
3580c87b03e5Sespie       /* If the argument pointer can be eliminated in favor of the
3581c87b03e5Sespie 	 frame pointer, we don't need to restore it.  We assume here
3582c87b03e5Sespie 	 that if such an elimination is present, it can always be used.
3583c87b03e5Sespie 	 This is the case on all known machines; if we don't make this
3584c87b03e5Sespie 	 assumption, we do unnecessary saving on many machines.  */
3585c87b03e5Sespie       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
3586c87b03e5Sespie       size_t i;
3587c87b03e5Sespie 
3588c87b03e5Sespie       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
3589c87b03e5Sespie 	if (elim_regs[i].from == ARG_POINTER_REGNUM
3590c87b03e5Sespie 	    && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
3591c87b03e5Sespie 	  break;
3592c87b03e5Sespie 
3593c87b03e5Sespie       if (i == ARRAY_SIZE (elim_regs))
3594c87b03e5Sespie #endif
3595c87b03e5Sespie 	{
3596c87b03e5Sespie 	  /* Now restore our arg pointer from the address at which it
3597c87b03e5Sespie 	     was saved in our stack frame.  */
3598c87b03e5Sespie 	  emit_move_insn (virtual_incoming_args_rtx,
3599c87b03e5Sespie 			  copy_to_reg (get_arg_pointer_save_area (cfun)));
3600c87b03e5Sespie 	}
3601c87b03e5Sespie     }
3602c87b03e5Sespie #endif
3603c87b03e5Sespie 
3604c87b03e5Sespie #ifdef HAVE_nonlocal_goto_receiver
3605c87b03e5Sespie   if (HAVE_nonlocal_goto_receiver)
3606c87b03e5Sespie     emit_insn (gen_nonlocal_goto_receiver ());
3607c87b03e5Sespie #endif
3608c87b03e5Sespie }
3609c87b03e5Sespie 
3610c87b03e5Sespie /* Make handlers for nonlocal gotos taking place in the function calls in
3611c87b03e5Sespie    block THISBLOCK.  */
3612c87b03e5Sespie 
3613c87b03e5Sespie static void
expand_nl_goto_receivers(thisblock)3614c87b03e5Sespie expand_nl_goto_receivers (thisblock)
3615c87b03e5Sespie      struct nesting *thisblock;
3616c87b03e5Sespie {
3617c87b03e5Sespie   tree link;
3618c87b03e5Sespie   rtx afterward = gen_label_rtx ();
3619c87b03e5Sespie   rtx insns, slot;
3620c87b03e5Sespie   rtx label_list;
3621c87b03e5Sespie   int any_invalid;
3622c87b03e5Sespie 
3623c87b03e5Sespie   /* Record the handler address in the stack slot for that purpose,
3624c87b03e5Sespie      during this block, saving and restoring the outer value.  */
3625c87b03e5Sespie   if (thisblock->next != 0)
3626c87b03e5Sespie     for (slot = nonlocal_goto_handler_slots; slot; slot = XEXP (slot, 1))
3627c87b03e5Sespie       {
3628c87b03e5Sespie 	rtx save_receiver = gen_reg_rtx (Pmode);
3629c87b03e5Sespie 	emit_move_insn (XEXP (slot, 0), save_receiver);
3630c87b03e5Sespie 
3631c87b03e5Sespie 	start_sequence ();
3632c87b03e5Sespie 	emit_move_insn (save_receiver, XEXP (slot, 0));
3633c87b03e5Sespie 	insns = get_insns ();
3634c87b03e5Sespie 	end_sequence ();
3635c87b03e5Sespie 	emit_insn_before (insns, thisblock->data.block.first_insn);
3636c87b03e5Sespie       }
3637c87b03e5Sespie 
3638c87b03e5Sespie   /* Jump around the handlers; they run only when specially invoked.  */
3639c87b03e5Sespie   emit_jump (afterward);
3640c87b03e5Sespie 
3641c87b03e5Sespie   /* Make a separate handler for each label.  */
3642c87b03e5Sespie   link = nonlocal_labels;
3643c87b03e5Sespie   slot = nonlocal_goto_handler_slots;
3644c87b03e5Sespie   label_list = NULL_RTX;
3645c87b03e5Sespie   for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
3646c87b03e5Sespie     /* Skip any labels we shouldn't be able to jump to from here,
3647c87b03e5Sespie        we generate one special handler for all of them below which just calls
3648c87b03e5Sespie        abort.  */
3649c87b03e5Sespie     if (! DECL_TOO_LATE (TREE_VALUE (link)))
3650c87b03e5Sespie       {
3651c87b03e5Sespie 	rtx lab;
3652c87b03e5Sespie 	lab = expand_nl_handler_label (XEXP (slot, 0),
3653c87b03e5Sespie 				       thisblock->data.block.first_insn);
3654c87b03e5Sespie 	label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
3655c87b03e5Sespie 
3656c87b03e5Sespie 	expand_nl_goto_receiver ();
3657c87b03e5Sespie 
3658c87b03e5Sespie 	/* Jump to the "real" nonlocal label.  */
3659c87b03e5Sespie 	expand_goto (TREE_VALUE (link));
3660c87b03e5Sespie       }
3661c87b03e5Sespie 
3662c87b03e5Sespie   /* A second pass over all nonlocal labels; this time we handle those
3663c87b03e5Sespie      we should not be able to jump to at this point.  */
3664c87b03e5Sespie   link = nonlocal_labels;
3665c87b03e5Sespie   slot = nonlocal_goto_handler_slots;
3666c87b03e5Sespie   any_invalid = 0;
3667c87b03e5Sespie   for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
3668c87b03e5Sespie     if (DECL_TOO_LATE (TREE_VALUE (link)))
3669c87b03e5Sespie       {
3670c87b03e5Sespie 	rtx lab;
3671c87b03e5Sespie 	lab = expand_nl_handler_label (XEXP (slot, 0),
3672c87b03e5Sespie 				       thisblock->data.block.first_insn);
3673c87b03e5Sespie 	label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
3674c87b03e5Sespie 	any_invalid = 1;
3675c87b03e5Sespie       }
3676c87b03e5Sespie 
3677c87b03e5Sespie   if (any_invalid)
3678c87b03e5Sespie     {
3679c87b03e5Sespie       expand_nl_goto_receiver ();
3680c87b03e5Sespie       expand_builtin_trap ();
3681c87b03e5Sespie     }
3682c87b03e5Sespie 
3683c87b03e5Sespie   nonlocal_goto_handler_labels = label_list;
3684c87b03e5Sespie   emit_label (afterward);
3685c87b03e5Sespie }
3686c87b03e5Sespie 
3687c87b03e5Sespie /* Warn about any unused VARS (which may contain nodes other than
3688c87b03e5Sespie    VAR_DECLs, but such nodes are ignored).  The nodes are connected
3689c87b03e5Sespie    via the TREE_CHAIN field.  */
3690c87b03e5Sespie 
3691c87b03e5Sespie void
warn_about_unused_variables(vars)3692c87b03e5Sespie warn_about_unused_variables (vars)
3693c87b03e5Sespie      tree vars;
3694c87b03e5Sespie {
3695c87b03e5Sespie   tree decl;
3696c87b03e5Sespie 
3697c87b03e5Sespie   if (warn_unused_variable)
3698c87b03e5Sespie     for (decl = vars; decl; decl = TREE_CHAIN (decl))
3699c87b03e5Sespie       if (TREE_CODE (decl) == VAR_DECL
3700c87b03e5Sespie 	  && ! TREE_USED (decl)
3701c87b03e5Sespie 	  && ! DECL_IN_SYSTEM_HEADER (decl)
3702c87b03e5Sespie 	  && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
3703c87b03e5Sespie 	warning_with_decl (decl, "unused variable `%s'");
3704c87b03e5Sespie }
3705c87b03e5Sespie 
3706c87b03e5Sespie /* Generate RTL code to terminate a binding contour.
3707c87b03e5Sespie 
3708c87b03e5Sespie    VARS is the chain of VAR_DECL nodes for the variables bound in this
3709c87b03e5Sespie    contour.  There may actually be other nodes in this chain, but any
3710c87b03e5Sespie    nodes other than VAR_DECLS are ignored.
3711c87b03e5Sespie 
3712c87b03e5Sespie    MARK_ENDS is nonzero if we should put a note at the beginning
3713c87b03e5Sespie    and end of this binding contour.
3714c87b03e5Sespie 
3715c87b03e5Sespie    DONT_JUMP_IN is nonzero if it is not valid to jump into this contour.
3716c87b03e5Sespie    (That is true automatically if the contour has a saved stack level.)  */
3717c87b03e5Sespie 
3718c87b03e5Sespie void
expand_end_bindings(vars,mark_ends,dont_jump_in)3719c87b03e5Sespie expand_end_bindings (vars, mark_ends, dont_jump_in)
3720c87b03e5Sespie      tree vars;
3721c87b03e5Sespie      int mark_ends;
3722c87b03e5Sespie      int dont_jump_in;
3723c87b03e5Sespie {
3724c87b03e5Sespie   struct nesting *thisblock = block_stack;
3725c87b03e5Sespie 
3726c87b03e5Sespie   /* If any of the variables in this scope were not used, warn the
3727c87b03e5Sespie      user.  */
3728c87b03e5Sespie   warn_about_unused_variables (vars);
3729c87b03e5Sespie 
3730c87b03e5Sespie   if (thisblock->exit_label)
3731c87b03e5Sespie     {
3732c87b03e5Sespie       do_pending_stack_adjust ();
3733c87b03e5Sespie       emit_label (thisblock->exit_label);
3734c87b03e5Sespie     }
3735c87b03e5Sespie 
3736c87b03e5Sespie   /* If necessary, make handlers for nonlocal gotos taking
3737c87b03e5Sespie      place in the function calls in this block.  */
3738c87b03e5Sespie   if (function_call_count != thisblock->data.block.n_function_calls
3739c87b03e5Sespie       && nonlocal_labels
3740c87b03e5Sespie       /* Make handler for outermost block
3741c87b03e5Sespie 	 if there were any nonlocal gotos to this function.  */
3742c87b03e5Sespie       && (thisblock->next == 0 ? current_function_has_nonlocal_label
3743c87b03e5Sespie 	  /* Make handler for inner block if it has something
3744c87b03e5Sespie 	     special to do when you jump out of it.  */
3745c87b03e5Sespie 	  : (thisblock->data.block.cleanups != 0
3746c87b03e5Sespie 	     || thisblock->data.block.stack_level != 0)))
3747c87b03e5Sespie     expand_nl_goto_receivers (thisblock);
3748c87b03e5Sespie 
3749c87b03e5Sespie   /* Don't allow jumping into a block that has a stack level.
3750c87b03e5Sespie      Cleanups are allowed, though.  */
3751c87b03e5Sespie   if (dont_jump_in
3752c87b03e5Sespie       || thisblock->data.block.stack_level != 0)
3753c87b03e5Sespie     {
3754c87b03e5Sespie       struct label_chain *chain;
3755c87b03e5Sespie 
3756c87b03e5Sespie       /* Any labels in this block are no longer valid to go to.
3757c87b03e5Sespie 	 Mark them to cause an error message.  */
3758c87b03e5Sespie       for (chain = thisblock->data.block.label_chain; chain; chain = chain->next)
3759c87b03e5Sespie 	{
3760c87b03e5Sespie 	  DECL_TOO_LATE (chain->label) = 1;
3761c87b03e5Sespie 	  /* If any goto without a fixup came to this label,
3762c87b03e5Sespie 	     that must be an error, because gotos without fixups
3763c87b03e5Sespie 	     come from outside all saved stack-levels.  */
3764c87b03e5Sespie 	  if (TREE_ADDRESSABLE (chain->label))
3765c87b03e5Sespie 	    error_with_decl (chain->label,
3766c87b03e5Sespie 			     "label `%s' used before containing binding contour");
3767c87b03e5Sespie 	}
3768c87b03e5Sespie     }
3769c87b03e5Sespie 
3770c87b03e5Sespie   /* Restore stack level in effect before the block
3771c87b03e5Sespie      (only if variable-size objects allocated).  */
3772c87b03e5Sespie   /* Perform any cleanups associated with the block.  */
3773c87b03e5Sespie 
3774c87b03e5Sespie   if (thisblock->data.block.stack_level != 0
3775c87b03e5Sespie       || thisblock->data.block.cleanups != 0)
3776c87b03e5Sespie     {
3777c87b03e5Sespie       int reachable;
3778c87b03e5Sespie       rtx insn;
3779c87b03e5Sespie 
3780c87b03e5Sespie       /* Don't let cleanups affect ({...}) constructs.  */
3781c87b03e5Sespie       int old_expr_stmts_for_value = expr_stmts_for_value;
3782c87b03e5Sespie       rtx old_last_expr_value = last_expr_value;
3783c87b03e5Sespie       tree old_last_expr_type = last_expr_type;
3784c87b03e5Sespie       expr_stmts_for_value = 0;
3785c87b03e5Sespie 
3786c87b03e5Sespie       /* Only clean up here if this point can actually be reached.  */
3787c87b03e5Sespie       insn = get_last_insn ();
3788c87b03e5Sespie       if (GET_CODE (insn) == NOTE)
3789c87b03e5Sespie 	insn = prev_nonnote_insn (insn);
3790c87b03e5Sespie       reachable = (! insn || GET_CODE (insn) != BARRIER);
3791c87b03e5Sespie 
3792c87b03e5Sespie       /* Do the cleanups.  */
3793c87b03e5Sespie       expand_cleanups (thisblock->data.block.cleanups, NULL_TREE, 0, reachable);
3794c87b03e5Sespie       if (reachable)
3795c87b03e5Sespie 	do_pending_stack_adjust ();
3796c87b03e5Sespie 
3797c87b03e5Sespie       expr_stmts_for_value = old_expr_stmts_for_value;
3798c87b03e5Sespie       last_expr_value = old_last_expr_value;
3799c87b03e5Sespie       last_expr_type = old_last_expr_type;
3800c87b03e5Sespie 
3801c87b03e5Sespie       /* Restore the stack level.  */
3802c87b03e5Sespie 
3803c87b03e5Sespie       if (reachable && thisblock->data.block.stack_level != 0)
3804c87b03e5Sespie 	{
3805c87b03e5Sespie 	  emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
3806c87b03e5Sespie 			      thisblock->data.block.stack_level, NULL_RTX);
3807c87b03e5Sespie 	  if (nonlocal_goto_handler_slots != 0)
3808c87b03e5Sespie 	    emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
3809c87b03e5Sespie 			     NULL_RTX);
3810c87b03e5Sespie 	}
3811c87b03e5Sespie 
3812c87b03e5Sespie       /* Any gotos out of this block must also do these things.
3813c87b03e5Sespie 	 Also report any gotos with fixups that came to labels in this
3814c87b03e5Sespie 	 level.  */
3815c87b03e5Sespie       fixup_gotos (thisblock,
3816c87b03e5Sespie 		   thisblock->data.block.stack_level,
3817c87b03e5Sespie 		   thisblock->data.block.cleanups,
3818c87b03e5Sespie 		   thisblock->data.block.first_insn,
3819c87b03e5Sespie 		   dont_jump_in);
3820c87b03e5Sespie     }
3821c87b03e5Sespie 
3822c87b03e5Sespie   /* Mark the beginning and end of the scope if requested.
3823c87b03e5Sespie      We do this now, after running cleanups on the variables
3824c87b03e5Sespie      just going out of scope, so they are in scope for their cleanups.  */
3825c87b03e5Sespie 
3826c87b03e5Sespie   if (mark_ends)
3827c87b03e5Sespie     {
3828c87b03e5Sespie       rtx note = emit_note (NULL, NOTE_INSN_BLOCK_END);
3829c87b03e5Sespie       NOTE_BLOCK (note) = NOTE_BLOCK (thisblock->data.block.first_insn);
3830c87b03e5Sespie     }
3831c87b03e5Sespie   else
3832c87b03e5Sespie     /* Get rid of the beginning-mark if we don't make an end-mark.  */
3833c87b03e5Sespie     NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
3834c87b03e5Sespie 
3835c87b03e5Sespie   /* Restore the temporary level of TARGET_EXPRs.  */
3836c87b03e5Sespie   target_temp_slot_level = thisblock->data.block.block_target_temp_slot_level;
3837c87b03e5Sespie 
3838c87b03e5Sespie   /* Restore block_stack level for containing block.  */
3839c87b03e5Sespie 
3840c87b03e5Sespie   stack_block_stack = thisblock->data.block.innermost_stack_block;
3841c87b03e5Sespie   POPSTACK (block_stack);
3842c87b03e5Sespie 
3843c87b03e5Sespie   /* Pop the stack slot nesting and free any slots at this level.  */
3844c87b03e5Sespie   pop_temp_slots ();
3845c87b03e5Sespie }
3846c87b03e5Sespie 
3847c87b03e5Sespie /* Generate code to save the stack pointer at the start of the current block
3848c87b03e5Sespie    and set up to restore it on exit.  */
3849c87b03e5Sespie 
3850c87b03e5Sespie void
save_stack_pointer()3851c87b03e5Sespie save_stack_pointer ()
3852c87b03e5Sespie {
3853c87b03e5Sespie   struct nesting *thisblock = block_stack;
3854c87b03e5Sespie 
3855c87b03e5Sespie   if (thisblock->data.block.stack_level == 0)
3856c87b03e5Sespie     {
3857c87b03e5Sespie       emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
3858c87b03e5Sespie 		       &thisblock->data.block.stack_level,
3859c87b03e5Sespie 		       thisblock->data.block.first_insn);
3860c87b03e5Sespie       stack_block_stack = thisblock;
3861c87b03e5Sespie     }
3862c87b03e5Sespie }
3863c87b03e5Sespie 
3864c87b03e5Sespie /* Generate RTL for the automatic variable declaration DECL.
3865c87b03e5Sespie    (Other kinds of declarations are simply ignored if seen here.)  */
3866c87b03e5Sespie 
3867c87b03e5Sespie void
expand_decl(decl)3868c87b03e5Sespie expand_decl (decl)
3869c87b03e5Sespie      tree decl;
3870c87b03e5Sespie {
3871c87b03e5Sespie   struct nesting *thisblock;
3872c87b03e5Sespie   tree type;
3873c87b03e5Sespie 
3874c87b03e5Sespie   type = TREE_TYPE (decl);
3875c87b03e5Sespie 
3876c87b03e5Sespie   /* For a CONST_DECL, set mode, alignment, and sizes from those of the
3877c87b03e5Sespie      type in case this node is used in a reference.  */
3878c87b03e5Sespie   if (TREE_CODE (decl) == CONST_DECL)
3879c87b03e5Sespie     {
3880c87b03e5Sespie       DECL_MODE (decl) = TYPE_MODE (type);
3881c87b03e5Sespie       DECL_ALIGN (decl) = TYPE_ALIGN (type);
3882c87b03e5Sespie       DECL_SIZE (decl) = TYPE_SIZE (type);
3883c87b03e5Sespie       DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
3884c87b03e5Sespie       return;
3885c87b03e5Sespie     }
3886c87b03e5Sespie 
3887c87b03e5Sespie   /* Otherwise, only automatic variables need any expansion done.  Static and
3888c87b03e5Sespie      external variables, and external functions, will be handled by
3889c87b03e5Sespie      `assemble_variable' (called from finish_decl).  TYPE_DECL requires
3890c87b03e5Sespie      nothing.  PARM_DECLs are handled in `assign_parms'.  */
3891c87b03e5Sespie   if (TREE_CODE (decl) != VAR_DECL)
3892c87b03e5Sespie     return;
3893c87b03e5Sespie 
3894c87b03e5Sespie   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
3895c87b03e5Sespie     return;
3896c87b03e5Sespie 
3897c87b03e5Sespie   thisblock = block_stack;
3898c87b03e5Sespie 
3899c87b03e5Sespie   /* Create the RTL representation for the variable.  */
3900c87b03e5Sespie 
3901c87b03e5Sespie   if (type == error_mark_node)
3902c87b03e5Sespie     SET_DECL_RTL (decl, gen_rtx_MEM (BLKmode, const0_rtx));
3903c87b03e5Sespie 
3904c87b03e5Sespie   else if (DECL_SIZE (decl) == 0)
3905c87b03e5Sespie     /* Variable with incomplete type.  */
3906c87b03e5Sespie     {
3907c87b03e5Sespie       rtx x;
3908c87b03e5Sespie       if (DECL_INITIAL (decl) == 0)
3909c87b03e5Sespie 	/* Error message was already done; now avoid a crash.  */
3910c87b03e5Sespie 	x = gen_rtx_MEM (BLKmode, const0_rtx);
3911c87b03e5Sespie       else
3912c87b03e5Sespie 	/* An initializer is going to decide the size of this array.
3913c87b03e5Sespie 	   Until we know the size, represent its address with a reg.  */
3914c87b03e5Sespie 	x = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
3915c87b03e5Sespie 
3916c87b03e5Sespie       set_mem_attributes (x, decl, 1);
3917c87b03e5Sespie       SET_DECL_RTL (decl, x);
3918c87b03e5Sespie     }
3919c87b03e5Sespie   else if (DECL_MODE (decl) != BLKmode
3920c87b03e5Sespie 	   /* If -ffloat-store, don't put explicit float vars
3921c87b03e5Sespie 	      into regs.  */
3922c87b03e5Sespie 	   && !(flag_float_store
3923c87b03e5Sespie 		&& TREE_CODE (type) == REAL_TYPE)
3924c87b03e5Sespie 	   && ! TREE_THIS_VOLATILE (decl)
3925c87b03e5Sespie 	   && ! DECL_NONLOCAL (decl)
3926c87b03e5Sespie 	   && (DECL_REGISTER (decl) || optimize))
3927c87b03e5Sespie     {
3928c87b03e5Sespie       /* Automatic variable that can go in a register.  */
3929c87b03e5Sespie       int unsignedp = TREE_UNSIGNED (type);
3930c87b03e5Sespie       enum machine_mode reg_mode
3931c87b03e5Sespie 	= promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
3932c87b03e5Sespie 
3933c87b03e5Sespie       SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
3934c87b03e5Sespie 
3935c87b03e5Sespie       if (GET_CODE (DECL_RTL (decl)) == REG)
3936c87b03e5Sespie 	REGNO_DECL (REGNO (DECL_RTL (decl))) = decl;
3937c87b03e5Sespie       else if (GET_CODE (DECL_RTL (decl)) == CONCAT)
3938c87b03e5Sespie 	{
3939c87b03e5Sespie 	  REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 0))) = decl;
3940c87b03e5Sespie 	  REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 1))) = decl;
3941c87b03e5Sespie 	}
3942c87b03e5Sespie 
3943c87b03e5Sespie       mark_user_reg (DECL_RTL (decl));
3944c87b03e5Sespie 
3945c87b03e5Sespie       if (POINTER_TYPE_P (type))
3946c87b03e5Sespie 	mark_reg_pointer (DECL_RTL (decl),
3947c87b03e5Sespie 			  TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
3948c87b03e5Sespie 
3949c87b03e5Sespie       maybe_set_unchanging (DECL_RTL (decl), decl);
3950c87b03e5Sespie 
3951c87b03e5Sespie       /* If something wants our address, try to use ADDRESSOF.  */
3952c87b03e5Sespie       if (TREE_ADDRESSABLE (decl))
3953c87b03e5Sespie 	put_var_into_stack (decl, /*rescan=*/false);
3954c87b03e5Sespie     }
3955c87b03e5Sespie 
3956c87b03e5Sespie   else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
3957c87b03e5Sespie 	   && ! (flag_stack_check && ! STACK_CHECK_BUILTIN
3958c87b03e5Sespie 		 && 0 < compare_tree_int (DECL_SIZE_UNIT (decl),
3959c87b03e5Sespie 					  STACK_CHECK_MAX_VAR_SIZE)))
3960c87b03e5Sespie     {
3961c87b03e5Sespie       /* Variable of fixed size that goes on the stack.  */
3962c87b03e5Sespie       rtx oldaddr = 0;
3963c87b03e5Sespie       rtx addr;
3964c87b03e5Sespie       rtx x;
3965c87b03e5Sespie 
3966c87b03e5Sespie       /* If we previously made RTL for this decl, it must be an array
3967c87b03e5Sespie 	 whose size was determined by the initializer.
3968c87b03e5Sespie 	 The old address was a register; set that register now
3969c87b03e5Sespie 	 to the proper address.  */
3970c87b03e5Sespie       if (DECL_RTL_SET_P (decl))
3971c87b03e5Sespie 	{
3972c87b03e5Sespie 	  if (GET_CODE (DECL_RTL (decl)) != MEM
3973c87b03e5Sespie 	      || GET_CODE (XEXP (DECL_RTL (decl), 0)) != REG)
3974c87b03e5Sespie 	    abort ();
3975c87b03e5Sespie 	  oldaddr = XEXP (DECL_RTL (decl), 0);
3976c87b03e5Sespie 	}
3977c87b03e5Sespie 
3978c87b03e5Sespie       /* Set alignment we actually gave this decl.  */
3979c87b03e5Sespie       DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
3980c87b03e5Sespie 			   : GET_MODE_BITSIZE (DECL_MODE (decl)));
3981c87b03e5Sespie       DECL_USER_ALIGN (decl) = 0;
3982c87b03e5Sespie 
3983c87b03e5Sespie       x = assign_temp (decl, 1, 1, 1);
3984c87b03e5Sespie       set_mem_attributes (x, decl, 1);
3985c87b03e5Sespie       SET_DECL_RTL (decl, x);
3986c87b03e5Sespie 
3987c87b03e5Sespie       if (oldaddr)
3988c87b03e5Sespie 	{
3989c87b03e5Sespie 	  addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);
3990c87b03e5Sespie 	  if (addr != oldaddr)
3991c87b03e5Sespie 	    emit_move_insn (oldaddr, addr);
3992c87b03e5Sespie 	}
3993c87b03e5Sespie     }
3994c87b03e5Sespie   else
3995c87b03e5Sespie     /* Dynamic-size object: must push space on the stack.  */
3996c87b03e5Sespie     {
3997c87b03e5Sespie       rtx address, size, x;
3998c87b03e5Sespie 
3999*8c057a53Smiod       if (warn_variable_decl)
4000*8c057a53Smiod 	warning ("variable-sized declaration");
4001*8c057a53Smiod 
4002c87b03e5Sespie       /* Record the stack pointer on entry to block, if have
4003c87b03e5Sespie 	 not already done so.  */
4004c87b03e5Sespie       do_pending_stack_adjust ();
4005c87b03e5Sespie       save_stack_pointer ();
4006c87b03e5Sespie 
4007c87b03e5Sespie       /* In function-at-a-time mode, variable_size doesn't expand this,
4008c87b03e5Sespie 	 so do it now.  */
4009c87b03e5Sespie       if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
4010c87b03e5Sespie 	expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
4011c87b03e5Sespie 		     const0_rtx, VOIDmode, 0);
4012c87b03e5Sespie 
4013c87b03e5Sespie       /* Compute the variable's size, in bytes.  */
4014c87b03e5Sespie       size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0);
4015c87b03e5Sespie       free_temp_slots ();
4016c87b03e5Sespie 
4017c87b03e5Sespie       /* Allocate space on the stack for the variable.  Note that
4018c87b03e5Sespie 	 DECL_ALIGN says how the variable is to be aligned and we
4019c87b03e5Sespie 	 cannot use it to conclude anything about the alignment of
4020c87b03e5Sespie 	 the size.  */
4021c87b03e5Sespie       address = allocate_dynamic_stack_space (size, NULL_RTX,
4022c87b03e5Sespie 					      TYPE_ALIGN (TREE_TYPE (decl)));
4023c87b03e5Sespie 
4024c87b03e5Sespie       /* Reference the variable indirect through that rtx.  */
4025c87b03e5Sespie       x = gen_rtx_MEM (DECL_MODE (decl), address);
4026c87b03e5Sespie       set_mem_attributes (x, decl, 1);
4027c87b03e5Sespie       SET_DECL_RTL (decl, x);
4028c87b03e5Sespie 
4029c87b03e5Sespie 
4030c87b03e5Sespie       /* Indicate the alignment we actually gave this variable.  */
4031c87b03e5Sespie #ifdef STACK_BOUNDARY
4032c87b03e5Sespie       DECL_ALIGN (decl) = STACK_BOUNDARY;
4033c87b03e5Sespie #else
4034c87b03e5Sespie       DECL_ALIGN (decl) = BIGGEST_ALIGNMENT;
4035c87b03e5Sespie #endif
4036c87b03e5Sespie       DECL_USER_ALIGN (decl) = 0;
4037c87b03e5Sespie     }
4038c87b03e5Sespie }
4039c87b03e5Sespie 
4040c87b03e5Sespie /* Emit code to perform the initialization of a declaration DECL.  */
4041c87b03e5Sespie 
4042c87b03e5Sespie void
expand_decl_init(decl)4043c87b03e5Sespie expand_decl_init (decl)
4044c87b03e5Sespie      tree decl;
4045c87b03e5Sespie {
4046c87b03e5Sespie   int was_used = TREE_USED (decl);
4047c87b03e5Sespie 
4048c87b03e5Sespie   /* If this is a CONST_DECL, we don't have to generate any code.  Likewise
4049c87b03e5Sespie      for static decls.  */
4050c87b03e5Sespie   if (TREE_CODE (decl) == CONST_DECL
4051c87b03e5Sespie       || TREE_STATIC (decl))
4052c87b03e5Sespie     return;
4053c87b03e5Sespie 
4054c87b03e5Sespie   /* Compute and store the initial value now.  */
4055c87b03e5Sespie 
4056c87b03e5Sespie   push_temp_slots ();
4057c87b03e5Sespie 
4058c87b03e5Sespie   if (DECL_INITIAL (decl) == error_mark_node)
4059c87b03e5Sespie     {
4060c87b03e5Sespie       enum tree_code code = TREE_CODE (TREE_TYPE (decl));
4061c87b03e5Sespie 
4062c87b03e5Sespie       if (code == INTEGER_TYPE || code == REAL_TYPE || code == ENUMERAL_TYPE
4063c87b03e5Sespie 	  || code == POINTER_TYPE || code == REFERENCE_TYPE)
4064c87b03e5Sespie 	expand_assignment (decl, convert (TREE_TYPE (decl), integer_zero_node),
4065c87b03e5Sespie 			   0, 0);
4066c87b03e5Sespie       emit_queue ();
4067c87b03e5Sespie     }
4068c87b03e5Sespie   else if (DECL_INITIAL (decl) && TREE_CODE (DECL_INITIAL (decl)) != TREE_LIST)
4069c87b03e5Sespie     {
4070c87b03e5Sespie       emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
4071c87b03e5Sespie       expand_assignment (decl, DECL_INITIAL (decl), 0, 0);
4072c87b03e5Sespie       emit_queue ();
4073c87b03e5Sespie     }
4074c87b03e5Sespie 
4075c87b03e5Sespie   /* Don't let the initialization count as "using" the variable.  */
4076c87b03e5Sespie   TREE_USED (decl) = was_used;
4077c87b03e5Sespie 
4078c87b03e5Sespie   /* Free any temporaries we made while initializing the decl.  */
4079c87b03e5Sespie   preserve_temp_slots (NULL_RTX);
4080c87b03e5Sespie   free_temp_slots ();
4081c87b03e5Sespie   pop_temp_slots ();
4082c87b03e5Sespie }
4083c87b03e5Sespie 
4084c87b03e5Sespie /* CLEANUP is an expression to be executed at exit from this binding contour;
4085c87b03e5Sespie    for example, in C++, it might call the destructor for this variable.
4086c87b03e5Sespie 
4087c87b03e5Sespie    We wrap CLEANUP in an UNSAVE_EXPR node, so that we can expand the
4088c87b03e5Sespie    CLEANUP multiple times, and have the correct semantics.  This
4089c87b03e5Sespie    happens in exception handling, for gotos, returns, breaks that
4090c87b03e5Sespie    leave the current scope.
4091c87b03e5Sespie 
4092c87b03e5Sespie    If CLEANUP is nonzero and DECL is zero, we record a cleanup
4093c87b03e5Sespie    that is not associated with any particular variable.  */
4094c87b03e5Sespie 
4095c87b03e5Sespie int
expand_decl_cleanup(decl,cleanup)4096c87b03e5Sespie expand_decl_cleanup (decl, cleanup)
4097c87b03e5Sespie      tree decl, cleanup;
4098c87b03e5Sespie {
4099c87b03e5Sespie   struct nesting *thisblock;
4100c87b03e5Sespie 
4101c87b03e5Sespie   /* Error if we are not in any block.  */
4102c87b03e5Sespie   if (cfun == 0 || block_stack == 0)
4103c87b03e5Sespie     return 0;
4104c87b03e5Sespie 
4105c87b03e5Sespie   thisblock = block_stack;
4106c87b03e5Sespie 
4107c87b03e5Sespie   /* Record the cleanup if there is one.  */
4108c87b03e5Sespie 
4109c87b03e5Sespie   if (cleanup != 0)
4110c87b03e5Sespie     {
4111c87b03e5Sespie       tree t;
4112c87b03e5Sespie       rtx seq;
4113c87b03e5Sespie       tree *cleanups = &thisblock->data.block.cleanups;
4114c87b03e5Sespie       int cond_context = conditional_context ();
4115c87b03e5Sespie 
4116c87b03e5Sespie       if (cond_context)
4117c87b03e5Sespie 	{
4118c87b03e5Sespie 	  rtx flag = gen_reg_rtx (word_mode);
4119c87b03e5Sespie 	  rtx set_flag_0;
4120c87b03e5Sespie 	  tree cond;
4121c87b03e5Sespie 
4122c87b03e5Sespie 	  start_sequence ();
4123c87b03e5Sespie 	  emit_move_insn (flag, const0_rtx);
4124c87b03e5Sespie 	  set_flag_0 = get_insns ();
4125c87b03e5Sespie 	  end_sequence ();
4126c87b03e5Sespie 
4127c87b03e5Sespie 	  thisblock->data.block.last_unconditional_cleanup
4128c87b03e5Sespie 	    = emit_insn_after (set_flag_0,
4129c87b03e5Sespie 				thisblock->data.block.last_unconditional_cleanup);
4130c87b03e5Sespie 
4131c87b03e5Sespie 	  emit_move_insn (flag, const1_rtx);
4132c87b03e5Sespie 
4133c87b03e5Sespie 	  cond = build_decl (VAR_DECL, NULL_TREE,
4134c87b03e5Sespie 			     (*lang_hooks.types.type_for_mode) (word_mode, 1));
4135c87b03e5Sespie 	  SET_DECL_RTL (cond, flag);
4136c87b03e5Sespie 
4137c87b03e5Sespie 	  /* Conditionalize the cleanup.  */
4138c87b03e5Sespie 	  cleanup = build (COND_EXPR, void_type_node,
4139c87b03e5Sespie 			   (*lang_hooks.truthvalue_conversion) (cond),
4140c87b03e5Sespie 			   cleanup, integer_zero_node);
4141c87b03e5Sespie 	  cleanup = fold (cleanup);
4142c87b03e5Sespie 
4143c87b03e5Sespie 	  cleanups = &thisblock->data.block.cleanups;
4144c87b03e5Sespie 	}
4145c87b03e5Sespie 
4146c87b03e5Sespie       cleanup = unsave_expr (cleanup);
4147c87b03e5Sespie 
4148c87b03e5Sespie       t = *cleanups = tree_cons (decl, cleanup, *cleanups);
4149c87b03e5Sespie 
4150c87b03e5Sespie       if (! cond_context)
4151c87b03e5Sespie 	/* If this block has a cleanup, it belongs in stack_block_stack.  */
4152c87b03e5Sespie 	stack_block_stack = thisblock;
4153c87b03e5Sespie 
4154c87b03e5Sespie       if (cond_context)
4155c87b03e5Sespie 	{
4156c87b03e5Sespie 	  start_sequence ();
4157c87b03e5Sespie 	}
4158c87b03e5Sespie 
4159c87b03e5Sespie       if (! using_eh_for_cleanups_p)
4160c87b03e5Sespie 	TREE_ADDRESSABLE (t) = 1;
4161c87b03e5Sespie       else
4162c87b03e5Sespie 	expand_eh_region_start ();
4163c87b03e5Sespie 
4164c87b03e5Sespie       if (cond_context)
4165c87b03e5Sespie 	{
4166c87b03e5Sespie 	  seq = get_insns ();
4167c87b03e5Sespie 	  end_sequence ();
4168c87b03e5Sespie 	  if (seq)
4169c87b03e5Sespie 	    thisblock->data.block.last_unconditional_cleanup
4170c87b03e5Sespie 	      = emit_insn_after (seq,
4171c87b03e5Sespie 				 thisblock->data.block.last_unconditional_cleanup);
4172c87b03e5Sespie 	}
4173c87b03e5Sespie       else
4174c87b03e5Sespie 	{
4175c87b03e5Sespie 	  thisblock->data.block.last_unconditional_cleanup
4176c87b03e5Sespie 	    = get_last_insn ();
4177c87b03e5Sespie 	  /* When we insert instructions after the last unconditional cleanup,
4178c87b03e5Sespie 	     we don't adjust last_insn.  That means that a later add_insn will
4179c87b03e5Sespie 	     clobber the instructions we've just added.  The easiest way to
4180c87b03e5Sespie 	     fix this is to just insert another instruction here, so that the
4181c87b03e5Sespie 	     instructions inserted after the last unconditional cleanup are
4182c87b03e5Sespie 	     never the last instruction.  */
4183c87b03e5Sespie 	  emit_note (NULL, NOTE_INSN_DELETED);
4184c87b03e5Sespie 	}
4185c87b03e5Sespie     }
4186c87b03e5Sespie   return 1;
4187c87b03e5Sespie }
4188c87b03e5Sespie 
4189c87b03e5Sespie /* Like expand_decl_cleanup, but maybe only run the cleanup if an exception
4190c87b03e5Sespie    is thrown.  */
4191c87b03e5Sespie 
4192c87b03e5Sespie int
expand_decl_cleanup_eh(decl,cleanup,eh_only)4193c87b03e5Sespie expand_decl_cleanup_eh (decl, cleanup, eh_only)
4194c87b03e5Sespie      tree decl, cleanup;
4195c87b03e5Sespie      int eh_only;
4196c87b03e5Sespie {
4197c87b03e5Sespie   int ret = expand_decl_cleanup (decl, cleanup);
4198c87b03e5Sespie   if (cleanup && ret)
4199c87b03e5Sespie     {
4200c87b03e5Sespie       tree node = block_stack->data.block.cleanups;
4201c87b03e5Sespie       CLEANUP_EH_ONLY (node) = eh_only;
4202c87b03e5Sespie     }
4203c87b03e5Sespie   return ret;
4204c87b03e5Sespie }
4205c87b03e5Sespie 
4206c87b03e5Sespie /* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
4207c87b03e5Sespie    DECL_ELTS is the list of elements that belong to DECL's type.
4208c87b03e5Sespie    In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup.  */
4209c87b03e5Sespie 
4210c87b03e5Sespie void
expand_anon_union_decl(decl,cleanup,decl_elts)4211c87b03e5Sespie expand_anon_union_decl (decl, cleanup, decl_elts)
4212c87b03e5Sespie      tree decl, cleanup, decl_elts;
4213c87b03e5Sespie {
4214c87b03e5Sespie   struct nesting *thisblock = cfun == 0 ? 0 : block_stack;
4215c87b03e5Sespie   rtx x;
4216c87b03e5Sespie   tree t;
4217c87b03e5Sespie 
4218c87b03e5Sespie   /* If any of the elements are addressable, so is the entire union.  */
4219c87b03e5Sespie   for (t = decl_elts; t; t = TREE_CHAIN (t))
4220c87b03e5Sespie     if (TREE_ADDRESSABLE (TREE_VALUE (t)))
4221c87b03e5Sespie       {
4222c87b03e5Sespie 	TREE_ADDRESSABLE (decl) = 1;
4223c87b03e5Sespie 	break;
4224c87b03e5Sespie       }
4225c87b03e5Sespie 
4226c87b03e5Sespie   expand_decl (decl);
4227c87b03e5Sespie   expand_decl_cleanup (decl, cleanup);
4228c87b03e5Sespie   x = DECL_RTL (decl);
4229c87b03e5Sespie 
4230c87b03e5Sespie   /* Go through the elements, assigning RTL to each.  */
4231c87b03e5Sespie   for (t = decl_elts; t; t = TREE_CHAIN (t))
4232c87b03e5Sespie     {
4233c87b03e5Sespie       tree decl_elt = TREE_VALUE (t);
4234c87b03e5Sespie       tree cleanup_elt = TREE_PURPOSE (t);
4235c87b03e5Sespie       enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
4236c87b03e5Sespie 
4237c87b03e5Sespie       /* If any of the elements are addressable, so is the entire
4238c87b03e5Sespie 	 union.  */
4239c87b03e5Sespie       if (TREE_USED (decl_elt))
4240c87b03e5Sespie 	TREE_USED (decl) = 1;
4241c87b03e5Sespie 
4242c87b03e5Sespie       /* Propagate the union's alignment to the elements.  */
4243c87b03e5Sespie       DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
4244c87b03e5Sespie       DECL_USER_ALIGN (decl_elt) = DECL_USER_ALIGN (decl);
4245c87b03e5Sespie 
4246c87b03e5Sespie       /* If the element has BLKmode and the union doesn't, the union is
4247c87b03e5Sespie          aligned such that the element doesn't need to have BLKmode, so
4248c87b03e5Sespie          change the element's mode to the appropriate one for its size.  */
4249c87b03e5Sespie       if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
4250c87b03e5Sespie 	DECL_MODE (decl_elt) = mode
4251c87b03e5Sespie 	  = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
4252c87b03e5Sespie 
4253c87b03e5Sespie       /* (SUBREG (MEM ...)) at RTL generation time is invalid, so we
4254c87b03e5Sespie          instead create a new MEM rtx with the proper mode.  */
4255c87b03e5Sespie       if (GET_CODE (x) == MEM)
4256c87b03e5Sespie 	{
4257c87b03e5Sespie 	  if (mode == GET_MODE (x))
4258c87b03e5Sespie 	    SET_DECL_RTL (decl_elt, x);
4259c87b03e5Sespie 	  else
4260c87b03e5Sespie 	    SET_DECL_RTL (decl_elt, adjust_address_nv (x, mode, 0));
4261c87b03e5Sespie 	}
4262c87b03e5Sespie       else if (GET_CODE (x) == REG)
4263c87b03e5Sespie 	{
4264c87b03e5Sespie 	  if (mode == GET_MODE (x))
4265c87b03e5Sespie 	    SET_DECL_RTL (decl_elt, x);
4266c87b03e5Sespie 	  else
4267c87b03e5Sespie 	    SET_DECL_RTL (decl_elt, gen_lowpart_SUBREG (mode, x));
4268c87b03e5Sespie 	}
4269c87b03e5Sespie       else
4270c87b03e5Sespie 	abort ();
4271c87b03e5Sespie 
4272c87b03e5Sespie       /* Record the cleanup if there is one.  */
4273c87b03e5Sespie 
4274c87b03e5Sespie       if (cleanup != 0)
4275c87b03e5Sespie 	thisblock->data.block.cleanups
4276c87b03e5Sespie 	  = tree_cons (decl_elt, cleanup_elt,
4277c87b03e5Sespie 		       thisblock->data.block.cleanups);
4278c87b03e5Sespie     }
4279c87b03e5Sespie }
4280c87b03e5Sespie 
4281c87b03e5Sespie /* Expand a list of cleanups LIST.
4282c87b03e5Sespie    Elements may be expressions or may be nested lists.
4283c87b03e5Sespie 
4284c87b03e5Sespie    If DONT_DO is nonnull, then any list-element
4285c87b03e5Sespie    whose TREE_PURPOSE matches DONT_DO is omitted.
4286c87b03e5Sespie    This is sometimes used to avoid a cleanup associated with
4287c87b03e5Sespie    a value that is being returned out of the scope.
4288c87b03e5Sespie 
4289c87b03e5Sespie    If IN_FIXUP is nonzero, we are generating this cleanup for a fixup
4290c87b03e5Sespie    goto and handle protection regions specially in that case.
4291c87b03e5Sespie 
4292c87b03e5Sespie    If REACHABLE, we emit code, otherwise just inform the exception handling
4293c87b03e5Sespie    code about this finalization.  */
4294c87b03e5Sespie 
4295c87b03e5Sespie static void
expand_cleanups(list,dont_do,in_fixup,reachable)4296c87b03e5Sespie expand_cleanups (list, dont_do, in_fixup, reachable)
4297c87b03e5Sespie      tree list;
4298c87b03e5Sespie      tree dont_do;
4299c87b03e5Sespie      int in_fixup;
4300c87b03e5Sespie      int reachable;
4301c87b03e5Sespie {
4302c87b03e5Sespie   tree tail;
4303c87b03e5Sespie   for (tail = list; tail; tail = TREE_CHAIN (tail))
4304c87b03e5Sespie     if (dont_do == 0 || TREE_PURPOSE (tail) != dont_do)
4305c87b03e5Sespie       {
4306c87b03e5Sespie 	if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
4307c87b03e5Sespie 	  expand_cleanups (TREE_VALUE (tail), dont_do, in_fixup, reachable);
4308c87b03e5Sespie 	else
4309c87b03e5Sespie 	  {
4310c87b03e5Sespie 	    if (! in_fixup && using_eh_for_cleanups_p)
4311c87b03e5Sespie 	      expand_eh_region_end_cleanup (TREE_VALUE (tail));
4312c87b03e5Sespie 
4313c87b03e5Sespie 	    if (reachable && !CLEANUP_EH_ONLY (tail))
4314c87b03e5Sespie 	      {
4315c87b03e5Sespie 		/* Cleanups may be run multiple times.  For example,
4316c87b03e5Sespie 		   when exiting a binding contour, we expand the
4317c87b03e5Sespie 		   cleanups associated with that contour.  When a goto
4318c87b03e5Sespie 		   within that binding contour has a target outside that
4319c87b03e5Sespie 		   contour, it will expand all cleanups from its scope to
4320c87b03e5Sespie 		   the target.  Though the cleanups are expanded multiple
4321c87b03e5Sespie 		   times, the control paths are non-overlapping so the
4322c87b03e5Sespie 		   cleanups will not be executed twice.  */
4323c87b03e5Sespie 
4324c87b03e5Sespie 		/* We may need to protect from outer cleanups.  */
4325c87b03e5Sespie 		if (in_fixup && using_eh_for_cleanups_p)
4326c87b03e5Sespie 		  {
4327c87b03e5Sespie 		    expand_eh_region_start ();
4328c87b03e5Sespie 
4329c87b03e5Sespie 		    expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
4330c87b03e5Sespie 
4331c87b03e5Sespie 		    expand_eh_region_end_fixup (TREE_VALUE (tail));
4332c87b03e5Sespie 		  }
4333c87b03e5Sespie 		else
4334c87b03e5Sespie 		  expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
4335c87b03e5Sespie 
4336c87b03e5Sespie 		free_temp_slots ();
4337c87b03e5Sespie 	      }
4338c87b03e5Sespie 	  }
4339c87b03e5Sespie       }
4340c87b03e5Sespie }
4341c87b03e5Sespie 
4342c87b03e5Sespie /* Mark when the context we are emitting RTL for as a conditional
4343c87b03e5Sespie    context, so that any cleanup actions we register with
4344c87b03e5Sespie    expand_decl_init will be properly conditionalized when those
4345c87b03e5Sespie    cleanup actions are later performed.  Must be called before any
4346c87b03e5Sespie    expression (tree) is expanded that is within a conditional context.  */
4347c87b03e5Sespie 
4348c87b03e5Sespie void
start_cleanup_deferral()4349c87b03e5Sespie start_cleanup_deferral ()
4350c87b03e5Sespie {
4351c87b03e5Sespie   /* block_stack can be NULL if we are inside the parameter list.  It is
4352c87b03e5Sespie      OK to do nothing, because cleanups aren't possible here.  */
4353c87b03e5Sespie   if (block_stack)
4354c87b03e5Sespie     ++block_stack->data.block.conditional_code;
4355c87b03e5Sespie }
4356c87b03e5Sespie 
4357c87b03e5Sespie /* Mark the end of a conditional region of code.  Because cleanup
4358c87b03e5Sespie    deferrals may be nested, we may still be in a conditional region
4359c87b03e5Sespie    after we end the currently deferred cleanups, only after we end all
4360c87b03e5Sespie    deferred cleanups, are we back in unconditional code.  */
4361c87b03e5Sespie 
4362c87b03e5Sespie void
end_cleanup_deferral()4363c87b03e5Sespie end_cleanup_deferral ()
4364c87b03e5Sespie {
4365c87b03e5Sespie   /* block_stack can be NULL if we are inside the parameter list.  It is
4366c87b03e5Sespie      OK to do nothing, because cleanups aren't possible here.  */
4367c87b03e5Sespie   if (block_stack)
4368c87b03e5Sespie     --block_stack->data.block.conditional_code;
4369c87b03e5Sespie }
4370c87b03e5Sespie 
4371c87b03e5Sespie /* Move all cleanups from the current block_stack
4372c87b03e5Sespie    to the containing block_stack, where they are assumed to
4373c87b03e5Sespie    have been created.  If anything can cause a temporary to
4374c87b03e5Sespie    be created, but not expanded for more than one level of
4375c87b03e5Sespie    block_stacks, then this code will have to change.  */
4376c87b03e5Sespie 
4377c87b03e5Sespie void
move_cleanups_up()4378c87b03e5Sespie move_cleanups_up ()
4379c87b03e5Sespie {
4380c87b03e5Sespie   struct nesting *block = block_stack;
4381c87b03e5Sespie   struct nesting *outer = block->next;
4382c87b03e5Sespie 
4383c87b03e5Sespie   outer->data.block.cleanups
4384c87b03e5Sespie     = chainon (block->data.block.cleanups,
4385c87b03e5Sespie 	       outer->data.block.cleanups);
4386c87b03e5Sespie   block->data.block.cleanups = 0;
4387c87b03e5Sespie }
4388c87b03e5Sespie 
4389c87b03e5Sespie tree
last_cleanup_this_contour()4390c87b03e5Sespie last_cleanup_this_contour ()
4391c87b03e5Sespie {
4392c87b03e5Sespie   if (block_stack == 0)
4393c87b03e5Sespie     return 0;
4394c87b03e5Sespie 
4395c87b03e5Sespie   return block_stack->data.block.cleanups;
4396c87b03e5Sespie }
4397c87b03e5Sespie 
4398c87b03e5Sespie /* Return 1 if there are any pending cleanups at this point.
4399c87b03e5Sespie    If THIS_CONTOUR is nonzero, check the current contour as well.
4400c87b03e5Sespie    Otherwise, look only at the contours that enclose this one.  */
4401c87b03e5Sespie 
4402c87b03e5Sespie int
any_pending_cleanups(this_contour)4403c87b03e5Sespie any_pending_cleanups (this_contour)
4404c87b03e5Sespie      int this_contour;
4405c87b03e5Sespie {
4406c87b03e5Sespie   struct nesting *block;
4407c87b03e5Sespie 
4408c87b03e5Sespie   if (cfun == NULL || cfun->stmt == NULL || block_stack == 0)
4409c87b03e5Sespie     return 0;
4410c87b03e5Sespie 
4411c87b03e5Sespie   if (this_contour && block_stack->data.block.cleanups != NULL)
4412c87b03e5Sespie     return 1;
4413c87b03e5Sespie   if (block_stack->data.block.cleanups == 0
4414c87b03e5Sespie       && block_stack->data.block.outer_cleanups == 0)
4415c87b03e5Sespie     return 0;
4416c87b03e5Sespie 
4417c87b03e5Sespie   for (block = block_stack->next; block; block = block->next)
4418c87b03e5Sespie     if (block->data.block.cleanups != 0)
4419c87b03e5Sespie       return 1;
4420c87b03e5Sespie 
4421c87b03e5Sespie   return 0;
4422c87b03e5Sespie }
4423c87b03e5Sespie 
4424c87b03e5Sespie /* Enter a case (Pascal) or switch (C) statement.
4425c87b03e5Sespie    Push a block onto case_stack and nesting_stack
4426c87b03e5Sespie    to accumulate the case-labels that are seen
4427c87b03e5Sespie    and to record the labels generated for the statement.
4428c87b03e5Sespie 
4429c87b03e5Sespie    EXIT_FLAG is nonzero if `exit_something' should exit this case stmt.
4430c87b03e5Sespie    Otherwise, this construct is transparent for `exit_something'.
4431c87b03e5Sespie 
4432c87b03e5Sespie    EXPR is the index-expression to be dispatched on.
4433c87b03e5Sespie    TYPE is its nominal type.  We could simply convert EXPR to this type,
4434c87b03e5Sespie    but instead we take short cuts.  */
4435c87b03e5Sespie 
4436c87b03e5Sespie void
expand_start_case(exit_flag,expr,type,printname)4437c87b03e5Sespie expand_start_case (exit_flag, expr, type, printname)
4438c87b03e5Sespie      int exit_flag;
4439c87b03e5Sespie      tree expr;
4440c87b03e5Sespie      tree type;
4441c87b03e5Sespie      const char *printname;
4442c87b03e5Sespie {
4443c87b03e5Sespie   struct nesting *thiscase = ALLOC_NESTING ();
4444c87b03e5Sespie 
4445c87b03e5Sespie   /* Make an entry on case_stack for the case we are entering.  */
4446c87b03e5Sespie 
4447c87b03e5Sespie   thiscase->desc = CASE_NESTING;
4448c87b03e5Sespie   thiscase->next = case_stack;
4449c87b03e5Sespie   thiscase->all = nesting_stack;
4450c87b03e5Sespie   thiscase->depth = ++nesting_depth;
4451c87b03e5Sespie   thiscase->exit_label = exit_flag ? gen_label_rtx () : 0;
4452c87b03e5Sespie   thiscase->data.case_stmt.case_list = 0;
4453c87b03e5Sespie   thiscase->data.case_stmt.index_expr = expr;
4454c87b03e5Sespie   thiscase->data.case_stmt.nominal_type = type;
4455c87b03e5Sespie   thiscase->data.case_stmt.default_label = 0;
4456c87b03e5Sespie   thiscase->data.case_stmt.printname = printname;
4457c87b03e5Sespie   thiscase->data.case_stmt.line_number_status = force_line_numbers ();
4458c87b03e5Sespie   case_stack = thiscase;
4459c87b03e5Sespie   nesting_stack = thiscase;
4460c87b03e5Sespie 
4461c87b03e5Sespie   do_pending_stack_adjust ();
4462c87b03e5Sespie   emit_queue ();
4463c87b03e5Sespie 
4464c87b03e5Sespie   /* Make sure case_stmt.start points to something that won't
4465c87b03e5Sespie      need any transformation before expand_end_case.  */
4466c87b03e5Sespie   if (GET_CODE (get_last_insn ()) != NOTE)
4467c87b03e5Sespie     emit_note (NULL, NOTE_INSN_DELETED);
4468c87b03e5Sespie 
4469c87b03e5Sespie   thiscase->data.case_stmt.start = get_last_insn ();
4470c87b03e5Sespie 
4471c87b03e5Sespie   start_cleanup_deferral ();
4472c87b03e5Sespie }
4473c87b03e5Sespie 
4474c87b03e5Sespie /* Start a "dummy case statement" within which case labels are invalid
4475c87b03e5Sespie    and are not connected to any larger real case statement.
4476c87b03e5Sespie    This can be used if you don't want to let a case statement jump
4477c87b03e5Sespie    into the middle of certain kinds of constructs.  */
4478c87b03e5Sespie 
4479c87b03e5Sespie void
expand_start_case_dummy()4480c87b03e5Sespie expand_start_case_dummy ()
4481c87b03e5Sespie {
4482c87b03e5Sespie   struct nesting *thiscase = ALLOC_NESTING ();
4483c87b03e5Sespie 
4484c87b03e5Sespie   /* Make an entry on case_stack for the dummy.  */
4485c87b03e5Sespie 
4486c87b03e5Sespie   thiscase->desc = CASE_NESTING;
4487c87b03e5Sespie   thiscase->next = case_stack;
4488c87b03e5Sespie   thiscase->all = nesting_stack;
4489c87b03e5Sespie   thiscase->depth = ++nesting_depth;
4490c87b03e5Sespie   thiscase->exit_label = 0;
4491c87b03e5Sespie   thiscase->data.case_stmt.case_list = 0;
4492c87b03e5Sespie   thiscase->data.case_stmt.start = 0;
4493c87b03e5Sespie   thiscase->data.case_stmt.nominal_type = 0;
4494c87b03e5Sespie   thiscase->data.case_stmt.default_label = 0;
4495c87b03e5Sespie   case_stack = thiscase;
4496c87b03e5Sespie   nesting_stack = thiscase;
4497c87b03e5Sespie   start_cleanup_deferral ();
4498c87b03e5Sespie }
4499c87b03e5Sespie 
4500c87b03e5Sespie /* End a dummy case statement.  */
4501c87b03e5Sespie 
4502c87b03e5Sespie void
expand_end_case_dummy()4503c87b03e5Sespie expand_end_case_dummy ()
4504c87b03e5Sespie {
4505c87b03e5Sespie   end_cleanup_deferral ();
4506c87b03e5Sespie   POPSTACK (case_stack);
4507c87b03e5Sespie }
4508c87b03e5Sespie 
4509c87b03e5Sespie /* Return the data type of the index-expression
4510c87b03e5Sespie    of the innermost case statement, or null if none.  */
4511c87b03e5Sespie 
4512c87b03e5Sespie tree
case_index_expr_type()4513c87b03e5Sespie case_index_expr_type ()
4514c87b03e5Sespie {
4515c87b03e5Sespie   if (case_stack)
4516c87b03e5Sespie     return TREE_TYPE (case_stack->data.case_stmt.index_expr);
4517c87b03e5Sespie   return 0;
4518c87b03e5Sespie }
4519c87b03e5Sespie 
4520c87b03e5Sespie static void
check_seenlabel()4521c87b03e5Sespie check_seenlabel ()
4522c87b03e5Sespie {
4523c87b03e5Sespie   /* If this is the first label, warn if any insns have been emitted.  */
4524c87b03e5Sespie   if (case_stack->data.case_stmt.line_number_status >= 0)
4525c87b03e5Sespie     {
4526c87b03e5Sespie       rtx insn;
4527c87b03e5Sespie 
4528c87b03e5Sespie       restore_line_number_status
4529c87b03e5Sespie 	(case_stack->data.case_stmt.line_number_status);
4530c87b03e5Sespie       case_stack->data.case_stmt.line_number_status = -1;
4531c87b03e5Sespie 
4532c87b03e5Sespie       for (insn = case_stack->data.case_stmt.start;
4533c87b03e5Sespie 	   insn;
4534c87b03e5Sespie 	   insn = NEXT_INSN (insn))
4535c87b03e5Sespie 	{
4536c87b03e5Sespie 	  if (GET_CODE (insn) == CODE_LABEL)
4537c87b03e5Sespie 	    break;
4538c87b03e5Sespie 	  if (GET_CODE (insn) != NOTE
4539c87b03e5Sespie 	      && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) != USE))
4540c87b03e5Sespie 	    {
4541c87b03e5Sespie 	      do
4542c87b03e5Sespie 		insn = PREV_INSN (insn);
4543c87b03e5Sespie 	      while (insn && (GET_CODE (insn) != NOTE || NOTE_LINE_NUMBER (insn) < 0));
4544c87b03e5Sespie 
4545c87b03e5Sespie 	      /* If insn is zero, then there must have been a syntax error.  */
4546c87b03e5Sespie 	      if (insn)
4547c87b03e5Sespie 		warning_with_file_and_line (NOTE_SOURCE_FILE (insn),
4548c87b03e5Sespie 					    NOTE_LINE_NUMBER (insn),
4549c87b03e5Sespie 					    "unreachable code at beginning of %s",
4550c87b03e5Sespie 					    case_stack->data.case_stmt.printname);
4551c87b03e5Sespie 	      break;
4552c87b03e5Sespie 	    }
4553c87b03e5Sespie 	}
4554c87b03e5Sespie     }
4555c87b03e5Sespie }
4556c87b03e5Sespie 
4557c87b03e5Sespie /* Accumulate one case or default label inside a case or switch statement.
4558c87b03e5Sespie    VALUE is the value of the case (a null pointer, for a default label).
4559c87b03e5Sespie    The function CONVERTER, when applied to arguments T and V,
4560c87b03e5Sespie    converts the value V to the type T.
4561c87b03e5Sespie 
4562c87b03e5Sespie    If not currently inside a case or switch statement, return 1 and do
4563c87b03e5Sespie    nothing.  The caller will print a language-specific error message.
4564c87b03e5Sespie    If VALUE is a duplicate or overlaps, return 2 and do nothing
4565c87b03e5Sespie    except store the (first) duplicate node in *DUPLICATE.
4566c87b03e5Sespie    If VALUE is out of range, return 3 and do nothing.
4567c87b03e5Sespie    If we are jumping into the scope of a cleanup or var-sized array, return 5.
4568c87b03e5Sespie    Return 0 on success.
4569c87b03e5Sespie 
4570c87b03e5Sespie    Extended to handle range statements.  */
4571c87b03e5Sespie 
4572c87b03e5Sespie int
pushcase(value,converter,label,duplicate)4573c87b03e5Sespie pushcase (value, converter, label, duplicate)
4574c87b03e5Sespie      tree value;
4575c87b03e5Sespie      tree (*converter) PARAMS ((tree, tree));
4576c87b03e5Sespie      tree label;
4577c87b03e5Sespie      tree *duplicate;
4578c87b03e5Sespie {
4579c87b03e5Sespie   tree index_type;
4580c87b03e5Sespie   tree nominal_type;
4581c87b03e5Sespie 
4582c87b03e5Sespie   /* Fail if not inside a real case statement.  */
4583c87b03e5Sespie   if (! (case_stack && case_stack->data.case_stmt.start))
4584c87b03e5Sespie     return 1;
4585c87b03e5Sespie 
4586c87b03e5Sespie   if (stack_block_stack
4587c87b03e5Sespie       && stack_block_stack->depth > case_stack->depth)
4588c87b03e5Sespie     return 5;
4589c87b03e5Sespie 
4590c87b03e5Sespie   index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
4591c87b03e5Sespie   nominal_type = case_stack->data.case_stmt.nominal_type;
4592c87b03e5Sespie 
4593c87b03e5Sespie   /* If the index is erroneous, avoid more problems: pretend to succeed.  */
4594c87b03e5Sespie   if (index_type == error_mark_node)
4595c87b03e5Sespie     return 0;
4596c87b03e5Sespie 
4597c87b03e5Sespie   /* Convert VALUE to the type in which the comparisons are nominally done.  */
4598c87b03e5Sespie   if (value != 0)
4599c87b03e5Sespie     value = (*converter) (nominal_type, value);
4600c87b03e5Sespie 
4601c87b03e5Sespie   check_seenlabel ();
4602c87b03e5Sespie 
4603c87b03e5Sespie   /* Fail if this value is out of range for the actual type of the index
4604c87b03e5Sespie      (which may be narrower than NOMINAL_TYPE).  */
4605c87b03e5Sespie   if (value != 0
4606c87b03e5Sespie       && (TREE_CONSTANT_OVERFLOW (value)
4607c87b03e5Sespie 	  || ! int_fits_type_p (value, index_type)))
4608c87b03e5Sespie     return 3;
4609c87b03e5Sespie 
4610c87b03e5Sespie   return add_case_node (value, value, label, duplicate);
4611c87b03e5Sespie }
4612c87b03e5Sespie 
4613c87b03e5Sespie /* Like pushcase but this case applies to all values between VALUE1 and
4614c87b03e5Sespie    VALUE2 (inclusive).  If VALUE1 is NULL, the range starts at the lowest
4615c87b03e5Sespie    value of the index type and ends at VALUE2.  If VALUE2 is NULL, the range
4616c87b03e5Sespie    starts at VALUE1 and ends at the highest value of the index type.
4617c87b03e5Sespie    If both are NULL, this case applies to all values.
4618c87b03e5Sespie 
4619c87b03e5Sespie    The return value is the same as that of pushcase but there is one
4620c87b03e5Sespie    additional error code: 4 means the specified range was empty.  */
4621c87b03e5Sespie 
4622c87b03e5Sespie int
pushcase_range(value1,value2,converter,label,duplicate)4623c87b03e5Sespie pushcase_range (value1, value2, converter, label, duplicate)
4624c87b03e5Sespie      tree value1, value2;
4625c87b03e5Sespie      tree (*converter) PARAMS ((tree, tree));
4626c87b03e5Sespie      tree label;
4627c87b03e5Sespie      tree *duplicate;
4628c87b03e5Sespie {
4629c87b03e5Sespie   tree index_type;
4630c87b03e5Sespie   tree nominal_type;
4631c87b03e5Sespie 
4632c87b03e5Sespie   /* Fail if not inside a real case statement.  */
4633c87b03e5Sespie   if (! (case_stack && case_stack->data.case_stmt.start))
4634c87b03e5Sespie     return 1;
4635c87b03e5Sespie 
4636c87b03e5Sespie   if (stack_block_stack
4637c87b03e5Sespie       && stack_block_stack->depth > case_stack->depth)
4638c87b03e5Sespie     return 5;
4639c87b03e5Sespie 
4640c87b03e5Sespie   index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
4641c87b03e5Sespie   nominal_type = case_stack->data.case_stmt.nominal_type;
4642c87b03e5Sespie 
4643c87b03e5Sespie   /* If the index is erroneous, avoid more problems: pretend to succeed.  */
4644c87b03e5Sespie   if (index_type == error_mark_node)
4645c87b03e5Sespie     return 0;
4646c87b03e5Sespie 
4647c87b03e5Sespie   check_seenlabel ();
4648c87b03e5Sespie 
4649c87b03e5Sespie   /* Convert VALUEs to type in which the comparisons are nominally done
4650c87b03e5Sespie      and replace any unspecified value with the corresponding bound.  */
4651c87b03e5Sespie   if (value1 == 0)
4652c87b03e5Sespie     value1 = TYPE_MIN_VALUE (index_type);
4653c87b03e5Sespie   if (value2 == 0)
4654c87b03e5Sespie     value2 = TYPE_MAX_VALUE (index_type);
4655c87b03e5Sespie 
4656c87b03e5Sespie   /* Fail if the range is empty.  Do this before any conversion since
4657c87b03e5Sespie      we want to allow out-of-range empty ranges.  */
4658c87b03e5Sespie   if (value2 != 0 && tree_int_cst_lt (value2, value1))
4659c87b03e5Sespie     return 4;
4660c87b03e5Sespie 
4661c87b03e5Sespie   /* If the max was unbounded, use the max of the nominal_type we are
4662c87b03e5Sespie      converting to.  Do this after the < check above to suppress false
4663c87b03e5Sespie      positives.  */
4664c87b03e5Sespie   if (value2 == 0)
4665c87b03e5Sespie     value2 = TYPE_MAX_VALUE (nominal_type);
4666c87b03e5Sespie 
4667c87b03e5Sespie   value1 = (*converter) (nominal_type, value1);
4668c87b03e5Sespie   value2 = (*converter) (nominal_type, value2);
4669c87b03e5Sespie 
4670c87b03e5Sespie   /* Fail if these values are out of range.  */
4671c87b03e5Sespie   if (TREE_CONSTANT_OVERFLOW (value1)
4672c87b03e5Sespie       || ! int_fits_type_p (value1, index_type))
4673c87b03e5Sespie     return 3;
4674c87b03e5Sespie 
4675c87b03e5Sespie   if (TREE_CONSTANT_OVERFLOW (value2)
4676c87b03e5Sespie       || ! int_fits_type_p (value2, index_type))
4677c87b03e5Sespie     return 3;
4678c87b03e5Sespie 
4679c87b03e5Sespie   return add_case_node (value1, value2, label, duplicate);
4680c87b03e5Sespie }
4681c87b03e5Sespie 
4682c87b03e5Sespie /* Do the actual insertion of a case label for pushcase and pushcase_range
4683c87b03e5Sespie    into case_stack->data.case_stmt.case_list.  Use an AVL tree to avoid
4684c87b03e5Sespie    slowdown for large switch statements.  */
4685c87b03e5Sespie 
4686c87b03e5Sespie int
add_case_node(low,high,label,duplicate)4687c87b03e5Sespie add_case_node (low, high, label, duplicate)
4688c87b03e5Sespie      tree low, high;
4689c87b03e5Sespie      tree label;
4690c87b03e5Sespie      tree *duplicate;
4691c87b03e5Sespie {
4692c87b03e5Sespie   struct case_node *p, **q, *r;
4693c87b03e5Sespie 
4694c87b03e5Sespie   /* If there's no HIGH value, then this is not a case range; it's
4695c87b03e5Sespie      just a simple case label.  But that's just a degenerate case
4696c87b03e5Sespie      range.  */
4697c87b03e5Sespie   if (!high)
4698c87b03e5Sespie     high = low;
4699c87b03e5Sespie 
4700c87b03e5Sespie   /* Handle default labels specially.  */
4701c87b03e5Sespie   if (!high && !low)
4702c87b03e5Sespie     {
4703c87b03e5Sespie       if (case_stack->data.case_stmt.default_label != 0)
4704c87b03e5Sespie 	{
4705c87b03e5Sespie 	  *duplicate = case_stack->data.case_stmt.default_label;
4706c87b03e5Sespie 	  return 2;
4707c87b03e5Sespie 	}
4708c87b03e5Sespie       case_stack->data.case_stmt.default_label = label;
4709c87b03e5Sespie       expand_label (label);
4710c87b03e5Sespie       return 0;
4711c87b03e5Sespie     }
4712c87b03e5Sespie 
4713c87b03e5Sespie   q = &case_stack->data.case_stmt.case_list;
4714c87b03e5Sespie   p = *q;
4715c87b03e5Sespie 
4716c87b03e5Sespie   while ((r = *q))
4717c87b03e5Sespie     {
4718c87b03e5Sespie       p = r;
4719c87b03e5Sespie 
4720c87b03e5Sespie       /* Keep going past elements distinctly greater than HIGH.  */
4721c87b03e5Sespie       if (tree_int_cst_lt (high, p->low))
4722c87b03e5Sespie 	q = &p->left;
4723c87b03e5Sespie 
4724c87b03e5Sespie       /* or distinctly less than LOW.  */
4725c87b03e5Sespie       else if (tree_int_cst_lt (p->high, low))
4726c87b03e5Sespie 	q = &p->right;
4727c87b03e5Sespie 
4728c87b03e5Sespie       else
4729c87b03e5Sespie 	{
4730c87b03e5Sespie 	  /* We have an overlap; this is an error.  */
4731c87b03e5Sespie 	  *duplicate = p->code_label;
4732c87b03e5Sespie 	  return 2;
4733c87b03e5Sespie 	}
4734c87b03e5Sespie     }
4735c87b03e5Sespie 
4736c87b03e5Sespie   /* Add this label to the chain, and succeed.  */
4737c87b03e5Sespie 
4738c87b03e5Sespie   r = (struct case_node *) ggc_alloc (sizeof (struct case_node));
4739c87b03e5Sespie   r->low = low;
4740c87b03e5Sespie 
4741c87b03e5Sespie   /* If the bounds are equal, turn this into the one-value case.  */
4742c87b03e5Sespie   if (tree_int_cst_equal (low, high))
4743c87b03e5Sespie     r->high = r->low;
4744c87b03e5Sespie   else
4745c87b03e5Sespie     r->high = high;
4746c87b03e5Sespie 
4747c87b03e5Sespie   r->code_label = label;
4748c87b03e5Sespie   expand_label (label);
4749c87b03e5Sespie 
4750c87b03e5Sespie   *q = r;
4751c87b03e5Sespie   r->parent = p;
4752c87b03e5Sespie   r->left = 0;
4753c87b03e5Sespie   r->right = 0;
4754c87b03e5Sespie   r->balance = 0;
4755c87b03e5Sespie 
4756c87b03e5Sespie   while (p)
4757c87b03e5Sespie     {
4758c87b03e5Sespie       struct case_node *s;
4759c87b03e5Sespie 
4760c87b03e5Sespie       if (r == p->left)
4761c87b03e5Sespie 	{
4762c87b03e5Sespie 	  int b;
4763c87b03e5Sespie 
4764c87b03e5Sespie 	  if (! (b = p->balance))
4765c87b03e5Sespie 	    /* Growth propagation from left side.  */
4766c87b03e5Sespie 	    p->balance = -1;
4767c87b03e5Sespie 	  else if (b < 0)
4768c87b03e5Sespie 	    {
4769c87b03e5Sespie 	      if (r->balance < 0)
4770c87b03e5Sespie 		{
4771c87b03e5Sespie 		  /* R-Rotation */
4772c87b03e5Sespie 		  if ((p->left = s = r->right))
4773c87b03e5Sespie 		    s->parent = p;
4774c87b03e5Sespie 
4775c87b03e5Sespie 		  r->right = p;
4776c87b03e5Sespie 		  p->balance = 0;
4777c87b03e5Sespie 		  r->balance = 0;
4778c87b03e5Sespie 		  s = p->parent;
4779c87b03e5Sespie 		  p->parent = r;
4780c87b03e5Sespie 
4781c87b03e5Sespie 		  if ((r->parent = s))
4782c87b03e5Sespie 		    {
4783c87b03e5Sespie 		      if (s->left == p)
4784c87b03e5Sespie 			s->left = r;
4785c87b03e5Sespie 		      else
4786c87b03e5Sespie 			s->right = r;
4787c87b03e5Sespie 		    }
4788c87b03e5Sespie 		  else
4789c87b03e5Sespie 		    case_stack->data.case_stmt.case_list = r;
4790c87b03e5Sespie 		}
4791c87b03e5Sespie 	      else
4792c87b03e5Sespie 		/* r->balance == +1 */
4793c87b03e5Sespie 		{
4794c87b03e5Sespie 		  /* LR-Rotation */
4795c87b03e5Sespie 
4796c87b03e5Sespie 		  int b2;
4797c87b03e5Sespie 		  struct case_node *t = r->right;
4798c87b03e5Sespie 
4799c87b03e5Sespie 		  if ((p->left = s = t->right))
4800c87b03e5Sespie 		    s->parent = p;
4801c87b03e5Sespie 
4802c87b03e5Sespie 		  t->right = p;
4803c87b03e5Sespie 		  if ((r->right = s = t->left))
4804c87b03e5Sespie 		    s->parent = r;
4805c87b03e5Sespie 
4806c87b03e5Sespie 		  t->left = r;
4807c87b03e5Sespie 		  b = t->balance;
4808c87b03e5Sespie 		  b2 = b < 0;
4809c87b03e5Sespie 		  p->balance = b2;
4810c87b03e5Sespie 		  b2 = -b2 - b;
4811c87b03e5Sespie 		  r->balance = b2;
4812c87b03e5Sespie 		  t->balance = 0;
4813c87b03e5Sespie 		  s = p->parent;
4814c87b03e5Sespie 		  p->parent = t;
4815c87b03e5Sespie 		  r->parent = t;
4816c87b03e5Sespie 
4817c87b03e5Sespie 		  if ((t->parent = s))
4818c87b03e5Sespie 		    {
4819c87b03e5Sespie 		      if (s->left == p)
4820c87b03e5Sespie 			s->left = t;
4821c87b03e5Sespie 		      else
4822c87b03e5Sespie 			s->right = t;
4823c87b03e5Sespie 		    }
4824c87b03e5Sespie 		  else
4825c87b03e5Sespie 		    case_stack->data.case_stmt.case_list = t;
4826c87b03e5Sespie 		}
4827c87b03e5Sespie 	      break;
4828c87b03e5Sespie 	    }
4829c87b03e5Sespie 
4830c87b03e5Sespie 	  else
4831c87b03e5Sespie 	    {
4832c87b03e5Sespie 	      /* p->balance == +1; growth of left side balances the node.  */
4833c87b03e5Sespie 	      p->balance = 0;
4834c87b03e5Sespie 	      break;
4835c87b03e5Sespie 	    }
4836c87b03e5Sespie 	}
4837c87b03e5Sespie       else
4838c87b03e5Sespie 	/* r == p->right */
4839c87b03e5Sespie 	{
4840c87b03e5Sespie 	  int b;
4841c87b03e5Sespie 
4842c87b03e5Sespie 	  if (! (b = p->balance))
4843c87b03e5Sespie 	    /* Growth propagation from right side.  */
4844c87b03e5Sespie 	    p->balance++;
4845c87b03e5Sespie 	  else if (b > 0)
4846c87b03e5Sespie 	    {
4847c87b03e5Sespie 	      if (r->balance > 0)
4848c87b03e5Sespie 		{
4849c87b03e5Sespie 		  /* L-Rotation */
4850c87b03e5Sespie 
4851c87b03e5Sespie 		  if ((p->right = s = r->left))
4852c87b03e5Sespie 		    s->parent = p;
4853c87b03e5Sespie 
4854c87b03e5Sespie 		  r->left = p;
4855c87b03e5Sespie 		  p->balance = 0;
4856c87b03e5Sespie 		  r->balance = 0;
4857c87b03e5Sespie 		  s = p->parent;
4858c87b03e5Sespie 		  p->parent = r;
4859c87b03e5Sespie 		  if ((r->parent = s))
4860c87b03e5Sespie 		    {
4861c87b03e5Sespie 		      if (s->left == p)
4862c87b03e5Sespie 			s->left = r;
4863c87b03e5Sespie 		      else
4864c87b03e5Sespie 			s->right = r;
4865c87b03e5Sespie 		    }
4866c87b03e5Sespie 
4867c87b03e5Sespie 		  else
4868c87b03e5Sespie 		    case_stack->data.case_stmt.case_list = r;
4869c87b03e5Sespie 		}
4870c87b03e5Sespie 
4871c87b03e5Sespie 	      else
4872c87b03e5Sespie 		/* r->balance == -1 */
4873c87b03e5Sespie 		{
4874c87b03e5Sespie 		  /* RL-Rotation */
4875c87b03e5Sespie 		  int b2;
4876c87b03e5Sespie 		  struct case_node *t = r->left;
4877c87b03e5Sespie 
4878c87b03e5Sespie 		  if ((p->right = s = t->left))
4879c87b03e5Sespie 		    s->parent = p;
4880c87b03e5Sespie 
4881c87b03e5Sespie 		  t->left = p;
4882c87b03e5Sespie 
4883c87b03e5Sespie 		  if ((r->left = s = t->right))
4884c87b03e5Sespie 		    s->parent = r;
4885c87b03e5Sespie 
4886c87b03e5Sespie 		  t->right = r;
4887c87b03e5Sespie 		  b = t->balance;
4888c87b03e5Sespie 		  b2 = b < 0;
4889c87b03e5Sespie 		  r->balance = b2;
4890c87b03e5Sespie 		  b2 = -b2 - b;
4891c87b03e5Sespie 		  p->balance = b2;
4892c87b03e5Sespie 		  t->balance = 0;
4893c87b03e5Sespie 		  s = p->parent;
4894c87b03e5Sespie 		  p->parent = t;
4895c87b03e5Sespie 		  r->parent = t;
4896c87b03e5Sespie 
4897c87b03e5Sespie 		  if ((t->parent = s))
4898c87b03e5Sespie 		    {
4899c87b03e5Sespie 		      if (s->left == p)
4900c87b03e5Sespie 			s->left = t;
4901c87b03e5Sespie 		      else
4902c87b03e5Sespie 			s->right = t;
4903c87b03e5Sespie 		    }
4904c87b03e5Sespie 
4905c87b03e5Sespie 		  else
4906c87b03e5Sespie 		    case_stack->data.case_stmt.case_list = t;
4907c87b03e5Sespie 		}
4908c87b03e5Sespie 	      break;
4909c87b03e5Sespie 	    }
4910c87b03e5Sespie 	  else
4911c87b03e5Sespie 	    {
4912c87b03e5Sespie 	      /* p->balance == -1; growth of right side balances the node.  */
4913c87b03e5Sespie 	      p->balance = 0;
4914c87b03e5Sespie 	      break;
4915c87b03e5Sespie 	    }
4916c87b03e5Sespie 	}
4917c87b03e5Sespie 
4918c87b03e5Sespie       r = p;
4919c87b03e5Sespie       p = p->parent;
4920c87b03e5Sespie     }
4921c87b03e5Sespie 
4922c87b03e5Sespie   return 0;
4923c87b03e5Sespie }
4924c87b03e5Sespie 
4925c87b03e5Sespie /* Returns the number of possible values of TYPE.
4926c87b03e5Sespie    Returns -1 if the number is unknown, variable, or if the number does not
4927c87b03e5Sespie    fit in a HOST_WIDE_INT.
4928c87b03e5Sespie    Sets *SPARSENESS to 2 if TYPE is an ENUMERAL_TYPE whose values
4929c87b03e5Sespie    do not increase monotonically (there may be duplicates);
4930c87b03e5Sespie    to 1 if the values increase monotonically, but not always by 1;
4931c87b03e5Sespie    otherwise sets it to 0.  */
4932c87b03e5Sespie 
4933c87b03e5Sespie HOST_WIDE_INT
all_cases_count(type,sparseness)4934c87b03e5Sespie all_cases_count (type, sparseness)
4935c87b03e5Sespie      tree type;
4936c87b03e5Sespie      int *sparseness;
4937c87b03e5Sespie {
4938c87b03e5Sespie   tree t;
4939c87b03e5Sespie   HOST_WIDE_INT count, minval, lastval;
4940c87b03e5Sespie 
4941c87b03e5Sespie   *sparseness = 0;
4942c87b03e5Sespie 
4943c87b03e5Sespie   switch (TREE_CODE (type))
4944c87b03e5Sespie     {
4945c87b03e5Sespie     case BOOLEAN_TYPE:
4946c87b03e5Sespie       count = 2;
4947c87b03e5Sespie       break;
4948c87b03e5Sespie 
4949c87b03e5Sespie     case CHAR_TYPE:
4950c87b03e5Sespie       count = 1 << BITS_PER_UNIT;
4951c87b03e5Sespie       break;
4952c87b03e5Sespie 
4953c87b03e5Sespie     default:
4954c87b03e5Sespie     case INTEGER_TYPE:
4955c87b03e5Sespie       if (TYPE_MAX_VALUE (type) != 0
4956c87b03e5Sespie 	  && 0 != (t = fold (build (MINUS_EXPR, type, TYPE_MAX_VALUE (type),
4957c87b03e5Sespie 				    TYPE_MIN_VALUE (type))))
4958c87b03e5Sespie 	  && 0 != (t = fold (build (PLUS_EXPR, type, t,
4959c87b03e5Sespie 				    convert (type, integer_zero_node))))
4960c87b03e5Sespie 	  && host_integerp (t, 1))
4961c87b03e5Sespie 	count = tree_low_cst (t, 1);
4962c87b03e5Sespie       else
4963c87b03e5Sespie 	return -1;
4964c87b03e5Sespie       break;
4965c87b03e5Sespie 
4966c87b03e5Sespie     case ENUMERAL_TYPE:
4967c87b03e5Sespie       /* Don't waste time with enumeral types with huge values.  */
4968c87b03e5Sespie       if (! host_integerp (TYPE_MIN_VALUE (type), 0)
4969c87b03e5Sespie 	  || TYPE_MAX_VALUE (type) == 0
4970c87b03e5Sespie 	  || ! host_integerp (TYPE_MAX_VALUE (type), 0))
4971c87b03e5Sespie 	return -1;
4972c87b03e5Sespie 
4973c87b03e5Sespie       lastval = minval = tree_low_cst (TYPE_MIN_VALUE (type), 0);
4974c87b03e5Sespie       count = 0;
4975c87b03e5Sespie 
4976c87b03e5Sespie       for (t = TYPE_VALUES (type); t != NULL_TREE; t = TREE_CHAIN (t))
4977c87b03e5Sespie 	{
4978c87b03e5Sespie 	  HOST_WIDE_INT thisval = tree_low_cst (TREE_VALUE (t), 0);
4979c87b03e5Sespie 
4980c87b03e5Sespie 	  if (*sparseness == 2 || thisval <= lastval)
4981c87b03e5Sespie 	    *sparseness = 2;
4982c87b03e5Sespie 	  else if (thisval != minval + count)
4983c87b03e5Sespie 	    *sparseness = 1;
4984c87b03e5Sespie 
4985c87b03e5Sespie 	  lastval = thisval;
4986c87b03e5Sespie 	  count++;
4987c87b03e5Sespie 	}
4988c87b03e5Sespie     }
4989c87b03e5Sespie 
4990c87b03e5Sespie   return count;
4991c87b03e5Sespie }
4992c87b03e5Sespie 
4993c87b03e5Sespie #define BITARRAY_TEST(ARRAY, INDEX) \
4994c87b03e5Sespie   ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
4995c87b03e5Sespie 			  & (1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR)))
4996c87b03e5Sespie #define BITARRAY_SET(ARRAY, INDEX) \
4997c87b03e5Sespie   ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
4998c87b03e5Sespie 			  |= 1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR))
4999c87b03e5Sespie 
5000c87b03e5Sespie /* Set the elements of the bitstring CASES_SEEN (which has length COUNT),
5001c87b03e5Sespie    with the case values we have seen, assuming the case expression
5002c87b03e5Sespie    has the given TYPE.
5003c87b03e5Sespie    SPARSENESS is as determined by all_cases_count.
5004c87b03e5Sespie 
5005c87b03e5Sespie    The time needed is proportional to COUNT, unless
5006c87b03e5Sespie    SPARSENESS is 2, in which case quadratic time is needed.  */
5007c87b03e5Sespie 
5008c87b03e5Sespie void
mark_seen_cases(type,cases_seen,count,sparseness)5009c87b03e5Sespie mark_seen_cases (type, cases_seen, count, sparseness)
5010c87b03e5Sespie      tree type;
5011c87b03e5Sespie      unsigned char *cases_seen;
5012c87b03e5Sespie      HOST_WIDE_INT count;
5013c87b03e5Sespie      int sparseness;
5014c87b03e5Sespie {
5015c87b03e5Sespie   tree next_node_to_try = NULL_TREE;
5016c87b03e5Sespie   HOST_WIDE_INT next_node_offset = 0;
5017c87b03e5Sespie 
5018c87b03e5Sespie   struct case_node *n, *root = case_stack->data.case_stmt.case_list;
5019c87b03e5Sespie   tree val = make_node (INTEGER_CST);
5020c87b03e5Sespie 
5021c87b03e5Sespie   TREE_TYPE (val) = type;
5022c87b03e5Sespie   if (! root)
5023c87b03e5Sespie     /* Do nothing.  */
5024c87b03e5Sespie     ;
5025c87b03e5Sespie   else if (sparseness == 2)
5026c87b03e5Sespie     {
5027c87b03e5Sespie       tree t;
5028c87b03e5Sespie       unsigned HOST_WIDE_INT xlo;
5029c87b03e5Sespie 
5030c87b03e5Sespie       /* This less efficient loop is only needed to handle
5031c87b03e5Sespie 	 duplicate case values (multiple enum constants
5032c87b03e5Sespie 	 with the same value).  */
5033c87b03e5Sespie       TREE_TYPE (val) = TREE_TYPE (root->low);
5034c87b03e5Sespie       for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
5035c87b03e5Sespie 	   t = TREE_CHAIN (t), xlo++)
5036c87b03e5Sespie 	{
5037c87b03e5Sespie 	  TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (TREE_VALUE (t));
5038c87b03e5Sespie 	  TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (TREE_VALUE (t));
5039c87b03e5Sespie 	  n = root;
5040c87b03e5Sespie 	  do
5041c87b03e5Sespie 	    {
5042c87b03e5Sespie 	      /* Keep going past elements distinctly greater than VAL.  */
5043c87b03e5Sespie 	      if (tree_int_cst_lt (val, n->low))
5044c87b03e5Sespie 		n = n->left;
5045c87b03e5Sespie 
5046c87b03e5Sespie 	      /* or distinctly less than VAL.  */
5047c87b03e5Sespie 	      else if (tree_int_cst_lt (n->high, val))
5048c87b03e5Sespie 		n = n->right;
5049c87b03e5Sespie 
5050c87b03e5Sespie 	      else
5051c87b03e5Sespie 		{
5052c87b03e5Sespie 		  /* We have found a matching range.  */
5053c87b03e5Sespie 		  BITARRAY_SET (cases_seen, xlo);
5054c87b03e5Sespie 		  break;
5055c87b03e5Sespie 		}
5056c87b03e5Sespie 	    }
5057c87b03e5Sespie 	  while (n);
5058c87b03e5Sespie 	}
5059c87b03e5Sespie     }
5060c87b03e5Sespie   else
5061c87b03e5Sespie     {
5062c87b03e5Sespie       if (root->left)
5063c87b03e5Sespie 	case_stack->data.case_stmt.case_list = root = case_tree2list (root, 0);
5064c87b03e5Sespie 
5065c87b03e5Sespie       for (n = root; n; n = n->right)
5066c87b03e5Sespie 	{
5067c87b03e5Sespie 	  TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
5068c87b03e5Sespie 	  TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
5069c87b03e5Sespie 	  while (! tree_int_cst_lt (n->high, val))
5070c87b03e5Sespie 	    {
5071c87b03e5Sespie 	      /* Calculate (into xlo) the "offset" of the integer (val).
5072c87b03e5Sespie 		 The element with lowest value has offset 0, the next smallest
5073c87b03e5Sespie 		 element has offset 1, etc.  */
5074c87b03e5Sespie 
5075c87b03e5Sespie 	      unsigned HOST_WIDE_INT xlo;
5076c87b03e5Sespie 	      HOST_WIDE_INT xhi;
5077c87b03e5Sespie 	      tree t;
5078c87b03e5Sespie 
5079c87b03e5Sespie 	      if (sparseness && TYPE_VALUES (type) != NULL_TREE)
5080c87b03e5Sespie 		{
5081c87b03e5Sespie 		  /* The TYPE_VALUES will be in increasing order, so
5082c87b03e5Sespie 		     starting searching where we last ended.  */
5083c87b03e5Sespie 		  t = next_node_to_try;
5084c87b03e5Sespie 		  xlo = next_node_offset;
5085c87b03e5Sespie 		  xhi = 0;
5086c87b03e5Sespie 		  for (;;)
5087c87b03e5Sespie 		    {
5088c87b03e5Sespie 		      if (t == NULL_TREE)
5089c87b03e5Sespie 			{
5090c87b03e5Sespie 			  t = TYPE_VALUES (type);
5091c87b03e5Sespie 			  xlo = 0;
5092c87b03e5Sespie 			}
5093c87b03e5Sespie 		      if (tree_int_cst_equal (val, TREE_VALUE (t)))
5094c87b03e5Sespie 			{
5095c87b03e5Sespie 			  next_node_to_try = TREE_CHAIN (t);
5096c87b03e5Sespie 			  next_node_offset = xlo + 1;
5097c87b03e5Sespie 			  break;
5098c87b03e5Sespie 			}
5099c87b03e5Sespie 		      xlo++;
5100c87b03e5Sespie 		      t = TREE_CHAIN (t);
5101c87b03e5Sespie 		      if (t == next_node_to_try)
5102c87b03e5Sespie 			{
5103c87b03e5Sespie 			  xlo = -1;
5104c87b03e5Sespie 			  break;
5105c87b03e5Sespie 			}
5106c87b03e5Sespie 		    }
5107c87b03e5Sespie 		}
5108c87b03e5Sespie 	      else
5109c87b03e5Sespie 		{
5110c87b03e5Sespie 		  t = TYPE_MIN_VALUE (type);
5111c87b03e5Sespie 		  if (t)
5112c87b03e5Sespie 		    neg_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t),
5113c87b03e5Sespie 				&xlo, &xhi);
5114c87b03e5Sespie 		  else
5115c87b03e5Sespie 		    xlo = xhi = 0;
5116c87b03e5Sespie 		  add_double (xlo, xhi,
5117c87b03e5Sespie 			      TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
5118c87b03e5Sespie 			      &xlo, &xhi);
5119c87b03e5Sespie 		}
5120c87b03e5Sespie 
5121c87b03e5Sespie 	      if (xhi == 0 && xlo < (unsigned HOST_WIDE_INT) count)
5122c87b03e5Sespie 		BITARRAY_SET (cases_seen, xlo);
5123c87b03e5Sespie 
5124c87b03e5Sespie 	      add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
5125c87b03e5Sespie 			  1, 0,
5126c87b03e5Sespie 			  &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
5127c87b03e5Sespie 	    }
5128c87b03e5Sespie 	}
5129c87b03e5Sespie     }
5130c87b03e5Sespie }
5131c87b03e5Sespie 
5132c87b03e5Sespie /* Given a switch statement with an expression that is an enumeration
5133c87b03e5Sespie    type, warn if any of the enumeration type's literals are not
5134c87b03e5Sespie    covered by the case expressions of the switch.  Also, warn if there
5135c87b03e5Sespie    are any extra switch cases that are *not* elements of the
5136c87b03e5Sespie    enumerated type.
5137c87b03e5Sespie 
5138c87b03e5Sespie    Historical note:
5139c87b03e5Sespie 
5140c87b03e5Sespie    At one stage this function would: ``If all enumeration literals
5141c87b03e5Sespie    were covered by the case expressions, turn one of the expressions
5142c87b03e5Sespie    into the default expression since it should not be possible to fall
5143c87b03e5Sespie    through such a switch.''
5144c87b03e5Sespie 
5145c87b03e5Sespie    That code has since been removed as: ``This optimization is
5146c87b03e5Sespie    disabled because it causes valid programs to fail.  ANSI C does not
5147c87b03e5Sespie    guarantee that an expression with enum type will have a value that
5148c87b03e5Sespie    is the same as one of the enumeration literals.''  */
5149c87b03e5Sespie 
5150c87b03e5Sespie void
check_for_full_enumeration_handling(type)5151c87b03e5Sespie check_for_full_enumeration_handling (type)
5152c87b03e5Sespie      tree type;
5153c87b03e5Sespie {
5154c87b03e5Sespie   struct case_node *n;
5155c87b03e5Sespie   tree chain;
5156c87b03e5Sespie 
5157c87b03e5Sespie   /* True iff the selector type is a numbered set mode.  */
5158c87b03e5Sespie   int sparseness = 0;
5159c87b03e5Sespie 
5160c87b03e5Sespie   /* The number of possible selector values.  */
5161c87b03e5Sespie   HOST_WIDE_INT size;
5162c87b03e5Sespie 
5163c87b03e5Sespie   /* For each possible selector value. a one iff it has been matched
5164c87b03e5Sespie      by a case value alternative.  */
5165c87b03e5Sespie   unsigned char *cases_seen;
5166c87b03e5Sespie 
5167c87b03e5Sespie   /* The allocated size of cases_seen, in chars.  */
5168c87b03e5Sespie   HOST_WIDE_INT bytes_needed;
5169c87b03e5Sespie 
5170c87b03e5Sespie   size = all_cases_count (type, &sparseness);
5171c87b03e5Sespie   bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
5172c87b03e5Sespie 
5173c87b03e5Sespie   if (size > 0 && size < 600000
5174c87b03e5Sespie       /* We deliberately use calloc here, not cmalloc, so that we can suppress
5175c87b03e5Sespie 	 this optimization if we don't have enough memory rather than
5176c87b03e5Sespie 	 aborting, as xmalloc would do.  */
5177c87b03e5Sespie       && (cases_seen =
5178c87b03e5Sespie 	  (unsigned char *) really_call_calloc (bytes_needed, 1)) != NULL)
5179c87b03e5Sespie     {
5180c87b03e5Sespie       HOST_WIDE_INT i;
5181c87b03e5Sespie       tree v = TYPE_VALUES (type);
5182c87b03e5Sespie 
5183c87b03e5Sespie       /* The time complexity of this code is normally O(N), where
5184c87b03e5Sespie 	 N being the number of members in the enumerated type.
5185c87b03e5Sespie 	 However, if type is an ENUMERAL_TYPE whose values do not
5186c87b03e5Sespie 	 increase monotonically, O(N*log(N)) time may be needed.  */
5187c87b03e5Sespie 
5188c87b03e5Sespie       mark_seen_cases (type, cases_seen, size, sparseness);
5189c87b03e5Sespie 
5190c87b03e5Sespie       for (i = 0; v != NULL_TREE && i < size; i++, v = TREE_CHAIN (v))
5191c87b03e5Sespie 	if (BITARRAY_TEST (cases_seen, i) == 0)
5192c87b03e5Sespie 	  warning ("enumeration value `%s' not handled in switch",
5193c87b03e5Sespie 		   IDENTIFIER_POINTER (TREE_PURPOSE (v)));
5194c87b03e5Sespie 
5195c87b03e5Sespie       free (cases_seen);
5196c87b03e5Sespie     }
5197c87b03e5Sespie 
5198c87b03e5Sespie   /* Now we go the other way around; we warn if there are case
5199c87b03e5Sespie      expressions that don't correspond to enumerators.  This can
5200c87b03e5Sespie      occur since C and C++ don't enforce type-checking of
5201c87b03e5Sespie      assignments to enumeration variables.  */
5202c87b03e5Sespie 
5203c87b03e5Sespie   if (case_stack->data.case_stmt.case_list
5204c87b03e5Sespie       && case_stack->data.case_stmt.case_list->left)
5205c87b03e5Sespie     case_stack->data.case_stmt.case_list
5206c87b03e5Sespie       = case_tree2list (case_stack->data.case_stmt.case_list, 0);
5207c87b03e5Sespie   for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
5208c87b03e5Sespie     {
5209c87b03e5Sespie       for (chain = TYPE_VALUES (type);
5210c87b03e5Sespie 	   chain && !tree_int_cst_equal (n->low, TREE_VALUE (chain));
5211c87b03e5Sespie 	   chain = TREE_CHAIN (chain))
5212c87b03e5Sespie 	;
5213c87b03e5Sespie 
5214c87b03e5Sespie       if (!chain)
5215c87b03e5Sespie 	{
5216c87b03e5Sespie 	  if (TYPE_NAME (type) == 0)
5217c87b03e5Sespie 	    warning ("case value `%ld' not in enumerated type",
5218c87b03e5Sespie 		     (long) TREE_INT_CST_LOW (n->low));
5219c87b03e5Sespie 	  else
5220c87b03e5Sespie 	    warning ("case value `%ld' not in enumerated type `%s'",
5221c87b03e5Sespie 		     (long) TREE_INT_CST_LOW (n->low),
5222c87b03e5Sespie 		     IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
5223c87b03e5Sespie 					  == IDENTIFIER_NODE)
5224c87b03e5Sespie 					 ? TYPE_NAME (type)
5225c87b03e5Sespie 					 : DECL_NAME (TYPE_NAME (type))));
5226c87b03e5Sespie 	}
5227c87b03e5Sespie       if (!tree_int_cst_equal (n->low, n->high))
5228c87b03e5Sespie 	{
5229c87b03e5Sespie 	  for (chain = TYPE_VALUES (type);
5230c87b03e5Sespie 	       chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
5231c87b03e5Sespie 	       chain = TREE_CHAIN (chain))
5232c87b03e5Sespie 	    ;
5233c87b03e5Sespie 
5234c87b03e5Sespie 	  if (!chain)
5235c87b03e5Sespie 	    {
5236c87b03e5Sespie 	      if (TYPE_NAME (type) == 0)
5237c87b03e5Sespie 		warning ("case value `%ld' not in enumerated type",
5238c87b03e5Sespie 			 (long) TREE_INT_CST_LOW (n->high));
5239c87b03e5Sespie 	      else
5240c87b03e5Sespie 		warning ("case value `%ld' not in enumerated type `%s'",
5241c87b03e5Sespie 			 (long) TREE_INT_CST_LOW (n->high),
5242c87b03e5Sespie 			 IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
5243c87b03e5Sespie 					      == IDENTIFIER_NODE)
5244c87b03e5Sespie 					     ? TYPE_NAME (type)
5245c87b03e5Sespie 					     : DECL_NAME (TYPE_NAME (type))));
5246c87b03e5Sespie 	    }
5247c87b03e5Sespie 	}
5248c87b03e5Sespie     }
5249c87b03e5Sespie }
5250c87b03e5Sespie 
5251c87b03e5Sespie 
5252c87b03e5Sespie 
5253c87b03e5Sespie /* Terminate a case (Pascal) or switch (C) statement
5254c87b03e5Sespie    in which ORIG_INDEX is the expression to be tested.
5255c87b03e5Sespie    If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
5256c87b03e5Sespie    type as given in the source before any compiler conversions.
5257c87b03e5Sespie    Generate the code to test it and jump to the right place.  */
5258c87b03e5Sespie 
5259c87b03e5Sespie void
expand_end_case_type(orig_index,orig_type)5260c87b03e5Sespie expand_end_case_type (orig_index, orig_type)
5261c87b03e5Sespie      tree orig_index, orig_type;
5262c87b03e5Sespie {
5263c87b03e5Sespie   tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
5264c87b03e5Sespie   rtx default_label = 0;
5265c87b03e5Sespie   struct case_node *n;
5266c87b03e5Sespie   unsigned int count;
5267c87b03e5Sespie   rtx index;
5268c87b03e5Sespie   rtx table_label;
5269c87b03e5Sespie   int ncases;
5270c87b03e5Sespie   rtx *labelvec;
5271c87b03e5Sespie   int i;
5272c87b03e5Sespie   rtx before_case, end;
5273c87b03e5Sespie   struct nesting *thiscase = case_stack;
5274c87b03e5Sespie   tree index_expr, index_type;
5275c87b03e5Sespie   int unsignedp;
5276c87b03e5Sespie 
5277c87b03e5Sespie   /* Don't crash due to previous errors.  */
5278c87b03e5Sespie   if (thiscase == NULL)
5279c87b03e5Sespie     return;
5280c87b03e5Sespie 
5281c87b03e5Sespie   table_label = gen_label_rtx ();
5282c87b03e5Sespie   index_expr = thiscase->data.case_stmt.index_expr;
5283c87b03e5Sespie   index_type = TREE_TYPE (index_expr);
5284c87b03e5Sespie   unsignedp = TREE_UNSIGNED (index_type);
5285c87b03e5Sespie   if (orig_type == NULL)
5286c87b03e5Sespie     orig_type = TREE_TYPE (orig_index);
5287c87b03e5Sespie 
5288c87b03e5Sespie   do_pending_stack_adjust ();
5289c87b03e5Sespie 
5290c87b03e5Sespie   /* This might get a spurious warning in the presence of a syntax error;
5291c87b03e5Sespie      it could be fixed by moving the call to check_seenlabel after the
5292c87b03e5Sespie      check for error_mark_node, and copying the code of check_seenlabel that
5293c87b03e5Sespie      deals with case_stack->data.case_stmt.line_number_status /
5294c87b03e5Sespie      restore_line_number_status in front of the call to end_cleanup_deferral;
5295c87b03e5Sespie      However, this might miss some useful warnings in the presence of
5296c87b03e5Sespie      non-syntax errors.  */
5297c87b03e5Sespie   check_seenlabel ();
5298c87b03e5Sespie 
5299c87b03e5Sespie   /* An ERROR_MARK occurs for various reasons including invalid data type.  */
5300c87b03e5Sespie   if (index_type != error_mark_node)
5301c87b03e5Sespie     {
5302c87b03e5Sespie       /* If the switch expression was an enumerated type, check that
5303c87b03e5Sespie 	 exactly all enumeration literals are covered by the cases.
5304c87b03e5Sespie 	 The check is made when -Wswitch was specified and there is no
5305c87b03e5Sespie 	 default case, or when -Wswitch-enum was specified.  */
5306c87b03e5Sespie       if (((warn_switch && !thiscase->data.case_stmt.default_label)
5307c87b03e5Sespie 	   || warn_switch_enum)
5308c87b03e5Sespie 	  && TREE_CODE (orig_type) == ENUMERAL_TYPE
5309c87b03e5Sespie 	  && TREE_CODE (index_expr) != INTEGER_CST)
5310c87b03e5Sespie 	check_for_full_enumeration_handling (orig_type);
5311c87b03e5Sespie 
5312c87b03e5Sespie       if (warn_switch_default && !thiscase->data.case_stmt.default_label)
5313c87b03e5Sespie 	warning ("switch missing default case");
5314c87b03e5Sespie 
5315c87b03e5Sespie       /* If we don't have a default-label, create one here,
5316c87b03e5Sespie 	 after the body of the switch.  */
5317c87b03e5Sespie       if (thiscase->data.case_stmt.default_label == 0)
5318c87b03e5Sespie 	{
5319c87b03e5Sespie 	  thiscase->data.case_stmt.default_label
5320c87b03e5Sespie 	    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
5321c87b03e5Sespie 	  expand_label (thiscase->data.case_stmt.default_label);
5322c87b03e5Sespie 	}
5323c87b03e5Sespie       default_label = label_rtx (thiscase->data.case_stmt.default_label);
5324c87b03e5Sespie 
5325c87b03e5Sespie       before_case = get_last_insn ();
5326c87b03e5Sespie 
5327c87b03e5Sespie       if (thiscase->data.case_stmt.case_list
5328c87b03e5Sespie 	  && thiscase->data.case_stmt.case_list->left)
5329c87b03e5Sespie 	thiscase->data.case_stmt.case_list
5330c87b03e5Sespie 	  = case_tree2list (thiscase->data.case_stmt.case_list, 0);
5331c87b03e5Sespie 
5332c87b03e5Sespie       /* Simplify the case-list before we count it.  */
5333c87b03e5Sespie       group_case_nodes (thiscase->data.case_stmt.case_list);
5334c87b03e5Sespie 
5335c87b03e5Sespie       /* Get upper and lower bounds of case values.
5336c87b03e5Sespie 	 Also convert all the case values to the index expr's data type.  */
5337c87b03e5Sespie 
5338c87b03e5Sespie       count = 0;
5339c87b03e5Sespie       for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
5340c87b03e5Sespie 	{
5341c87b03e5Sespie 	  /* Check low and high label values are integers.  */
5342c87b03e5Sespie 	  if (TREE_CODE (n->low) != INTEGER_CST)
5343c87b03e5Sespie 	    abort ();
5344c87b03e5Sespie 	  if (TREE_CODE (n->high) != INTEGER_CST)
5345c87b03e5Sespie 	    abort ();
5346c87b03e5Sespie 
5347c87b03e5Sespie 	  n->low = convert (index_type, n->low);
5348c87b03e5Sespie 	  n->high = convert (index_type, n->high);
5349c87b03e5Sespie 
5350c87b03e5Sespie 	  /* Count the elements and track the largest and smallest
5351c87b03e5Sespie 	     of them (treating them as signed even if they are not).  */
5352c87b03e5Sespie 	  if (count++ == 0)
5353c87b03e5Sespie 	    {
5354c87b03e5Sespie 	      minval = n->low;
5355c87b03e5Sespie 	      maxval = n->high;
5356c87b03e5Sespie 	    }
5357c87b03e5Sespie 	  else
5358c87b03e5Sespie 	    {
5359c87b03e5Sespie 	      if (INT_CST_LT (n->low, minval))
5360c87b03e5Sespie 		minval = n->low;
5361c87b03e5Sespie 	      if (INT_CST_LT (maxval, n->high))
5362c87b03e5Sespie 		maxval = n->high;
5363c87b03e5Sespie 	    }
5364c87b03e5Sespie 	  /* A range counts double, since it requires two compares.  */
5365c87b03e5Sespie 	  if (! tree_int_cst_equal (n->low, n->high))
5366c87b03e5Sespie 	    count++;
5367c87b03e5Sespie 	}
5368c87b03e5Sespie 
5369c87b03e5Sespie       /* Compute span of values.  */
5370c87b03e5Sespie       if (count != 0)
5371c87b03e5Sespie 	range = fold (build (MINUS_EXPR, index_type, maxval, minval));
5372c87b03e5Sespie 
5373c87b03e5Sespie       end_cleanup_deferral ();
5374c87b03e5Sespie 
5375c87b03e5Sespie       if (count == 0)
5376c87b03e5Sespie 	{
5377c87b03e5Sespie 	  expand_expr (index_expr, const0_rtx, VOIDmode, 0);
5378c87b03e5Sespie 	  emit_queue ();
5379c87b03e5Sespie 	  emit_jump (default_label);
5380c87b03e5Sespie 	}
5381c87b03e5Sespie 
5382c87b03e5Sespie       /* If range of values is much bigger than number of values,
5383c87b03e5Sespie 	 make a sequence of conditional branches instead of a dispatch.
5384c87b03e5Sespie 	 If the switch-index is a constant, do it this way
5385c87b03e5Sespie 	 because we can optimize it.  */
5386c87b03e5Sespie 
5387c87b03e5Sespie       else if (count < case_values_threshold ()
5388c87b03e5Sespie 	       || compare_tree_int (range, 10 * count) > 0
5389c87b03e5Sespie 	       /* RANGE may be signed, and really large ranges will show up
5390c87b03e5Sespie 		  as negative numbers.  */
5391c87b03e5Sespie 	       || compare_tree_int (range, 0) < 0
5392c87b03e5Sespie #ifndef ASM_OUTPUT_ADDR_DIFF_ELT
5393c87b03e5Sespie 	       || flag_pic
5394c87b03e5Sespie #endif
5395c87b03e5Sespie 	       || TREE_CODE (index_expr) == INTEGER_CST
5396c87b03e5Sespie 	       || (TREE_CODE (index_expr) == COMPOUND_EXPR
5397c87b03e5Sespie 		   && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST))
5398c87b03e5Sespie 	{
5399c87b03e5Sespie 	  index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
5400c87b03e5Sespie 
5401c87b03e5Sespie 	  /* If the index is a short or char that we do not have
5402c87b03e5Sespie 	     an insn to handle comparisons directly, convert it to
5403c87b03e5Sespie 	     a full integer now, rather than letting each comparison
5404c87b03e5Sespie 	     generate the conversion.  */
5405c87b03e5Sespie 
5406c87b03e5Sespie 	  if (GET_MODE_CLASS (GET_MODE (index)) == MODE_INT
5407c87b03e5Sespie 	      && ! have_insn_for (COMPARE, GET_MODE (index)))
5408c87b03e5Sespie 	    {
5409c87b03e5Sespie 	      enum machine_mode wider_mode;
5410c87b03e5Sespie 	      for (wider_mode = GET_MODE (index); wider_mode != VOIDmode;
5411c87b03e5Sespie 		   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
5412c87b03e5Sespie 		if (have_insn_for (COMPARE, wider_mode))
5413c87b03e5Sespie 		  {
5414c87b03e5Sespie 		    index = convert_to_mode (wider_mode, index, unsignedp);
5415c87b03e5Sespie 		    break;
5416c87b03e5Sespie 		  }
5417c87b03e5Sespie 	    }
5418c87b03e5Sespie 
5419c87b03e5Sespie 	  emit_queue ();
5420c87b03e5Sespie 	  do_pending_stack_adjust ();
5421c87b03e5Sespie 
5422c87b03e5Sespie 	  index = protect_from_queue (index, 0);
5423c87b03e5Sespie 	  if (GET_CODE (index) == MEM)
5424c87b03e5Sespie 	    index = copy_to_reg (index);
5425c87b03e5Sespie 	  if (GET_CODE (index) == CONST_INT
5426c87b03e5Sespie 	      || TREE_CODE (index_expr) == INTEGER_CST)
5427c87b03e5Sespie 	    {
5428c87b03e5Sespie 	      /* Make a tree node with the proper constant value
5429c87b03e5Sespie 		 if we don't already have one.  */
5430c87b03e5Sespie 	      if (TREE_CODE (index_expr) != INTEGER_CST)
5431c87b03e5Sespie 		{
5432c87b03e5Sespie 		  index_expr
5433c87b03e5Sespie 		    = build_int_2 (INTVAL (index),
5434c87b03e5Sespie 				   unsignedp || INTVAL (index) >= 0 ? 0 : -1);
5435c87b03e5Sespie 		  index_expr = convert (index_type, index_expr);
5436c87b03e5Sespie 		}
5437c87b03e5Sespie 
5438c87b03e5Sespie 	      /* For constant index expressions we need only
5439c87b03e5Sespie 		 issue an unconditional branch to the appropriate
5440c87b03e5Sespie 		 target code.  The job of removing any unreachable
5441c87b03e5Sespie 		 code is left to the optimisation phase if the
5442c87b03e5Sespie 		 "-O" option is specified.  */
5443c87b03e5Sespie 	      for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
5444c87b03e5Sespie 		if (! tree_int_cst_lt (index_expr, n->low)
5445c87b03e5Sespie 		    && ! tree_int_cst_lt (n->high, index_expr))
5446c87b03e5Sespie 		  break;
5447c87b03e5Sespie 
5448c87b03e5Sespie 	      if (n)
5449c87b03e5Sespie 		emit_jump (label_rtx (n->code_label));
5450c87b03e5Sespie 	      else
5451c87b03e5Sespie 		emit_jump (default_label);
5452c87b03e5Sespie 	    }
5453c87b03e5Sespie 	  else
5454c87b03e5Sespie 	    {
5455c87b03e5Sespie 	      /* If the index expression is not constant we generate
5456c87b03e5Sespie 		 a binary decision tree to select the appropriate
5457c87b03e5Sespie 		 target code.  This is done as follows:
5458c87b03e5Sespie 
5459c87b03e5Sespie 		 The list of cases is rearranged into a binary tree,
5460c87b03e5Sespie 		 nearly optimal assuming equal probability for each case.
5461c87b03e5Sespie 
5462c87b03e5Sespie 		 The tree is transformed into RTL, eliminating
5463c87b03e5Sespie 		 redundant test conditions at the same time.
5464c87b03e5Sespie 
5465c87b03e5Sespie 		 If program flow could reach the end of the
5466c87b03e5Sespie 		 decision tree an unconditional jump to the
5467c87b03e5Sespie 		 default code is emitted.  */
5468c87b03e5Sespie 
5469c87b03e5Sespie 	      use_cost_table
5470c87b03e5Sespie 		= (TREE_CODE (orig_type) != ENUMERAL_TYPE
5471c87b03e5Sespie 		   && estimate_case_costs (thiscase->data.case_stmt.case_list));
5472c87b03e5Sespie 	      balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL);
5473c87b03e5Sespie 	      emit_case_nodes (index, thiscase->data.case_stmt.case_list,
5474c87b03e5Sespie 			       default_label, index_type);
5475c87b03e5Sespie 	      emit_jump_if_reachable (default_label);
5476c87b03e5Sespie 	    }
5477c87b03e5Sespie 	}
5478c87b03e5Sespie       else
5479c87b03e5Sespie 	{
5480c87b03e5Sespie 	  if (! try_casesi (index_type, index_expr, minval, range,
5481c87b03e5Sespie 			    table_label, default_label))
5482c87b03e5Sespie 	    {
5483c87b03e5Sespie 	      index_type = thiscase->data.case_stmt.nominal_type;
5484c87b03e5Sespie 
5485c87b03e5Sespie 	      /* Index jumptables from zero for suitable values of
5486c87b03e5Sespie                  minval to avoid a subtraction.  */
5487c87b03e5Sespie 	      if (! optimize_size
5488c87b03e5Sespie 		  && compare_tree_int (minval, 0) > 0
5489c87b03e5Sespie 		  && compare_tree_int (minval, 3) < 0)
5490c87b03e5Sespie 		{
5491c87b03e5Sespie 		  minval = integer_zero_node;
5492c87b03e5Sespie 		  range = maxval;
5493c87b03e5Sespie 		}
5494c87b03e5Sespie 
5495c87b03e5Sespie 	      if (! try_tablejump (index_type, index_expr, minval, range,
5496c87b03e5Sespie 				   table_label, default_label))
5497c87b03e5Sespie 		abort ();
5498c87b03e5Sespie 	    }
5499c87b03e5Sespie 
5500c87b03e5Sespie 	  /* Get table of labels to jump to, in order of case index.  */
5501c87b03e5Sespie 
5502c87b03e5Sespie 	  ncases = tree_low_cst (range, 0) + 1;
5503c87b03e5Sespie 	  labelvec = (rtx *) alloca (ncases * sizeof (rtx));
5504c87b03e5Sespie 	  memset ((char *) labelvec, 0, ncases * sizeof (rtx));
5505c87b03e5Sespie 
5506c87b03e5Sespie 	  for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
5507c87b03e5Sespie 	    {
5508c87b03e5Sespie 	      /* Compute the low and high bounds relative to the minimum
5509c87b03e5Sespie 		 value since that should fit in a HOST_WIDE_INT while the
5510c87b03e5Sespie 		 actual values may not.  */
5511c87b03e5Sespie 	      HOST_WIDE_INT i_low
5512c87b03e5Sespie 		= tree_low_cst (fold (build (MINUS_EXPR, index_type,
5513c87b03e5Sespie 					     n->low, minval)), 1);
5514c87b03e5Sespie 	      HOST_WIDE_INT i_high
5515c87b03e5Sespie 		= tree_low_cst (fold (build (MINUS_EXPR, index_type,
5516c87b03e5Sespie 					     n->high, minval)), 1);
5517c87b03e5Sespie 	      HOST_WIDE_INT i;
5518c87b03e5Sespie 
5519c87b03e5Sespie 	      for (i = i_low; i <= i_high; i ++)
5520c87b03e5Sespie 		labelvec[i]
5521c87b03e5Sespie 		  = gen_rtx_LABEL_REF (Pmode, label_rtx (n->code_label));
5522c87b03e5Sespie 	    }
5523c87b03e5Sespie 
5524c87b03e5Sespie 	  /* Fill in the gaps with the default.  */
5525c87b03e5Sespie 	  for (i = 0; i < ncases; i++)
5526c87b03e5Sespie 	    if (labelvec[i] == 0)
5527c87b03e5Sespie 	      labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
5528c87b03e5Sespie 
5529c87b03e5Sespie 	  /* Output the table */
5530c87b03e5Sespie 	  emit_label (table_label);
5531c87b03e5Sespie 
5532c87b03e5Sespie 	  if (CASE_VECTOR_PC_RELATIVE || flag_pic)
5533c87b03e5Sespie 	    emit_jump_insn (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
5534c87b03e5Sespie 						   gen_rtx_LABEL_REF (Pmode, table_label),
5535c87b03e5Sespie 						   gen_rtvec_v (ncases, labelvec),
5536c87b03e5Sespie 						   const0_rtx, const0_rtx));
5537c87b03e5Sespie 	  else
5538c87b03e5Sespie 	    emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
5539c87b03e5Sespie 					      gen_rtvec_v (ncases, labelvec)));
5540c87b03e5Sespie 
5541c87b03e5Sespie 	  /* If the case insn drops through the table,
5542c87b03e5Sespie 	     after the table we must jump to the default-label.
5543c87b03e5Sespie 	     Otherwise record no drop-through after the table.  */
5544c87b03e5Sespie #ifdef CASE_DROPS_THROUGH
5545c87b03e5Sespie 	  emit_jump (default_label);
5546c87b03e5Sespie #else
5547c87b03e5Sespie 	  emit_barrier ();
5548c87b03e5Sespie #endif
5549c87b03e5Sespie 	}
5550c87b03e5Sespie 
5551c87b03e5Sespie       before_case = NEXT_INSN (before_case);
5552c87b03e5Sespie       end = get_last_insn ();
5553c87b03e5Sespie       if (squeeze_notes (&before_case, &end))
5554c87b03e5Sespie 	abort ();
5555c87b03e5Sespie       reorder_insns (before_case, end,
5556c87b03e5Sespie 		     thiscase->data.case_stmt.start);
5557c87b03e5Sespie     }
5558c87b03e5Sespie   else
5559c87b03e5Sespie     end_cleanup_deferral ();
5560c87b03e5Sespie 
5561c87b03e5Sespie   if (thiscase->exit_label)
5562c87b03e5Sespie     emit_label (thiscase->exit_label);
5563c87b03e5Sespie 
5564c87b03e5Sespie   POPSTACK (case_stack);
5565c87b03e5Sespie 
5566c87b03e5Sespie   free_temp_slots ();
5567c87b03e5Sespie }
5568c87b03e5Sespie 
5569c87b03e5Sespie /* Convert the tree NODE into a list linked by the right field, with the left
5570c87b03e5Sespie    field zeroed.  RIGHT is used for recursion; it is a list to be placed
5571c87b03e5Sespie    rightmost in the resulting list.  */
5572c87b03e5Sespie 
5573c87b03e5Sespie static struct case_node *
case_tree2list(node,right)5574c87b03e5Sespie case_tree2list (node, right)
5575c87b03e5Sespie      struct case_node *node, *right;
5576c87b03e5Sespie {
5577c87b03e5Sespie   struct case_node *left;
5578c87b03e5Sespie 
5579c87b03e5Sespie   if (node->right)
5580c87b03e5Sespie     right = case_tree2list (node->right, right);
5581c87b03e5Sespie 
5582c87b03e5Sespie   node->right = right;
5583c87b03e5Sespie   if ((left = node->left))
5584c87b03e5Sespie     {
5585c87b03e5Sespie       node->left = 0;
5586c87b03e5Sespie       return case_tree2list (left, node);
5587c87b03e5Sespie     }
5588c87b03e5Sespie 
5589c87b03e5Sespie   return node;
5590c87b03e5Sespie }
5591c87b03e5Sespie 
5592c87b03e5Sespie /* Generate code to jump to LABEL if OP1 and OP2 are equal.  */
5593c87b03e5Sespie 
5594c87b03e5Sespie static void
do_jump_if_equal(op1,op2,label,unsignedp)5595c87b03e5Sespie do_jump_if_equal (op1, op2, label, unsignedp)
5596c87b03e5Sespie      rtx op1, op2, label;
5597c87b03e5Sespie      int unsignedp;
5598c87b03e5Sespie {
5599c87b03e5Sespie   if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
5600c87b03e5Sespie     {
5601c87b03e5Sespie       if (INTVAL (op1) == INTVAL (op2))
5602c87b03e5Sespie 	emit_jump (label);
5603c87b03e5Sespie     }
5604c87b03e5Sespie   else
5605c87b03e5Sespie     emit_cmp_and_jump_insns (op1, op2, EQ, NULL_RTX,
5606c87b03e5Sespie 			     (GET_MODE (op1) == VOIDmode
5607c87b03e5Sespie 			     ? GET_MODE (op2) : GET_MODE (op1)),
5608c87b03e5Sespie 			     unsignedp, label);
5609c87b03e5Sespie }
5610c87b03e5Sespie 
5611c87b03e5Sespie /* Not all case values are encountered equally.  This function
5612c87b03e5Sespie    uses a heuristic to weight case labels, in cases where that
5613c87b03e5Sespie    looks like a reasonable thing to do.
5614c87b03e5Sespie 
5615c87b03e5Sespie    Right now, all we try to guess is text, and we establish the
5616c87b03e5Sespie    following weights:
5617c87b03e5Sespie 
5618c87b03e5Sespie 	chars above space:	16
5619c87b03e5Sespie 	digits:			16
5620c87b03e5Sespie 	default:		12
5621c87b03e5Sespie 	space, punct:		8
5622c87b03e5Sespie 	tab:			4
5623c87b03e5Sespie 	newline:		2
5624c87b03e5Sespie 	other "\" chars:	1
5625c87b03e5Sespie 	remaining chars:	0
5626c87b03e5Sespie 
5627c87b03e5Sespie    If we find any cases in the switch that are not either -1 or in the range
5628c87b03e5Sespie    of valid ASCII characters, or are control characters other than those
5629c87b03e5Sespie    commonly used with "\", don't treat this switch scanning text.
5630c87b03e5Sespie 
5631c87b03e5Sespie    Return 1 if these nodes are suitable for cost estimation, otherwise
5632c87b03e5Sespie    return 0.  */
5633c87b03e5Sespie 
5634c87b03e5Sespie static int
estimate_case_costs(node)5635c87b03e5Sespie estimate_case_costs (node)
5636c87b03e5Sespie      case_node_ptr node;
5637c87b03e5Sespie {
5638c87b03e5Sespie   tree min_ascii = integer_minus_one_node;
5639c87b03e5Sespie   tree max_ascii = convert (TREE_TYPE (node->high), build_int_2 (127, 0));
5640c87b03e5Sespie   case_node_ptr n;
5641c87b03e5Sespie   int i;
5642c87b03e5Sespie 
5643c87b03e5Sespie   /* If we haven't already made the cost table, make it now.  Note that the
5644c87b03e5Sespie      lower bound of the table is -1, not zero.  */
5645c87b03e5Sespie 
5646c87b03e5Sespie   if (! cost_table_initialized)
5647c87b03e5Sespie     {
5648c87b03e5Sespie       cost_table_initialized = 1;
5649c87b03e5Sespie 
5650c87b03e5Sespie       for (i = 0; i < 128; i++)
5651c87b03e5Sespie 	{
5652c87b03e5Sespie 	  if (ISALNUM (i))
5653c87b03e5Sespie 	    COST_TABLE (i) = 16;
5654c87b03e5Sespie 	  else if (ISPUNCT (i))
5655c87b03e5Sespie 	    COST_TABLE (i) = 8;
5656c87b03e5Sespie 	  else if (ISCNTRL (i))
5657c87b03e5Sespie 	    COST_TABLE (i) = -1;
5658c87b03e5Sespie 	}
5659c87b03e5Sespie 
5660c87b03e5Sespie       COST_TABLE (' ') = 8;
5661c87b03e5Sespie       COST_TABLE ('\t') = 4;
5662c87b03e5Sespie       COST_TABLE ('\0') = 4;
5663c87b03e5Sespie       COST_TABLE ('\n') = 2;
5664c87b03e5Sespie       COST_TABLE ('\f') = 1;
5665c87b03e5Sespie       COST_TABLE ('\v') = 1;
5666c87b03e5Sespie       COST_TABLE ('\b') = 1;
5667c87b03e5Sespie     }
5668c87b03e5Sespie 
5669c87b03e5Sespie   /* See if all the case expressions look like text.  It is text if the
5670c87b03e5Sespie      constant is >= -1 and the highest constant is <= 127.  Do all comparisons
5671c87b03e5Sespie      as signed arithmetic since we don't want to ever access cost_table with a
5672c87b03e5Sespie      value less than -1.  Also check that none of the constants in a range
5673c87b03e5Sespie      are strange control characters.  */
5674c87b03e5Sespie 
5675c87b03e5Sespie   for (n = node; n; n = n->right)
5676c87b03e5Sespie     {
5677c87b03e5Sespie       if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
5678c87b03e5Sespie 	return 0;
5679c87b03e5Sespie 
5680c87b03e5Sespie       for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);
5681c87b03e5Sespie 	   i <= (HOST_WIDE_INT) TREE_INT_CST_LOW (n->high); i++)
5682c87b03e5Sespie 	if (COST_TABLE (i) < 0)
5683c87b03e5Sespie 	  return 0;
5684c87b03e5Sespie     }
5685c87b03e5Sespie 
5686c87b03e5Sespie   /* All interesting values are within the range of interesting
5687c87b03e5Sespie      ASCII characters.  */
5688c87b03e5Sespie   return 1;
5689c87b03e5Sespie }
5690c87b03e5Sespie 
5691c87b03e5Sespie /* Scan an ordered list of case nodes
5692c87b03e5Sespie    combining those with consecutive values or ranges.
5693c87b03e5Sespie 
5694c87b03e5Sespie    Eg. three separate entries 1: 2: 3: become one entry 1..3:  */
5695c87b03e5Sespie 
5696c87b03e5Sespie static void
group_case_nodes(head)5697c87b03e5Sespie group_case_nodes (head)
5698c87b03e5Sespie      case_node_ptr head;
5699c87b03e5Sespie {
5700c87b03e5Sespie   case_node_ptr node = head;
5701c87b03e5Sespie 
5702c87b03e5Sespie   while (node)
5703c87b03e5Sespie     {
5704c87b03e5Sespie       rtx lb = next_real_insn (label_rtx (node->code_label));
5705c87b03e5Sespie       rtx lb2;
5706c87b03e5Sespie       case_node_ptr np = node;
5707c87b03e5Sespie 
5708c87b03e5Sespie       /* Try to group the successors of NODE with NODE.  */
5709c87b03e5Sespie       while (((np = np->right) != 0)
5710c87b03e5Sespie 	     /* Do they jump to the same place?  */
5711c87b03e5Sespie 	     && ((lb2 = next_real_insn (label_rtx (np->code_label))) == lb
5712c87b03e5Sespie 		 || (lb != 0 && lb2 != 0
5713c87b03e5Sespie 		     && simplejump_p (lb)
5714c87b03e5Sespie 		     && simplejump_p (lb2)
5715c87b03e5Sespie 		     && rtx_equal_p (SET_SRC (PATTERN (lb)),
5716c87b03e5Sespie 				     SET_SRC (PATTERN (lb2)))))
5717c87b03e5Sespie 	     /* Are their ranges consecutive?  */
5718c87b03e5Sespie 	     && tree_int_cst_equal (np->low,
5719c87b03e5Sespie 				    fold (build (PLUS_EXPR,
5720c87b03e5Sespie 						 TREE_TYPE (node->high),
5721c87b03e5Sespie 						 node->high,
5722c87b03e5Sespie 						 integer_one_node)))
5723c87b03e5Sespie 	     /* An overflow is not consecutive.  */
5724c87b03e5Sespie 	     && tree_int_cst_lt (node->high,
5725c87b03e5Sespie 				 fold (build (PLUS_EXPR,
5726c87b03e5Sespie 					      TREE_TYPE (node->high),
5727c87b03e5Sespie 					      node->high,
5728c87b03e5Sespie 					      integer_one_node))))
5729c87b03e5Sespie 	{
5730c87b03e5Sespie 	  node->high = np->high;
5731c87b03e5Sespie 	}
5732c87b03e5Sespie       /* NP is the first node after NODE which can't be grouped with it.
5733c87b03e5Sespie 	 Delete the nodes in between, and move on to that node.  */
5734c87b03e5Sespie       node->right = np;
5735c87b03e5Sespie       node = np;
5736c87b03e5Sespie     }
5737c87b03e5Sespie }
5738c87b03e5Sespie 
5739c87b03e5Sespie /* Take an ordered list of case nodes
5740c87b03e5Sespie    and transform them into a near optimal binary tree,
5741c87b03e5Sespie    on the assumption that any target code selection value is as
5742c87b03e5Sespie    likely as any other.
5743c87b03e5Sespie 
5744c87b03e5Sespie    The transformation is performed by splitting the ordered
5745c87b03e5Sespie    list into two equal sections plus a pivot.  The parts are
5746c87b03e5Sespie    then attached to the pivot as left and right branches.  Each
5747c87b03e5Sespie    branch is then transformed recursively.  */
5748c87b03e5Sespie 
5749c87b03e5Sespie static void
balance_case_nodes(head,parent)5750c87b03e5Sespie balance_case_nodes (head, parent)
5751c87b03e5Sespie      case_node_ptr *head;
5752c87b03e5Sespie      case_node_ptr parent;
5753c87b03e5Sespie {
5754c87b03e5Sespie   case_node_ptr np;
5755c87b03e5Sespie 
5756c87b03e5Sespie   np = *head;
5757c87b03e5Sespie   if (np)
5758c87b03e5Sespie     {
5759c87b03e5Sespie       int cost = 0;
5760c87b03e5Sespie       int i = 0;
5761c87b03e5Sespie       int ranges = 0;
5762c87b03e5Sespie       case_node_ptr *npp;
5763c87b03e5Sespie       case_node_ptr left;
5764c87b03e5Sespie 
5765c87b03e5Sespie       /* Count the number of entries on branch.  Also count the ranges.  */
5766c87b03e5Sespie 
5767c87b03e5Sespie       while (np)
5768c87b03e5Sespie 	{
5769c87b03e5Sespie 	  if (!tree_int_cst_equal (np->low, np->high))
5770c87b03e5Sespie 	    {
5771c87b03e5Sespie 	      ranges++;
5772c87b03e5Sespie 	      if (use_cost_table)
5773c87b03e5Sespie 		cost += COST_TABLE (TREE_INT_CST_LOW (np->high));
5774c87b03e5Sespie 	    }
5775c87b03e5Sespie 
5776c87b03e5Sespie 	  if (use_cost_table)
5777c87b03e5Sespie 	    cost += COST_TABLE (TREE_INT_CST_LOW (np->low));
5778c87b03e5Sespie 
5779c87b03e5Sespie 	  i++;
5780c87b03e5Sespie 	  np = np->right;
5781c87b03e5Sespie 	}
5782c87b03e5Sespie 
5783c87b03e5Sespie       if (i > 2)
5784c87b03e5Sespie 	{
5785c87b03e5Sespie 	  /* Split this list if it is long enough for that to help.  */
5786c87b03e5Sespie 	  npp = head;
5787c87b03e5Sespie 	  left = *npp;
5788c87b03e5Sespie 	  if (use_cost_table)
5789c87b03e5Sespie 	    {
5790c87b03e5Sespie 	      /* Find the place in the list that bisects the list's total cost,
5791c87b03e5Sespie 		 Here I gets half the total cost.  */
5792c87b03e5Sespie 	      int n_moved = 0;
5793c87b03e5Sespie 	      i = (cost + 1) / 2;
5794c87b03e5Sespie 	      while (1)
5795c87b03e5Sespie 		{
5796c87b03e5Sespie 		  /* Skip nodes while their cost does not reach that amount.  */
5797c87b03e5Sespie 		  if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
5798c87b03e5Sespie 		    i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->high));
5799c87b03e5Sespie 		  i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->low));
5800c87b03e5Sespie 		  if (i <= 0)
5801c87b03e5Sespie 		    break;
5802c87b03e5Sespie 		  npp = &(*npp)->right;
5803c87b03e5Sespie 		  n_moved += 1;
5804c87b03e5Sespie 		}
5805c87b03e5Sespie 	      if (n_moved == 0)
5806c87b03e5Sespie 		{
5807c87b03e5Sespie 		  /* Leave this branch lopsided, but optimize left-hand
5808c87b03e5Sespie 		     side and fill in `parent' fields for right-hand side.  */
5809c87b03e5Sespie 		  np = *head;
5810c87b03e5Sespie 		  np->parent = parent;
5811c87b03e5Sespie 		  balance_case_nodes (&np->left, np);
5812c87b03e5Sespie 		  for (; np->right; np = np->right)
5813c87b03e5Sespie 		    np->right->parent = np;
5814c87b03e5Sespie 		  return;
5815c87b03e5Sespie 		}
5816c87b03e5Sespie 	    }
5817c87b03e5Sespie 	  /* If there are just three nodes, split at the middle one.  */
5818c87b03e5Sespie 	  else if (i == 3)
5819c87b03e5Sespie 	    npp = &(*npp)->right;
5820c87b03e5Sespie 	  else
5821c87b03e5Sespie 	    {
5822c87b03e5Sespie 	      /* Find the place in the list that bisects the list's total cost,
5823c87b03e5Sespie 		 where ranges count as 2.
5824c87b03e5Sespie 		 Here I gets half the total cost.  */
5825c87b03e5Sespie 	      i = (i + ranges + 1) / 2;
5826c87b03e5Sespie 	      while (1)
5827c87b03e5Sespie 		{
5828c87b03e5Sespie 		  /* Skip nodes while their cost does not reach that amount.  */
5829c87b03e5Sespie 		  if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
5830c87b03e5Sespie 		    i--;
5831c87b03e5Sespie 		  i--;
5832c87b03e5Sespie 		  if (i <= 0)
5833c87b03e5Sespie 		    break;
5834c87b03e5Sespie 		  npp = &(*npp)->right;
5835c87b03e5Sespie 		}
5836c87b03e5Sespie 	    }
5837c87b03e5Sespie 	  *head = np = *npp;
5838c87b03e5Sespie 	  *npp = 0;
5839c87b03e5Sespie 	  np->parent = parent;
5840c87b03e5Sespie 	  np->left = left;
5841c87b03e5Sespie 
5842c87b03e5Sespie 	  /* Optimize each of the two split parts.  */
5843c87b03e5Sespie 	  balance_case_nodes (&np->left, np);
5844c87b03e5Sespie 	  balance_case_nodes (&np->right, np);
5845c87b03e5Sespie 	}
5846c87b03e5Sespie       else
5847c87b03e5Sespie 	{
5848c87b03e5Sespie 	  /* Else leave this branch as one level,
5849c87b03e5Sespie 	     but fill in `parent' fields.  */
5850c87b03e5Sespie 	  np = *head;
5851c87b03e5Sespie 	  np->parent = parent;
5852c87b03e5Sespie 	  for (; np->right; np = np->right)
5853c87b03e5Sespie 	    np->right->parent = np;
5854c87b03e5Sespie 	}
5855c87b03e5Sespie     }
5856c87b03e5Sespie }
5857c87b03e5Sespie 
5858c87b03e5Sespie /* Search the parent sections of the case node tree
5859c87b03e5Sespie    to see if a test for the lower bound of NODE would be redundant.
5860c87b03e5Sespie    INDEX_TYPE is the type of the index expression.
5861c87b03e5Sespie 
5862c87b03e5Sespie    The instructions to generate the case decision tree are
5863c87b03e5Sespie    output in the same order as nodes are processed so it is
5864c87b03e5Sespie    known that if a parent node checks the range of the current
5865c87b03e5Sespie    node minus one that the current node is bounded at its lower
5866c87b03e5Sespie    span.  Thus the test would be redundant.  */
5867c87b03e5Sespie 
5868c87b03e5Sespie static int
node_has_low_bound(node,index_type)5869c87b03e5Sespie node_has_low_bound (node, index_type)
5870c87b03e5Sespie      case_node_ptr node;
5871c87b03e5Sespie      tree index_type;
5872c87b03e5Sespie {
5873c87b03e5Sespie   tree low_minus_one;
5874c87b03e5Sespie   case_node_ptr pnode;
5875c87b03e5Sespie 
5876c87b03e5Sespie   /* If the lower bound of this node is the lowest value in the index type,
5877c87b03e5Sespie      we need not test it.  */
5878c87b03e5Sespie 
5879c87b03e5Sespie   if (tree_int_cst_equal (node->low, TYPE_MIN_VALUE (index_type)))
5880c87b03e5Sespie     return 1;
5881c87b03e5Sespie 
5882c87b03e5Sespie   /* If this node has a left branch, the value at the left must be less
5883c87b03e5Sespie      than that at this node, so it cannot be bounded at the bottom and
5884c87b03e5Sespie      we need not bother testing any further.  */
5885c87b03e5Sespie 
5886c87b03e5Sespie   if (node->left)
5887c87b03e5Sespie     return 0;
5888c87b03e5Sespie 
5889c87b03e5Sespie   low_minus_one = fold (build (MINUS_EXPR, TREE_TYPE (node->low),
5890c87b03e5Sespie 			       node->low, integer_one_node));
5891c87b03e5Sespie 
5892c87b03e5Sespie   /* If the subtraction above overflowed, we can't verify anything.
5893c87b03e5Sespie      Otherwise, look for a parent that tests our value - 1.  */
5894c87b03e5Sespie 
5895c87b03e5Sespie   if (! tree_int_cst_lt (low_minus_one, node->low))
5896c87b03e5Sespie     return 0;
5897c87b03e5Sespie 
5898c87b03e5Sespie   for (pnode = node->parent; pnode; pnode = pnode->parent)
5899c87b03e5Sespie     if (tree_int_cst_equal (low_minus_one, pnode->high))
5900c87b03e5Sespie       return 1;
5901c87b03e5Sespie 
5902c87b03e5Sespie   return 0;
5903c87b03e5Sespie }
5904c87b03e5Sespie 
5905c87b03e5Sespie /* Search the parent sections of the case node tree
5906c87b03e5Sespie    to see if a test for the upper bound of NODE would be redundant.
5907c87b03e5Sespie    INDEX_TYPE is the type of the index expression.
5908c87b03e5Sespie 
5909c87b03e5Sespie    The instructions to generate the case decision tree are
5910c87b03e5Sespie    output in the same order as nodes are processed so it is
5911c87b03e5Sespie    known that if a parent node checks the range of the current
5912c87b03e5Sespie    node plus one that the current node is bounded at its upper
5913c87b03e5Sespie    span.  Thus the test would be redundant.  */
5914c87b03e5Sespie 
5915c87b03e5Sespie static int
node_has_high_bound(node,index_type)5916c87b03e5Sespie node_has_high_bound (node, index_type)
5917c87b03e5Sespie      case_node_ptr node;
5918c87b03e5Sespie      tree index_type;
5919c87b03e5Sespie {
5920c87b03e5Sespie   tree high_plus_one;
5921c87b03e5Sespie   case_node_ptr pnode;
5922c87b03e5Sespie 
5923c87b03e5Sespie   /* If there is no upper bound, obviously no test is needed.  */
5924c87b03e5Sespie 
5925c87b03e5Sespie   if (TYPE_MAX_VALUE (index_type) == NULL)
5926c87b03e5Sespie     return 1;
5927c87b03e5Sespie 
5928c87b03e5Sespie   /* If the upper bound of this node is the highest value in the type
5929c87b03e5Sespie      of the index expression, we need not test against it.  */
5930c87b03e5Sespie 
5931c87b03e5Sespie   if (tree_int_cst_equal (node->high, TYPE_MAX_VALUE (index_type)))
5932c87b03e5Sespie     return 1;
5933c87b03e5Sespie 
5934c87b03e5Sespie   /* If this node has a right branch, the value at the right must be greater
5935c87b03e5Sespie      than that at this node, so it cannot be bounded at the top and
5936c87b03e5Sespie      we need not bother testing any further.  */
5937c87b03e5Sespie 
5938c87b03e5Sespie   if (node->right)
5939c87b03e5Sespie     return 0;
5940c87b03e5Sespie 
5941c87b03e5Sespie   high_plus_one = fold (build (PLUS_EXPR, TREE_TYPE (node->high),
5942c87b03e5Sespie 			       node->high, integer_one_node));
5943c87b03e5Sespie 
5944c87b03e5Sespie   /* If the addition above overflowed, we can't verify anything.
5945c87b03e5Sespie      Otherwise, look for a parent that tests our value + 1.  */
5946c87b03e5Sespie 
5947c87b03e5Sespie   if (! tree_int_cst_lt (node->high, high_plus_one))
5948c87b03e5Sespie     return 0;
5949c87b03e5Sespie 
5950c87b03e5Sespie   for (pnode = node->parent; pnode; pnode = pnode->parent)
5951c87b03e5Sespie     if (tree_int_cst_equal (high_plus_one, pnode->low))
5952c87b03e5Sespie       return 1;
5953c87b03e5Sespie 
5954c87b03e5Sespie   return 0;
5955c87b03e5Sespie }
5956c87b03e5Sespie 
5957c87b03e5Sespie /* Search the parent sections of the
5958c87b03e5Sespie    case node tree to see if both tests for the upper and lower
5959c87b03e5Sespie    bounds of NODE would be redundant.  */
5960c87b03e5Sespie 
5961c87b03e5Sespie static int
node_is_bounded(node,index_type)5962c87b03e5Sespie node_is_bounded (node, index_type)
5963c87b03e5Sespie      case_node_ptr node;
5964c87b03e5Sespie      tree index_type;
5965c87b03e5Sespie {
5966c87b03e5Sespie   return (node_has_low_bound (node, index_type)
5967c87b03e5Sespie 	  && node_has_high_bound (node, index_type));
5968c87b03e5Sespie }
5969c87b03e5Sespie 
5970c87b03e5Sespie /*  Emit an unconditional jump to LABEL unless it would be dead code.  */
5971c87b03e5Sespie 
5972c87b03e5Sespie static void
emit_jump_if_reachable(label)5973c87b03e5Sespie emit_jump_if_reachable (label)
5974c87b03e5Sespie      rtx label;
5975c87b03e5Sespie {
5976c87b03e5Sespie   if (GET_CODE (get_last_insn ()) != BARRIER)
5977c87b03e5Sespie     emit_jump (label);
5978c87b03e5Sespie }
5979c87b03e5Sespie 
5980c87b03e5Sespie /* Emit step-by-step code to select a case for the value of INDEX.
5981c87b03e5Sespie    The thus generated decision tree follows the form of the
5982c87b03e5Sespie    case-node binary tree NODE, whose nodes represent test conditions.
5983c87b03e5Sespie    INDEX_TYPE is the type of the index of the switch.
5984c87b03e5Sespie 
5985c87b03e5Sespie    Care is taken to prune redundant tests from the decision tree
5986c87b03e5Sespie    by detecting any boundary conditions already checked by
5987c87b03e5Sespie    emitted rtx.  (See node_has_high_bound, node_has_low_bound
5988c87b03e5Sespie    and node_is_bounded, above.)
5989c87b03e5Sespie 
5990c87b03e5Sespie    Where the test conditions can be shown to be redundant we emit
5991c87b03e5Sespie    an unconditional jump to the target code.  As a further
5992c87b03e5Sespie    optimization, the subordinates of a tree node are examined to
5993c87b03e5Sespie    check for bounded nodes.  In this case conditional and/or
5994c87b03e5Sespie    unconditional jumps as a result of the boundary check for the
5995c87b03e5Sespie    current node are arranged to target the subordinates associated
5996c87b03e5Sespie    code for out of bound conditions on the current node.
5997c87b03e5Sespie 
5998c87b03e5Sespie    We can assume that when control reaches the code generated here,
5999c87b03e5Sespie    the index value has already been compared with the parents
6000c87b03e5Sespie    of this node, and determined to be on the same side of each parent
6001c87b03e5Sespie    as this node is.  Thus, if this node tests for the value 51,
6002c87b03e5Sespie    and a parent tested for 52, we don't need to consider
6003c87b03e5Sespie    the possibility of a value greater than 51.  If another parent
6004c87b03e5Sespie    tests for the value 50, then this node need not test anything.  */
6005c87b03e5Sespie 
6006c87b03e5Sespie static void
emit_case_nodes(index,node,default_label,index_type)6007c87b03e5Sespie emit_case_nodes (index, node, default_label, index_type)
6008c87b03e5Sespie      rtx index;
6009c87b03e5Sespie      case_node_ptr node;
6010c87b03e5Sespie      rtx default_label;
6011c87b03e5Sespie      tree index_type;
6012c87b03e5Sespie {
6013c87b03e5Sespie   /* If INDEX has an unsigned type, we must make unsigned branches.  */
6014c87b03e5Sespie   int unsignedp = TREE_UNSIGNED (index_type);
6015c87b03e5Sespie   enum machine_mode mode = GET_MODE (index);
6016c87b03e5Sespie   enum machine_mode imode = TYPE_MODE (index_type);
6017c87b03e5Sespie 
6018c87b03e5Sespie   /* See if our parents have already tested everything for us.
6019c87b03e5Sespie      If they have, emit an unconditional jump for this node.  */
6020c87b03e5Sespie   if (node_is_bounded (node, index_type))
6021c87b03e5Sespie     emit_jump (label_rtx (node->code_label));
6022c87b03e5Sespie 
6023c87b03e5Sespie   else if (tree_int_cst_equal (node->low, node->high))
6024c87b03e5Sespie     {
6025c87b03e5Sespie       /* Node is single valued.  First see if the index expression matches
6026c87b03e5Sespie 	 this node and then check our children, if any.  */
6027c87b03e5Sespie 
6028c87b03e5Sespie       do_jump_if_equal (index,
6029c87b03e5Sespie 			convert_modes (mode, imode,
6030c87b03e5Sespie 				       expand_expr (node->low, NULL_RTX,
6031c87b03e5Sespie 						    VOIDmode, 0),
6032c87b03e5Sespie 				       unsignedp),
6033c87b03e5Sespie 			label_rtx (node->code_label), unsignedp);
6034c87b03e5Sespie 
6035c87b03e5Sespie       if (node->right != 0 && node->left != 0)
6036c87b03e5Sespie 	{
6037c87b03e5Sespie 	  /* This node has children on both sides.
6038c87b03e5Sespie 	     Dispatch to one side or the other
6039c87b03e5Sespie 	     by comparing the index value with this node's value.
6040c87b03e5Sespie 	     If one subtree is bounded, check that one first,
6041c87b03e5Sespie 	     so we can avoid real branches in the tree.  */
6042c87b03e5Sespie 
6043c87b03e5Sespie 	  if (node_is_bounded (node->right, index_type))
6044c87b03e5Sespie 	    {
6045c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6046c87b03e5Sespie 				       convert_modes
6047c87b03e5Sespie 				       (mode, imode,
6048c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6049c87b03e5Sespie 						     VOIDmode, 0),
6050c87b03e5Sespie 					unsignedp),
6051c87b03e5Sespie 				       GT, NULL_RTX, mode, unsignedp,
6052c87b03e5Sespie 				       label_rtx (node->right->code_label));
6053c87b03e5Sespie 	      emit_case_nodes (index, node->left, default_label, index_type);
6054c87b03e5Sespie 	    }
6055c87b03e5Sespie 
6056c87b03e5Sespie 	  else if (node_is_bounded (node->left, index_type))
6057c87b03e5Sespie 	    {
6058c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6059c87b03e5Sespie 				       convert_modes
6060c87b03e5Sespie 				       (mode, imode,
6061c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6062c87b03e5Sespie 						     VOIDmode, 0),
6063c87b03e5Sespie 					unsignedp),
6064c87b03e5Sespie 				       LT, NULL_RTX, mode, unsignedp,
6065c87b03e5Sespie 				       label_rtx (node->left->code_label));
6066c87b03e5Sespie 	      emit_case_nodes (index, node->right, default_label, index_type);
6067c87b03e5Sespie 	    }
6068c87b03e5Sespie 
6069c87b03e5Sespie 	  else
6070c87b03e5Sespie 	    {
6071c87b03e5Sespie 	      /* Neither node is bounded.  First distinguish the two sides;
6072c87b03e5Sespie 		 then emit the code for one side at a time.  */
6073c87b03e5Sespie 
6074c87b03e5Sespie 	      tree test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
6075c87b03e5Sespie 
6076c87b03e5Sespie 	      /* See if the value is on the right.  */
6077c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6078c87b03e5Sespie 				       convert_modes
6079c87b03e5Sespie 				       (mode, imode,
6080c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6081c87b03e5Sespie 						     VOIDmode, 0),
6082c87b03e5Sespie 					unsignedp),
6083c87b03e5Sespie 				       GT, NULL_RTX, mode, unsignedp,
6084c87b03e5Sespie 				       label_rtx (test_label));
6085c87b03e5Sespie 
6086c87b03e5Sespie 	      /* Value must be on the left.
6087c87b03e5Sespie 		 Handle the left-hand subtree.  */
6088c87b03e5Sespie 	      emit_case_nodes (index, node->left, default_label, index_type);
6089c87b03e5Sespie 	      /* If left-hand subtree does nothing,
6090c87b03e5Sespie 		 go to default.  */
6091c87b03e5Sespie 	      emit_jump_if_reachable (default_label);
6092c87b03e5Sespie 
6093c87b03e5Sespie 	      /* Code branches here for the right-hand subtree.  */
6094c87b03e5Sespie 	      expand_label (test_label);
6095c87b03e5Sespie 	      emit_case_nodes (index, node->right, default_label, index_type);
6096c87b03e5Sespie 	    }
6097c87b03e5Sespie 	}
6098c87b03e5Sespie 
6099c87b03e5Sespie       else if (node->right != 0 && node->left == 0)
6100c87b03e5Sespie 	{
6101c87b03e5Sespie 	  /* Here we have a right child but no left so we issue conditional
6102c87b03e5Sespie 	     branch to default and process the right child.
6103c87b03e5Sespie 
6104c87b03e5Sespie 	     Omit the conditional branch to default if we it avoid only one
6105c87b03e5Sespie 	     right child; it costs too much space to save so little time.  */
6106c87b03e5Sespie 
6107c87b03e5Sespie 	  if (node->right->right || node->right->left
6108c87b03e5Sespie 	      || !tree_int_cst_equal (node->right->low, node->right->high))
6109c87b03e5Sespie 	    {
6110c87b03e5Sespie 	      if (!node_has_low_bound (node, index_type))
6111c87b03e5Sespie 		{
6112c87b03e5Sespie 		  emit_cmp_and_jump_insns (index,
6113c87b03e5Sespie 					   convert_modes
6114c87b03e5Sespie 					   (mode, imode,
6115c87b03e5Sespie 					    expand_expr (node->high, NULL_RTX,
6116c87b03e5Sespie 							 VOIDmode, 0),
6117c87b03e5Sespie 					    unsignedp),
6118c87b03e5Sespie 					   LT, NULL_RTX, mode, unsignedp,
6119c87b03e5Sespie 					   default_label);
6120c87b03e5Sespie 		}
6121c87b03e5Sespie 
6122c87b03e5Sespie 	      emit_case_nodes (index, node->right, default_label, index_type);
6123c87b03e5Sespie 	    }
6124c87b03e5Sespie 	  else
6125c87b03e5Sespie 	    /* We cannot process node->right normally
6126c87b03e5Sespie 	       since we haven't ruled out the numbers less than
6127c87b03e5Sespie 	       this node's value.  So handle node->right explicitly.  */
6128c87b03e5Sespie 	    do_jump_if_equal (index,
6129c87b03e5Sespie 			      convert_modes
6130c87b03e5Sespie 			      (mode, imode,
6131c87b03e5Sespie 			       expand_expr (node->right->low, NULL_RTX,
6132c87b03e5Sespie 					    VOIDmode, 0),
6133c87b03e5Sespie 			       unsignedp),
6134c87b03e5Sespie 			      label_rtx (node->right->code_label), unsignedp);
6135c87b03e5Sespie 	}
6136c87b03e5Sespie 
6137c87b03e5Sespie       else if (node->right == 0 && node->left != 0)
6138c87b03e5Sespie 	{
6139c87b03e5Sespie 	  /* Just one subtree, on the left.  */
6140c87b03e5Sespie 	  if (node->left->left || node->left->right
6141c87b03e5Sespie 	      || !tree_int_cst_equal (node->left->low, node->left->high))
6142c87b03e5Sespie 	    {
6143c87b03e5Sespie 	      if (!node_has_high_bound (node, index_type))
6144c87b03e5Sespie 		{
6145c87b03e5Sespie 		  emit_cmp_and_jump_insns (index,
6146c87b03e5Sespie 					   convert_modes
6147c87b03e5Sespie 					   (mode, imode,
6148c87b03e5Sespie 					    expand_expr (node->high, NULL_RTX,
6149c87b03e5Sespie 							 VOIDmode, 0),
6150c87b03e5Sespie 					    unsignedp),
6151c87b03e5Sespie 					   GT, NULL_RTX, mode, unsignedp,
6152c87b03e5Sespie 					   default_label);
6153c87b03e5Sespie 		}
6154c87b03e5Sespie 
6155c87b03e5Sespie 	      emit_case_nodes (index, node->left, default_label, index_type);
6156c87b03e5Sespie 	    }
6157c87b03e5Sespie 	  else
6158c87b03e5Sespie 	    /* We cannot process node->left normally
6159c87b03e5Sespie 	       since we haven't ruled out the numbers less than
6160c87b03e5Sespie 	       this node's value.  So handle node->left explicitly.  */
6161c87b03e5Sespie 	    do_jump_if_equal (index,
6162c87b03e5Sespie 			      convert_modes
6163c87b03e5Sespie 			      (mode, imode,
6164c87b03e5Sespie 			       expand_expr (node->left->low, NULL_RTX,
6165c87b03e5Sespie 					    VOIDmode, 0),
6166c87b03e5Sespie 			       unsignedp),
6167c87b03e5Sespie 			      label_rtx (node->left->code_label), unsignedp);
6168c87b03e5Sespie 	}
6169c87b03e5Sespie     }
6170c87b03e5Sespie   else
6171c87b03e5Sespie     {
6172c87b03e5Sespie       /* Node is a range.  These cases are very similar to those for a single
6173c87b03e5Sespie 	 value, except that we do not start by testing whether this node
6174c87b03e5Sespie 	 is the one to branch to.  */
6175c87b03e5Sespie 
6176c87b03e5Sespie       if (node->right != 0 && node->left != 0)
6177c87b03e5Sespie 	{
6178c87b03e5Sespie 	  /* Node has subtrees on both sides.
6179c87b03e5Sespie 	     If the right-hand subtree is bounded,
6180c87b03e5Sespie 	     test for it first, since we can go straight there.
6181c87b03e5Sespie 	     Otherwise, we need to make a branch in the control structure,
6182c87b03e5Sespie 	     then handle the two subtrees.  */
6183c87b03e5Sespie 	  tree test_label = 0;
6184c87b03e5Sespie 
6185c87b03e5Sespie 	  if (node_is_bounded (node->right, index_type))
6186c87b03e5Sespie 	    /* Right hand node is fully bounded so we can eliminate any
6187c87b03e5Sespie 	       testing and branch directly to the target code.  */
6188c87b03e5Sespie 	    emit_cmp_and_jump_insns (index,
6189c87b03e5Sespie 				     convert_modes
6190c87b03e5Sespie 				     (mode, imode,
6191c87b03e5Sespie 				      expand_expr (node->high, NULL_RTX,
6192c87b03e5Sespie 						   VOIDmode, 0),
6193c87b03e5Sespie 				      unsignedp),
6194c87b03e5Sespie 				     GT, NULL_RTX, mode, unsignedp,
6195c87b03e5Sespie 				     label_rtx (node->right->code_label));
6196c87b03e5Sespie 	  else
6197c87b03e5Sespie 	    {
6198c87b03e5Sespie 	      /* Right hand node requires testing.
6199c87b03e5Sespie 		 Branch to a label where we will handle it later.  */
6200c87b03e5Sespie 
6201c87b03e5Sespie 	      test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
6202c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6203c87b03e5Sespie 				       convert_modes
6204c87b03e5Sespie 				       (mode, imode,
6205c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6206c87b03e5Sespie 						     VOIDmode, 0),
6207c87b03e5Sespie 					unsignedp),
6208c87b03e5Sespie 				       GT, NULL_RTX, mode, unsignedp,
6209c87b03e5Sespie 				       label_rtx (test_label));
6210c87b03e5Sespie 	    }
6211c87b03e5Sespie 
6212c87b03e5Sespie 	  /* Value belongs to this node or to the left-hand subtree.  */
6213c87b03e5Sespie 
6214c87b03e5Sespie 	  emit_cmp_and_jump_insns (index,
6215c87b03e5Sespie 				   convert_modes
6216c87b03e5Sespie 				   (mode, imode,
6217c87b03e5Sespie 				    expand_expr (node->low, NULL_RTX,
6218c87b03e5Sespie 						 VOIDmode, 0),
6219c87b03e5Sespie 				    unsignedp),
6220c87b03e5Sespie 				   GE, NULL_RTX, mode, unsignedp,
6221c87b03e5Sespie 				   label_rtx (node->code_label));
6222c87b03e5Sespie 
6223c87b03e5Sespie 	  /* Handle the left-hand subtree.  */
6224c87b03e5Sespie 	  emit_case_nodes (index, node->left, default_label, index_type);
6225c87b03e5Sespie 
6226c87b03e5Sespie 	  /* If right node had to be handled later, do that now.  */
6227c87b03e5Sespie 
6228c87b03e5Sespie 	  if (test_label)
6229c87b03e5Sespie 	    {
6230c87b03e5Sespie 	      /* If the left-hand subtree fell through,
6231c87b03e5Sespie 		 don't let it fall into the right-hand subtree.  */
6232c87b03e5Sespie 	      emit_jump_if_reachable (default_label);
6233c87b03e5Sespie 
6234c87b03e5Sespie 	      expand_label (test_label);
6235c87b03e5Sespie 	      emit_case_nodes (index, node->right, default_label, index_type);
6236c87b03e5Sespie 	    }
6237c87b03e5Sespie 	}
6238c87b03e5Sespie 
6239c87b03e5Sespie       else if (node->right != 0 && node->left == 0)
6240c87b03e5Sespie 	{
6241c87b03e5Sespie 	  /* Deal with values to the left of this node,
6242c87b03e5Sespie 	     if they are possible.  */
6243c87b03e5Sespie 	  if (!node_has_low_bound (node, index_type))
6244c87b03e5Sespie 	    {
6245c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6246c87b03e5Sespie 				       convert_modes
6247c87b03e5Sespie 				       (mode, imode,
6248c87b03e5Sespie 					expand_expr (node->low, NULL_RTX,
6249c87b03e5Sespie 						     VOIDmode, 0),
6250c87b03e5Sespie 					unsignedp),
6251c87b03e5Sespie 				       LT, NULL_RTX, mode, unsignedp,
6252c87b03e5Sespie 				       default_label);
6253c87b03e5Sespie 	    }
6254c87b03e5Sespie 
6255c87b03e5Sespie 	  /* Value belongs to this node or to the right-hand subtree.  */
6256c87b03e5Sespie 
6257c87b03e5Sespie 	  emit_cmp_and_jump_insns (index,
6258c87b03e5Sespie 				   convert_modes
6259c87b03e5Sespie 				   (mode, imode,
6260c87b03e5Sespie 				    expand_expr (node->high, NULL_RTX,
6261c87b03e5Sespie 						 VOIDmode, 0),
6262c87b03e5Sespie 				    unsignedp),
6263c87b03e5Sespie 				   LE, NULL_RTX, mode, unsignedp,
6264c87b03e5Sespie 				   label_rtx (node->code_label));
6265c87b03e5Sespie 
6266c87b03e5Sespie 	  emit_case_nodes (index, node->right, default_label, index_type);
6267c87b03e5Sespie 	}
6268c87b03e5Sespie 
6269c87b03e5Sespie       else if (node->right == 0 && node->left != 0)
6270c87b03e5Sespie 	{
6271c87b03e5Sespie 	  /* Deal with values to the right of this node,
6272c87b03e5Sespie 	     if they are possible.  */
6273c87b03e5Sespie 	  if (!node_has_high_bound (node, index_type))
6274c87b03e5Sespie 	    {
6275c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6276c87b03e5Sespie 				       convert_modes
6277c87b03e5Sespie 				       (mode, imode,
6278c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6279c87b03e5Sespie 						     VOIDmode, 0),
6280c87b03e5Sespie 					unsignedp),
6281c87b03e5Sespie 				       GT, NULL_RTX, mode, unsignedp,
6282c87b03e5Sespie 				       default_label);
6283c87b03e5Sespie 	    }
6284c87b03e5Sespie 
6285c87b03e5Sespie 	  /* Value belongs to this node or to the left-hand subtree.  */
6286c87b03e5Sespie 
6287c87b03e5Sespie 	  emit_cmp_and_jump_insns (index,
6288c87b03e5Sespie 				   convert_modes
6289c87b03e5Sespie 				   (mode, imode,
6290c87b03e5Sespie 				    expand_expr (node->low, NULL_RTX,
6291c87b03e5Sespie 						 VOIDmode, 0),
6292c87b03e5Sespie 				    unsignedp),
6293c87b03e5Sespie 				   GE, NULL_RTX, mode, unsignedp,
6294c87b03e5Sespie 				   label_rtx (node->code_label));
6295c87b03e5Sespie 
6296c87b03e5Sespie 	  emit_case_nodes (index, node->left, default_label, index_type);
6297c87b03e5Sespie 	}
6298c87b03e5Sespie 
6299c87b03e5Sespie       else
6300c87b03e5Sespie 	{
6301c87b03e5Sespie 	  /* Node has no children so we check low and high bounds to remove
6302c87b03e5Sespie 	     redundant tests.  Only one of the bounds can exist,
6303c87b03e5Sespie 	     since otherwise this node is bounded--a case tested already.  */
6304c87b03e5Sespie 	  int high_bound = node_has_high_bound (node, index_type);
6305c87b03e5Sespie 	  int low_bound = node_has_low_bound (node, index_type);
6306c87b03e5Sespie 
6307c87b03e5Sespie 	  if (!high_bound && low_bound)
6308c87b03e5Sespie 	    {
6309c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6310c87b03e5Sespie 				       convert_modes
6311c87b03e5Sespie 				       (mode, imode,
6312c87b03e5Sespie 					expand_expr (node->high, NULL_RTX,
6313c87b03e5Sespie 						     VOIDmode, 0),
6314c87b03e5Sespie 					unsignedp),
6315c87b03e5Sespie 				       GT, NULL_RTX, mode, unsignedp,
6316c87b03e5Sespie 				       default_label);
6317c87b03e5Sespie 	    }
6318c87b03e5Sespie 
6319c87b03e5Sespie 	  else if (!low_bound && high_bound)
6320c87b03e5Sespie 	    {
6321c87b03e5Sespie 	      emit_cmp_and_jump_insns (index,
6322c87b03e5Sespie 				       convert_modes
6323c87b03e5Sespie 				       (mode, imode,
6324c87b03e5Sespie 					expand_expr (node->low, NULL_RTX,
6325c87b03e5Sespie 						     VOIDmode, 0),
6326c87b03e5Sespie 					unsignedp),
6327c87b03e5Sespie 				       LT, NULL_RTX, mode, unsignedp,
6328c87b03e5Sespie 				       default_label);
6329c87b03e5Sespie 	    }
6330c87b03e5Sespie 	  else if (!low_bound && !high_bound)
6331c87b03e5Sespie 	    {
6332c87b03e5Sespie 	      /* Widen LOW and HIGH to the same width as INDEX.  */
6333c87b03e5Sespie 	      tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
6334c87b03e5Sespie 	      tree low = build1 (CONVERT_EXPR, type, node->low);
6335c87b03e5Sespie 	      tree high = build1 (CONVERT_EXPR, type, node->high);
6336c87b03e5Sespie 	      rtx low_rtx, new_index, new_bound;
6337c87b03e5Sespie 
6338c87b03e5Sespie 	      /* Instead of doing two branches, emit one unsigned branch for
6339c87b03e5Sespie 		 (index-low) > (high-low).  */
6340c87b03e5Sespie 	      low_rtx = expand_expr (low, NULL_RTX, mode, 0);
6341c87b03e5Sespie 	      new_index = expand_simple_binop (mode, MINUS, index, low_rtx,
6342c87b03e5Sespie 					       NULL_RTX, unsignedp,
6343c87b03e5Sespie 					       OPTAB_WIDEN);
6344c87b03e5Sespie 	      new_bound = expand_expr (fold (build (MINUS_EXPR, type,
6345c87b03e5Sespie 						    high, low)),
6346c87b03e5Sespie 				       NULL_RTX, mode, 0);
6347c87b03e5Sespie 
6348c87b03e5Sespie 	      emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
6349c87b03e5Sespie 				       mode, 1, default_label);
6350c87b03e5Sespie 	    }
6351c87b03e5Sespie 
6352c87b03e5Sespie 	  emit_jump (label_rtx (node->code_label));
6353c87b03e5Sespie 	}
6354c87b03e5Sespie     }
6355c87b03e5Sespie }
6356c87b03e5Sespie 
6357c87b03e5Sespie #include "gt-stmt.h"
6358