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