|
|
1.1 root 1: /* Expands front end tree to back end RTL for GNU C-Compiler
1.1.1.2 root 2: Copyright (C) 1987,1988 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This file handles the generation of rtl code from tree structure
1.1.1.2 root 23: above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
1.1 root 24: It also creates the rtl expressions for parameters and auto variables
25: and has full responsibility for allocating stack slots.
26:
1.1.1.2 root 27: The functions whose names start with `expand_' are called by the
28: parser to generate RTL instructions for various kinds of constructs.
29:
30: Some control and binding constructs require calling several such
31: functions at different times. For example, a simple if-then
32: is expanded by calling `expand_start_cond' (with the condition-expression
33: as argument) before parsing the then-clause and calling `expand_end_cond'
34: after parsing the then-clause.
35:
1.1.1.10 root 36: `expand_function_start' is called at the beginning of a function,
37: before the function body is parsed, and `expand_function_end' is
1.1.1.2 root 38: called after parsing the body.
39:
40: Call `assign_stack_local' to allocate a stack slot for a local variable.
41: This is usually done during the RTL generation for the function body,
42: but it can also be done in the reload pass when a pseudo-register does
43: not get a hard register.
44:
45: Call `put_var_into_stack' when you learn, belatedly, that a variable
46: previously given a pseudo-register must in fact go in the stack.
47: This function changes the DECL_RTL to be a stack slot instead of a reg
48: then scans all the RTL instructions so far generated to correct them. */
1.1 root 49:
50: #include "config.h"
51:
52: #include <stdio.h>
53:
54: #include "rtl.h"
55: #include "tree.h"
1.1.1.2 root 56: #include "flags.h"
1.1 root 57: #include "insn-flags.h"
1.1.1.2 root 58: #include "insn-config.h"
1.1 root 59: #include "expr.h"
1.1.1.2 root 60: #include "regs.h"
1.1 root 61:
62: #define MAX(x,y) (((x) > (y)) ? (x) : (y))
63: #define MIN(x,y) (((x) < (y)) ? (x) : (y))
64:
1.1.1.2 root 65: /* Nonzero if function being compiled pops its args on return.
66: May affect compilation of return insn or of function epilogue. */
67:
68: int current_function_pops_args;
69:
1.1.1.10 root 70: /* Nonzero if function being compiled needs to be given an address
71: where the value should be stored. */
72:
73: int current_function_returns_struct;
74:
75: /* Nonzero if function being compiled needs to be passed a static chain. */
76:
77: int current_function_needs_context;
78:
1.1.1.11 root 79: /* Nonzero if function being compiled can call setjmp. */
80:
81: int current_function_calls_setjmp;
82:
1.1.1.2 root 83: /* If function's args have a fixed size, this is that size, in bytes.
84: Otherwise, it is -1.
85: May affect compilation of return insn or of function epilogue. */
86:
87: int current_function_args_size;
88:
89: /* # bytes the prologue should push and pretend that the caller pushed them.
90: The prologue must do this, but only if parms can be passed in registers. */
91:
92: int current_function_pretend_args_size;
93:
94: /* Name of function now being compiled. */
95:
96: char *current_function_name;
97:
1.1 root 98: /* Label that will go on function epilogue.
99: Jumping to this label serves as a "return" instruction
100: on machines which require execution of the epilogue on all returns. */
101:
1.1.1.2 root 102: rtx return_label;
1.1 root 103:
1.1.1.5 root 104: /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
105: So we can mark them all live at the end of the function, if nonopt. */
106: rtx save_expr_regs;
107:
1.1.1.13! root 108: /* List (chain of EXPR_LISTs) of all stack slots in this function.
! 109: Made for the sake of unshare_all_rtl. */
! 110: rtx stack_slot_list;
! 111:
1.1.1.5 root 112: /* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */
113: static rtx parm_birth_insn;
114:
1.1 root 115: /* The FUNCTION_DECL node for the function being compiled. */
116:
117: static tree this_function;
118:
119: /* Offset to end of allocated area of stack frame.
120: If stack grows down, this is the address of the last stack slot allocated.
121: If stack grows up, this is the address for the next slot. */
122: static int frame_offset;
123:
1.1.1.2 root 124: /* Nonzero if a stack slot has been generated whose address is not
125: actually valid. It means that the generated rtl must all be scanned
126: to detect and correct the invalid addresses where they occur. */
127: static int invalid_stack_slot;
1.1 root 128:
129: /* Label to jump back to for tail recursion, or 0 if we have
130: not yet needed one for this function. */
131: static rtx tail_recursion_label;
132:
133: /* Place after which to insert the tail_recursion_label if we need one. */
134: static rtx tail_recursion_reentry;
135:
1.1.1.2 root 136: /* Each time we expand an expression-statement,
137: record the expr's type and its RTL value here. */
138:
139: static tree last_expr_type;
140: static rtx last_expr_value;
141:
1.1.1.10 root 142: /* Chain of all RTL_EXPRs that have insns in them. */
143: static tree rtl_expr_chain;
144:
1.1.1.8 root 145: /* Last insn of those whose job was to put parms into their nominal homes. */
146: static rtx last_parm_insn;
147:
1.1.1.6 root 148: static void expand_goto_internal ();
149: static int expand_fixup ();
1.1.1.2 root 150: static void fixup_gotos ();
1.1.1.7 root 151: static void expand_cleanups ();
152: static void fixup_cleanups ();
1.1.1.8 root 153: static void expand_null_return_1 ();
1.1 root 154: static int tail_recursion_args ();
1.1.1.8 root 155: static void fixup_stack_slots ();
1.1.1.2 root 156: static rtx fixup_stack_1 ();
157: static rtx fixup_memory_subreg ();
1.1.1.13! root 158: static rtx walk_fixup_memory_subreg ();
1.1.1.2 root 159: static void fixup_var_refs ();
1.1.1.10 root 160: static void fixup_var_refs_insns ();
1.1.1.2 root 161: static rtx fixup_var_refs_1 ();
162: static rtx parm_stack_loc ();
163: static void optimize_bit_field ();
164: void do_jump_if_equal ();
1.1 root 165:
1.1.1.13! root 166: /* Functions and data structures for expanding case statements. */
! 167:
! 168: static void balance_case_nodes ();
! 169: static void emit_case_nodes ();
! 170: static void group_case_nodes ();
! 171: static void emit_jump_if_reachable ();
! 172:
! 173: /* Case label structure, used to hold info on labels within case
! 174: statements. We handle "range" labels; for a single-value label
! 175: as in C, the high and low limits are the same. */
! 176:
! 177: struct case_node
! 178: {
! 179: struct case_node *left;
! 180: struct case_node *right;
! 181: struct case_node *parent;
! 182: tree low;
! 183: tree high;
! 184: tree test_label;
! 185: tree code_label;
! 186: };
! 187:
! 188: typedef struct case_node case_node;
! 189: typedef struct case_node *case_node_ptr;
! 190:
1.1.1.2 root 191: /* Stack of control and binding constructs we are currently inside.
1.1 root 192:
1.1.1.2 root 193: These constructs begin when you call `expand_start_WHATEVER'
194: and end when you call `expand_end_WHATEVER'. This stack records
195: info about how the construct began that tells the end-function
196: what to do. It also may provide information about the construct
197: to alter the behavior of other constructs within the body.
198: For example, they may affect the behavior of C `break' and `continue'.
199:
200: Each construct gets one `struct nesting' object.
201: All of these objects are chained through the `all' field.
202: `nesting_stack' points to the first object (innermost construct).
203: The position of an entry on `nesting_stack' is in its `depth' field.
204:
205: Each type of construct has its own individual stack.
206: For example, loops have `loop_stack'. Each object points to the
207: next object of the same type through the `next' field.
208:
209: Some constructs are visible to `break' exit-statements and others
210: are not. Which constructs are visible depends on the language.
211: Therefore, the data structure allows each construct to be visible
212: or not, according to the args given when the construct is started.
213: The construct is visible if the `exit_label' field is non-null.
214: In that case, the value should be a CODE_LABEL rtx. */
215:
216: struct nesting
1.1 root 217: {
1.1.1.2 root 218: struct nesting *all;
219: struct nesting *next;
220: int depth;
221: rtx exit_label;
222: union
223: {
224: /* For conds (if-then and if-then-else statements). */
225: struct
226: {
227: /* Label on the else-part, if any, else 0. */
228: rtx else_label;
229: /* Label at the end of the whole construct. */
230: rtx after_label;
231: } cond;
232: /* For loops. */
233: struct
234: {
235: /* Label at the top of the loop; place to loop back to. */
236: rtx start_label;
237: /* Label at the end of the whole construct. */
238: rtx end_label;
239: /* Label for `continue' statement to jump to;
240: this is in front of the stepper of the loop. */
241: rtx continue_label;
242: } loop;
243: /* For variable binding contours. */
244: struct
245: {
246: /* Nonzero => value to restore stack to on exit. */
247: rtx stack_level;
248: /* The NOTE that starts this contour.
249: Used by expand_goto to check whether the destination
250: is within each contour or not. */
251: rtx first_insn;
252: /* Innermost containing binding contour that has a stack level. */
253: struct nesting *innermost_stack_block;
1.1.1.7 root 254: /* List of cleanups to be run on exit from this contour.
255: This is a list of expressions to be evaluated.
256: The TREE_PURPOSE of each link is the ..._DECL node
257: which the cleanup pertains to. */
258: tree cleanups;
1.1.1.13! root 259: /* List of cleanup-lists of blocks containing this block,
! 260: as they were at the locus where this block appears.
! 261: There is an element for each containing block,
! 262: ordered innermost containing block first.
! 263: The element's TREE_VALUE is the cleanup-list of that block,
! 264: which may be null. */
! 265: tree outer_cleanups;
1.1.1.2 root 266: /* Chain of labels defined inside this binding contour.
1.1.1.8 root 267: For contours that have stack levels or cleanups. */
1.1.1.2 root 268: struct label_chain *label_chain;
269: } block;
270: /* For switch (C) or case (Pascal) statements,
271: and also for dummies (see `expand_start_case_dummy'). */
272: struct
273: {
274: /* The insn after which the case dispatch should finally
275: be emitted. Zero for a dummy. */
276: rtx start;
1.1.1.13! root 277: /* A list of case labels, kept in ascending order by value
! 278: as the list is built.
! 279: During expand_end_case, this list may be rearranged into a
! 280: nearly balanced binary tree. */
! 281: struct case_node *case_list;
! 282: /* Label to jump to if no case matches. */
! 283: tree default_label;
1.1.1.2 root 284: /* The expression to be dispatched on. */
285: tree index_expr;
286: /* Type that INDEX_EXPR should be converted to. */
287: tree nominal_type;
1.1.1.13! root 288: /* Number of range exprs in case statement. */
! 289: short num_ranges;
1.1.1.2 root 290: } case_stmt;
291: } data;
292: };
1.1 root 293:
1.1.1.2 root 294: /* Chain of all pending binding contours. */
295: struct nesting *block_stack;
1.1 root 296:
1.1.1.7 root 297: /* Chain of all pending binding contours that restore stack levels
298: or have cleanups. */
1.1.1.2 root 299: struct nesting *stack_block_stack;
1.1 root 300:
1.1.1.2 root 301: /* Chain of all pending conditional statements. */
302: struct nesting *cond_stack;
1.1 root 303:
1.1.1.2 root 304: /* Chain of all pending loops. */
305: struct nesting *loop_stack;
306:
307: /* Chain of all pending case or switch statements. */
308: struct nesting *case_stack;
309:
310: /* Separate chain including all of the above,
311: chained through the `all' field. */
312: struct nesting *nesting_stack;
313:
314: /* Number of entries on nesting_stack now. */
315: int nesting_depth;
316:
317: /* Pop one of the sub-stacks, such as `loop_stack' or `cond_stack';
318: and pop off `nesting_stack' down to the same level. */
319:
320: #define POPSTACK(STACK) \
321: do { int initial_depth = nesting_stack->depth; \
322: do { struct nesting *this = STACK; \
323: STACK = this->next; \
324: nesting_stack = this->all; \
325: nesting_depth = this->depth; \
326: free (this); } \
327: while (nesting_depth > initial_depth); } while (0)
328:
1.1 root 329: /* Return the rtx-label that corresponds to a LABEL_DECL,
330: creating it if necessary. */
331:
332: static rtx
333: label_rtx (label)
334: tree label;
335: {
1.1.1.2 root 336: if (TREE_CODE (label) != LABEL_DECL)
337: abort ();
338:
1.1 root 339: if (DECL_RTL (label))
340: return DECL_RTL (label);
341:
342: return DECL_RTL (label) = gen_label_rtx ();
343: }
344:
345: /* Add an unconditional jump to LABEL as the next sequential instruction. */
346:
347: void
348: emit_jump (label)
349: rtx label;
350: {
351: do_pending_stack_adjust ();
352: emit_jump_insn (gen_jump (label));
353: emit_barrier ();
354: }
1.1.1.2 root 355:
356: /* Handle goto statements and the labels that they can go to. */
1.1 root 357:
1.1.1.2 root 358: /* In some cases it is impossible to generate code for a forward goto
359: until the label definition is seen. This happens when it may be necessary
360: for the goto to reset the stack pointer: we don't yet know how to do that.
361: So expand_goto puts an entry on this fixup list.
362: Each time a binding contour that resets the stack is exited,
363: we check each fixup.
364: If the target label has now been defined, we can insert the proper code. */
1.1 root 365:
1.1.1.2 root 366: struct goto_fixup
1.1 root 367: {
1.1.1.2 root 368: /* Points to following fixup. */
369: struct goto_fixup *next;
370: /* Points to the insn before the jump insn.
371: If more code must be inserted, it goes after this insn. */
372: rtx before_jump;
1.1.1.6 root 373: /* The LABEL_DECL that this jump is jumping to, or 0
374: for break, continue or return. */
1.1.1.2 root 375: tree target;
1.1.1.6 root 376: /* The CODE_LABEL rtx that this is jumping to. */
377: rtx target_rtl;
1.1.1.2 root 378: /* The outermost stack level that should be restored for this jump.
379: Each time a binding contour that resets the stack is exited,
380: if the target label is *not* yet defined, this slot is updated. */
381: rtx stack_level;
1.1.1.13! root 382: /* List of lists of cleanup expressions to be run by this goto.
! 383: There is one element for each block that this goto is within.
! 384: The TREE_VALUE contains the cleanup list of that block as of the
! 385: time this goto was seen.
! 386: The TREE_ADDRESSABLE flag is 1 for a block that has been exited. */
1.1.1.7 root 387: tree cleanup_list_list;
1.1.1.2 root 388: };
389:
390: static struct goto_fixup *goto_fixup_chain;
391:
392: /* Within any binding contour that must restore a stack level,
393: all labels are recorded with a chain of these structures. */
394:
395: struct label_chain
396: {
397: /* Points to following fixup. */
398: struct label_chain *next;
399: tree label;
400: };
401:
402: /* Specify the location in the RTL code of a label BODY,
403: which is a LABEL_DECL tree node.
404:
405: This is used for the kind of label that the user can jump to with a
406: goto statement, and for alternatives of a switch or case statement.
407: RTL labels generated for loops and conditionals don't go through here;
408: they are generated directly at the RTL level, by other functions below.
409:
410: Note that this has nothing to do with defining label *names*.
411: Languages vary in how they do that and what that even means. */
412:
413: void
414: expand_label (body)
415: tree body;
416: {
417: struct label_chain *p;
418:
419: do_pending_stack_adjust ();
420: emit_label (label_rtx (body));
421:
1.1.1.7 root 422: if (stack_block_stack != 0)
1.1.1.2 root 423: {
424: p = (struct label_chain *) oballoc (sizeof (struct label_chain));
425: p->next = stack_block_stack->data.block.label_chain;
426: stack_block_stack->data.block.label_chain = p;
427: p->label = body;
428: }
1.1 root 429: }
430:
1.1.1.2 root 431: /* Generate RTL code for a `goto' statement with target label BODY.
432: BODY should be a LABEL_DECL tree node that was or will later be
433: defined with `expand_label'. */
434:
435: void
436: expand_goto (body)
437: tree body;
1.1 root 438: {
1.1.1.8 root 439: expand_goto_internal (body, label_rtx (body), 0);
1.1.1.6 root 440: }
441:
1.1.1.8 root 442: /* Generate RTL code for a `goto' statement with target label BODY.
443: LABEL should be a LABEL_REF.
444: LAST_INSN, if non-0, is the rtx we should consider as the last
1.1.1.9 root 445: insn emitted (for the purposes of cleaning up a return). */
1.1.1.8 root 446:
1.1.1.6 root 447: static void
1.1.1.8 root 448: expand_goto_internal (body, label, last_insn)
1.1.1.6 root 449: tree body;
450: rtx label;
1.1.1.8 root 451: rtx last_insn;
1.1.1.6 root 452: {
1.1.1.2 root 453: struct nesting *block;
454: rtx stack_level = 0;
455:
456: if (GET_CODE (label) != CODE_LABEL)
457: abort ();
458:
459: /* If label has already been defined, we can tell now
460: whether and how we must alter the stack level. */
461:
1.1.1.6 root 462: if (PREV_INSN (label) != 0)
1.1.1.2 root 463: {
1.1.1.13! root 464: /* Find the innermost pending block that contains the label.
1.1.1.2 root 465: (Check containment by comparing insn-uids.)
1.1.1.13! root 466: Then restore the outermost stack level within that block,
! 467: and do cleanups of all blocks contained in it. */
1.1.1.2 root 468: for (block = block_stack; block; block = block->next)
469: {
470: if (INSN_UID (block->data.block.first_insn) < INSN_UID (label))
471: break;
472: if (block->data.block.stack_level != 0)
473: stack_level = block->data.block.stack_level;
1.1.1.7 root 474: /* Execute the cleanups for blocks we are exiting. */
475: if (block->data.block.cleanups != 0)
476: expand_cleanups (block->data.block.cleanups, 0);
1.1.1.2 root 477: }
478:
479: if (stack_level)
480: emit_move_insn (stack_pointer_rtx, stack_level);
481:
1.1.1.6 root 482: if (body != 0 && TREE_PACKED (body))
1.1.1.13! root 483: error ("jump to `%s' invalidly jumps into binding contour",
1.1.1.2 root 484: IDENTIFIER_POINTER (DECL_NAME (body)));
485: }
486: /* Label not yet defined: may need to put this goto
487: on the fixup list. */
1.1.1.8 root 488: else if (! expand_fixup (body, label, last_insn))
1.1.1.13! root 489: {
! 490: /* No fixup needed. Record that the label is the target
! 491: of at least one goto that has no fixup. */
! 492: if (body != 0)
! 493: TREE_ADDRESSABLE (body) = 1;
! 494: }
1.1.1.2 root 495:
1.1.1.6 root 496: emit_jump (label);
497: }
498:
499: /* Generate if necessary a fixup for a goto
500: whose target label in tree structure (if any) is TREE_LABEL
501: and whose target in rtl is RTL_LABEL.
502:
1.1.1.8 root 503: If LAST_INSN is nonzero, we pretend that the jump appears
504: after insn LAST_INSN instead of at the current point in the insn stream.
505:
1.1.1.6 root 506: The fixup will be used later to insert insns at this point
507: to restore the stack level as appropriate for the target label.
508:
509: Value is nonzero if a fixup is made. */
510:
511: static int
1.1.1.8 root 512: expand_fixup (tree_label, rtl_label, last_insn)
1.1.1.6 root 513: tree tree_label;
514: rtx rtl_label;
1.1.1.8 root 515: rtx last_insn;
1.1.1.6 root 516: {
1.1.1.13! root 517: struct nesting *block, *end_block;
! 518:
! 519: /* See if we can recognize which block the label will be output in.
! 520: This is possible in some very common cases.
! 521: If we succeed, set END_BLOCK to that block.
! 522: Otherwise, set it to 0. */
! 523:
! 524: if (cond_stack
! 525: && (rtl_label == cond_stack->data.cond.else_label
! 526: || rtl_label == cond_stack->data.cond.after_label))
! 527: end_block = cond_stack;
! 528: /* If we are in a loop, recognize certain labels which
! 529: are likely targets. This reduces the number of fixups
! 530: we need to create. */
! 531: else if (loop_stack
! 532: && (rtl_label == loop_stack->data.loop.start_label
! 533: || rtl_label == loop_stack->data.loop.end_label
! 534: || rtl_label == loop_stack->data.loop.continue_label))
! 535: end_block = loop_stack;
! 536: else
! 537: end_block = 0;
! 538:
! 539: /* Now set END_BLOCK to the binding level to which we will return. */
! 540:
! 541: if (end_block)
! 542: {
! 543: struct nesting *next_block = end_block->all;
! 544: block = block_stack;
! 545:
! 546: /* First see if the END_BLOCK is inside the innermost binding level.
! 547: If so, then no cleanups or stack levels are relevant. */
! 548: while (next_block && next_block != block)
! 549: next_block = next_block->all;
! 550:
! 551: if (next_block)
! 552: return 0;
! 553:
! 554: /* Otherwise, set END_BLOCK to the innermost binding level
! 555: which is outside the relevant control-structure nesting. */
! 556: next_block = block_stack->next;
! 557: for (block = block_stack; block != end_block; block = block->all)
! 558: if (block == next_block)
! 559: next_block = next_block->next;
! 560: end_block = next_block;
! 561: }
! 562:
1.1.1.7 root 563: /* Does any containing block have a stack level or cleanups?
1.1.1.6 root 564: If not, no fixup is needed, and that is the normal case
565: (the only case, for standard C). */
1.1.1.13! root 566: for (block = block_stack; block != end_block; block = block->next)
1.1.1.7 root 567: if (block->data.block.stack_level != 0
568: || block->data.block.cleanups != 0)
1.1.1.6 root 569: break;
570:
1.1.1.13! root 571: if (block != end_block)
1.1.1.6 root 572: {
573: /* Ok, a fixup is needed. Add a fixup to the list of such. */
574: struct goto_fixup *fixup
575: = (struct goto_fixup *) oballoc (sizeof (struct goto_fixup));
576: /* In case an old stack level is restored, make sure that comes
577: after any pending stack adjust. */
578: do_pending_stack_adjust ();
1.1.1.8 root 579: fixup->before_jump = last_insn ? last_insn : get_last_insn ();
1.1.1.6 root 580: fixup->target = tree_label;
581: fixup->target_rtl = rtl_label;
582: fixup->stack_level = 0;
1.1.1.13! root 583: fixup->cleanup_list_list
! 584: = (block->data.block.outer_cleanups || block->data.block.cleanups
! 585: ? tree_cons (0, block->data.block.cleanups,
! 586: block->data.block.outer_cleanups)
! 587: : 0);
1.1.1.6 root 588: fixup->next = goto_fixup_chain;
589: goto_fixup_chain = fixup;
1.1.1.2 root 590: }
591:
1.1.1.6 root 592: return block != 0;
1.1 root 593: }
594:
1.1.1.2 root 595: /* When exiting a binding contour, process all pending gotos requiring fixups.
1.1.1.13! root 596: THISBLOCK is the structure that describes the block being exited.
1.1.1.7 root 597: STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
1.1.1.13! root 598: CLEANUP_LIST is a list of expressions to evaluate on exiting this contour.
! 599: FIRST_INSN is the insn that began this contour.
1.1.1.7 root 600:
1.1.1.2 root 601: Gotos that jump out of this contour must restore the
1.1.1.7 root 602: stack level and do the cleanups before actually jumping.
1.1 root 603:
1.1.1.7 root 604: DONT_JUMP_IN nonzero means report error there is a jump into this
605: contour from before the beginning of the contour.
606: This is also done if STACK_LEVEL is nonzero. */
1.1 root 607:
1.1.1.2 root 608: static void
1.1.1.13! root 609: fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
! 610: struct nesting *thisblock;
1.1.1.2 root 611: rtx stack_level;
1.1.1.7 root 612: tree cleanup_list;
1.1.1.2 root 613: rtx first_insn;
1.1.1.7 root 614: int dont_jump_in;
1.1 root 615: {
1.1.1.13! root 616: register struct goto_fixup *f, *prev;
1.1 root 617:
1.1.1.13! root 618: /* F is the fixup we are considering; PREV is the previous one. */
! 619:
! 620: for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
1.1.1.2 root 621: {
622: /* Test for a fixup that is inactive because it is already handled. */
623: if (f->before_jump == 0)
1.1.1.13! root 624: {
! 625: /* Delete inactive fixup from the chain, if that is easy to do. */
! 626: if (prev != 0)
! 627: prev->next = f->next;
! 628: }
1.1.1.2 root 629: /* Has this fixup's target label been defined?
630: If so, we can finalize it. */
1.1.1.6 root 631: else if (PREV_INSN (f->target_rtl) != 0)
1.1.1.2 root 632: {
633: /* If this fixup jumped into this contour from before the beginning
634: of this contour, report an error. */
1.1.1.13! root 635: /* ??? Bug: this does not detect jumping in through intermediate
! 636: blocks that have stack levels or cleanups.
! 637: It detects only a problem with the innermost block
! 638: around the label. */
1.1.1.6 root 639: if (f->target != 0
1.1.1.13! root 640: && (dont_jump_in || stack_level || cleanup_list)
1.1.1.6 root 641: && INSN_UID (first_insn) > INSN_UID (f->before_jump)
1.1.1.2 root 642: && ! TREE_ADDRESSABLE (f->target))
643: {
1.1.1.13! root 644: error_with_decl (f->target,
! 645: "label `%s' used before containing binding contour");
1.1.1.2 root 646: /* Prevent multiple errors for one label. */
647: TREE_ADDRESSABLE (f->target) = 1;
648: }
1.1 root 649:
1.1.1.7 root 650: /* Execute cleanups for blocks this jump exits. */
651: if (f->cleanup_list_list)
1.1.1.13! root 652: {
! 653: tree lists;
! 654: for (lists = f->cleanup_list_list; lists; lists = TREE_CHAIN (lists))
! 655: /* Marked elements correspond to blocks that have been closed.
! 656: Do their cleanups. */
! 657: if (TREE_ADDRESSABLE (lists)
! 658: && TREE_VALUE (lists) != 0)
! 659: fixup_cleanups (TREE_VALUE (lists), &f->before_jump);
! 660: }
1.1.1.7 root 661:
1.1.1.2 root 662: /* Restore stack level for the biggest contour that this
663: jump jumps out of. */
664: if (f->stack_level)
665: emit_insn_after (gen_move_insn (stack_pointer_rtx, f->stack_level),
666: f->before_jump);
667: f->before_jump = 0;
668: }
669: /* Label has still not appeared. If we are exiting a block with
670: a stack level to restore, mark this stack level as needing
1.1.1.13! root 671: restoration when the fixup is later finalized.
! 672: Also mark the cleanup_list_list element for F
! 673: that corresponds to this block, so that ultimately
! 674: this block's cleanups will be executed by the code above. */
1.1.1.7 root 675: else
676: {
1.1.1.13! root 677: tree lists = f->cleanup_list_list;
! 678: for (; lists; lists = TREE_CHAIN (lists))
! 679: /* If the following elt. corresponds to our containing block
! 680: then the elt. must be for this block. */
! 681: if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)
! 682: TREE_ADDRESSABLE (lists) = 1;
! 683:
1.1.1.7 root 684: if (stack_level)
685: f->stack_level = stack_level;
686: }
1.1.1.2 root 687: }
688: }
689:
690: /* Generate RTL for an asm statement (explicit assembler code).
691: BODY is a STRING_CST node containing the assembler code text. */
692:
693: void
694: expand_asm (body)
695: tree body;
1.1 root 696: {
1.1.1.2 root 697: emit_insn (gen_rtx (ASM_INPUT, VOIDmode,
698: TREE_STRING_POINTER (body)));
699: last_expr_type = 0;
700: }
701:
702: /* Generate RTL for an asm statement with arguments.
703: STRING is the instruction template.
704: OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
705: Each output or input has an expression in the TREE_VALUE and
706: a constraint-string in the TREE_PURPOSE.
1.1.1.8 root 707: CLOBBERS is a list of STRING_CST nodes each naming a hard register
708: that is clobbered by this insn.
1.1.1.2 root 709:
710: Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
711: Some elements of OUTPUTS may be replaced with trees representing temporary
712: values. The caller should copy those temporary values to the originally
713: specified lvalues.
1.1 root 714:
1.1.1.2 root 715: VOL nonzero means the insn is volatile; don't optimize it. */
1.1 root 716:
1.1.1.2 root 717: void
1.1.1.13! root 718: expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
1.1.1.8 root 719: tree string, outputs, inputs, clobbers;
1.1.1.2 root 720: int vol;
1.1.1.13! root 721: char *filename;
! 722: int line;
1.1.1.2 root 723: {
724: rtvec argvec, constraints;
725: rtx body;
726: int ninputs = list_length (inputs);
727: int noutputs = list_length (outputs);
1.1.1.8 root 728: int nclobbers = list_length (clobbers);
1.1.1.2 root 729: tree tail;
1.1.1.13! root 730: register int i;
! 731: /* Vector of RTX's of evaluated output operands. */
! 732: rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
! 733: /* The insn we have emitted. */
! 734: rtx insn;
1.1.1.2 root 735:
1.1.1.4 root 736: last_expr_type = 0;
737:
1.1.1.2 root 738: for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
739: {
740: tree val = TREE_VALUE (tail);
1.1 root 741:
1.1.1.4 root 742: /* If there's an erroneous arg, emit no insn. */
743: if (TREE_TYPE (val) == error_mark_node)
744: return;
745:
1.1.1.2 root 746: /* If an output operand is not a variable or indirect ref,
747: create a SAVE_EXPR which is a pseudo-reg
748: to act as an intermediate temporary.
749: Make the asm insn write into that, then copy it to
750: the real output operand. */
751:
752: if (TREE_CODE (val) != VAR_DECL
753: && TREE_CODE (val) != PARM_DECL
754: && TREE_CODE (val) != INDIRECT_REF)
1.1.1.10 root 755: {
756: rtx reg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (val)));
757: /* `build' isn't safe; it really expects args to be trees. */
758: tree t = build_nt (SAVE_EXPR, val, reg);
759:
760: save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, reg, save_expr_regs);
761: TREE_VALUE (tail) = t;
762: TREE_TYPE (t) = TREE_TYPE (val);
763: }
1.1.1.13! root 764: output_rtx[i] = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0);
1.1.1.2 root 765: }
1.1 root 766:
1.1.1.8 root 767: if (ninputs + noutputs > MAX_RECOG_OPERANDS)
768: {
769: error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
770: return;
771: }
772:
1.1.1.2 root 773: /* Make vectors for the expression-rtx and constraint strings. */
1.1 root 774:
1.1.1.4 root 775: argvec = rtvec_alloc (ninputs);
776: constraints = rtvec_alloc (ninputs);
1.1 root 777:
1.1.1.2 root 778: body = gen_rtx (ASM_OPERANDS, VOIDmode,
779: TREE_STRING_POINTER (string), "", 0, argvec, constraints);
1.1.1.10 root 780: MEM_VOLATILE_P (body) = vol;
1.1 root 781:
1.1.1.2 root 782: /* Eval the inputs and put them into ARGVEC.
783: Put their constraints into ASM_INPUTs and store in CONSTRAINTS. */
1.1 root 784:
1.1.1.2 root 785: i = 0;
786: for (tail = inputs; tail; tail = TREE_CHAIN (tail))
787: {
1.1.1.4 root 788: /* If there's an erroneous arg, emit no insn,
789: because the ASM_INPUT would get VOIDmode
790: and that could cause a crash in reload. */
791: if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
792: return;
1.1.1.8 root 793: if (TREE_PURPOSE (tail) == NULL_TREE)
794: {
1.1.1.13! root 795: error ("hard register `%s' listed as input operand to `asm'",
1.1.1.8 root 796: TREE_STRING_POINTER (TREE_VALUE (tail)) );
797: return;
798: }
1.1.1.4 root 799:
1.1.1.2 root 800: XVECEXP (body, 3, i) /* argvec */
801: = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0);
802: XVECEXP (body, 4, i) /* constraints */
803: = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
804: TREE_STRING_POINTER (TREE_PURPOSE (tail)));
805: i++;
806: }
1.1 root 807:
1.1.1.13! root 808: /* Protect all the operands from the queue,
! 809: now that they have all been evaluated. */
! 810:
! 811: for (i = 0; i < ninputs; i++)
! 812: XVECEXP (body, 3, i) = protect_from_queue (XVECEXP (body, 3, i), 0);
! 813:
! 814: for (i = 0; i < noutputs; i++)
! 815: output_rtx[i] = protect_from_queue (output_rtx[i], 1);
! 816:
1.1.1.2 root 817: /* Now, for each output, construct an rtx
818: (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT
819: ARGVEC CONSTRAINTS))
820: If there is more than one, put them inside a PARALLEL. */
1.1 root 821:
1.1.1.8 root 822: if (noutputs == 1 && nclobbers == 0)
1.1.1.2 root 823: {
824: XSTR (body, 1) = TREE_STRING_POINTER (TREE_PURPOSE (outputs));
1.1.1.13! root 825: insn = emit_insn (gen_rtx (SET, VOIDmode, output_rtx[0], body));
1.1.1.2 root 826: }
1.1.1.8 root 827: else if (noutputs == 0 && nclobbers == 0)
1.1.1.5 root 828: {
829: /* No output operands: put in a raw ASM_OPERANDS rtx. */
1.1.1.13! root 830: insn = emit_insn (body);
1.1.1.5 root 831: }
1.1.1.2 root 832: else
833: {
1.1.1.12 root 834: rtx obody = body;
835: int num = noutputs;
836: if (num == 0) num = 1;
837: body = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num + nclobbers));
1.1.1.8 root 838:
839: /* For each output operand, store a SET. */
1.1.1.2 root 840:
841: for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1.1 root 842: {
1.1.1.2 root 843: tree val = TREE_VALUE (tail);
844:
845: XVECEXP (body, 0, i)
846: = gen_rtx (SET, VOIDmode,
1.1.1.13! root 847: output_rtx[i],
1.1.1.2 root 848: gen_rtx (ASM_OPERANDS, VOIDmode,
849: TREE_STRING_POINTER (string),
850: TREE_STRING_POINTER (TREE_PURPOSE (tail)),
851: i, argvec, constraints));
1.1.1.10 root 852: MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
1.1 root 853: }
854:
1.1.1.12 root 855: /* If there are no outputs (but there are some clobbers)
856: store the bare ASM_OPERANDS into the PARALLEL. */
857:
858: if (i == 0)
859: XVECEXP (body, 0, i++) = obody;
860:
1.1.1.8 root 861: /* Store (clobber REG) for each clobbered register specified. */
862:
863: for (tail = clobbers; tail; tail = TREE_CHAIN (tail), i++)
864: {
865: int j;
866: char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
867: extern char *reg_names[];
868:
869: for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
870: if (!strcmp (regname, reg_names[j]))
871: break;
872:
873: if (j == FIRST_PSEUDO_REGISTER)
874: {
1.1.1.13! root 875: error ("unknown register name `%s' in `asm'", regname);
1.1.1.8 root 876: return;
877: }
878:
1.1.1.12 root 879: /* Use QImode since that's guaranteed to clobber just one reg. */
1.1.1.8 root 880: XVECEXP (body, 0, i)
1.1.1.12 root 881: = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, QImode, j));
1.1.1.8 root 882: }
883:
1.1.1.13! root 884: insn = emit_insn (body);
1.1.1.2 root 885: }
1.1.1.13! root 886:
! 887: /* Record the source file and line number in the insn,
! 888: for the sake of errors generated at reload or final time. */
! 889:
! 890: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_ASM_FILE,
! 891: gen_rtx (SYMBOL_REF, VOIDmode, filename),
! 892: REG_NOTES (insn));
! 893: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_ASM_LINE,
! 894: gen_rtx (CONST_INT, VOIDmode, line),
! 895: REG_NOTES (insn));
! 896:
1.1.1.2 root 897: last_expr_type = 0;
898: }
1.1 root 899:
1.1.1.2 root 900: /* Nonzero if within a ({...}) grouping, in which case we must
901: always compute a value for each expr-stmt in case it is the last one. */
1.1 root 902:
1.1.1.2 root 903: int expr_stmts_for_value;
1.1 root 904:
1.1.1.2 root 905: /* Generate RTL to evaluate the expression EXP
906: and remember it in case this is the VALUE in a ({... VALUE; }) constr. */
1.1 root 907:
1.1.1.2 root 908: void
909: expand_expr_stmt (exp)
910: tree exp;
911: {
1.1.1.13! root 912: /* If -W, warn about statements with no side effects,
! 913: except inside a ({...}) where they may be useful. */
! 914: if (extra_warnings && expr_stmts_for_value == 0 && !TREE_VOLATILE (exp))
! 915: warning ("statement with no effect");
1.1.1.2 root 916: last_expr_type = TREE_TYPE (exp);
1.1.1.13! root 917: if (! flag_syntax_only)
! 918: last_expr_value = expand_expr (exp, expr_stmts_for_value ? 0 : const0_rtx,
! 919: VOIDmode, 0);
1.1.1.2 root 920: emit_queue ();
921: }
1.1 root 922:
1.1.1.2 root 923: /* Clear out the memory of the last expression evaluated. */
1.1 root 924:
1.1.1.2 root 925: void
926: clear_last_expr ()
927: {
928: last_expr_type = 0;
929: }
1.1 root 930:
1.1.1.7 root 931: /* Begin a statement which will return a value.
1.1.1.10 root 932: Return the RTL_EXPR for this statement expr.
933: The caller must save that value and pass it to expand_end_stmt_expr. */
1.1.1.7 root 934:
935: tree
936: expand_start_stmt_expr ()
937: {
938: rtx save = start_sequence ();
1.1.1.10 root 939: /* Make the RTL_EXPR node temporary, not momentary,
940: so that rtl_expr_chain doesn't become garbage. */
941: int momentary = suspend_momentary ();
1.1.1.7 root 942: tree t = make_node (RTL_EXPR);
1.1.1.10 root 943: resume_momentary (momentary);
1.1.1.7 root 944: RTL_EXPR_RTL (t) = save;
1.1.1.10 root 945: expr_stmts_for_value++;
1.1.1.7 root 946: return t;
947: }
948:
949: /* Restore the previous state at the end of a statement that returns a value.
950: Returns a tree node representing the statement's value and the
951: insns to compute the value.
952:
1.1.1.2 root 953: The nodes of that expression have been freed by now, so we cannot use them.
954: But we don't want to do that anyway; the expression has already been
1.1.1.10 root 955: evaluated and now we just want to use the value. So generate a RTL_EXPR
1.1.1.2 root 956: with the proper type and RTL value.
1.1 root 957:
1.1.1.7 root 958: If the last substatement was not an expression,
1.1.1.2 root 959: return something with type `void'. */
1.1 root 960:
1.1.1.2 root 961: tree
1.1.1.7 root 962: expand_end_stmt_expr (t)
963: tree t;
1.1.1.2 root 964: {
1.1.1.7 root 965: rtx saved = RTL_EXPR_RTL (t);
1.1 root 966:
1.1.1.2 root 967: if (last_expr_type == 0)
968: {
969: last_expr_type = void_type_node;
970: last_expr_value = const0_rtx;
971: }
1.1.1.7 root 972: TREE_TYPE (t) = last_expr_type;
1.1.1.2 root 973: RTL_EXPR_RTL (t) = last_expr_value;
1.1.1.10 root 974: RTL_EXPR_SEQUENCE (t) = get_insns ();
975:
976: rtl_expr_chain = tree_cons (NULL_TREE, t, rtl_expr_chain);
1.1 root 977:
1.1.1.7 root 978: end_sequence (saved);
1.1.1.10 root 979:
980: /* Don't consider deleting this expr or containing exprs at tree level. */
981: TREE_VOLATILE (t) = 1;
982: /* Propagate volatility of the actual RTL expr. */
983: TREE_THIS_VOLATILE (t) = volatile_refs_p (last_expr_value);
984:
985: last_expr_type = 0;
1.1.1.2 root 986: expr_stmts_for_value--;
1.1.1.7 root 987:
988: return t;
1.1.1.2 root 989: }
990:
991: /* Generate RTL for the start of an if-then. COND is the expression
992: whose truth should be tested.
1.1 root 993:
1.1.1.2 root 994: If EXITFLAG is nonzero, this conditional is visible to
995: `exit_something'. */
1.1 root 996:
1.1.1.2 root 997: void
998: expand_start_cond (cond, exitflag)
999: tree cond;
1000: int exitflag;
1001: {
1002: struct nesting *thiscond
1003: = (struct nesting *) xmalloc (sizeof (struct nesting));
1.1 root 1004:
1.1.1.2 root 1005: /* Make an entry on cond_stack for the cond we are entering. */
1.1 root 1006:
1.1.1.2 root 1007: thiscond->next = cond_stack;
1008: thiscond->all = nesting_stack;
1009: thiscond->depth = ++nesting_depth;
1010: thiscond->data.cond.after_label = 0;
1011: thiscond->data.cond.else_label = gen_label_rtx ();
1012: thiscond->exit_label = exitflag ? thiscond->data.cond.else_label : 0;
1013: cond_stack = thiscond;
1014: nesting_stack = thiscond;
1.1 root 1015:
1.1.1.2 root 1016: do_jump (cond, thiscond->data.cond.else_label, NULL);
1017: }
1.1 root 1018:
1.1.1.2 root 1019: /* Generate RTL for the end of an if-then with no else-clause.
1020: Pop the record for it off of cond_stack. */
1.1 root 1021:
1.1.1.2 root 1022: void
1023: expand_end_cond ()
1024: {
1025: struct nesting *thiscond = cond_stack;
1.1 root 1026:
1.1.1.2 root 1027: do_pending_stack_adjust ();
1028: emit_label (thiscond->data.cond.else_label);
1.1 root 1029:
1.1.1.2 root 1030: POPSTACK (cond_stack);
1031: last_expr_type = 0;
1032: }
1.1 root 1033:
1.1.1.2 root 1034: /* Generate RTL between the then-clause and the else-clause
1035: of an if-then-else. */
1.1 root 1036:
1.1.1.2 root 1037: void
1038: expand_start_else ()
1039: {
1040: cond_stack->data.cond.after_label = gen_label_rtx ();
1041: if (cond_stack->exit_label != 0)
1042: cond_stack->exit_label = cond_stack->data.cond.after_label;
1043: emit_jump (cond_stack->data.cond.after_label);
1044: if (cond_stack->data.cond.else_label)
1045: emit_label (cond_stack->data.cond.else_label);
1046: }
1.1 root 1047:
1.1.1.2 root 1048: /* Generate RTL for the end of an if-then-else.
1049: Pop the record for it off of cond_stack. */
1050:
1051: void
1052: expand_end_else ()
1053: {
1054: struct nesting *thiscond = cond_stack;
1055:
1056: do_pending_stack_adjust ();
1057: /* Note: a syntax error can cause this to be called
1058: without first calling `expand_start_else'. */
1059: if (thiscond->data.cond.after_label)
1060: emit_label (thiscond->data.cond.after_label);
1061:
1062: POPSTACK (cond_stack);
1063: last_expr_type = 0;
1064: }
1065:
1066: /* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this
1067: loop should be exited by `exit_something'. This is a loop for which
1068: `expand_continue' will jump to the top of the loop.
1069:
1070: Make an entry on loop_stack to record the labels associated with
1071: this loop. */
1072:
1073: void
1074: expand_start_loop (exit_flag)
1075: int exit_flag;
1076: {
1077: register struct nesting *thisloop
1078: = (struct nesting *) xmalloc (sizeof (struct nesting));
1079:
1080: /* Make an entry on loop_stack for the loop we are entering. */
1081:
1082: thisloop->next = loop_stack;
1083: thisloop->all = nesting_stack;
1084: thisloop->depth = ++nesting_depth;
1085: thisloop->data.loop.start_label = gen_label_rtx ();
1086: thisloop->data.loop.end_label = gen_label_rtx ();
1087: thisloop->data.loop.continue_label = thisloop->data.loop.start_label;
1088: thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0;
1089: loop_stack = thisloop;
1090: nesting_stack = thisloop;
1091:
1092: do_pending_stack_adjust ();
1093: emit_queue ();
1094: emit_note (0, NOTE_INSN_LOOP_BEG);
1095: emit_label (thisloop->data.loop.start_label);
1096: }
1097:
1098: /* Like expand_start_loop but for a loop where the continuation point
1099: (for expand_continue_loop) will be specified explicitly. */
1.1 root 1100:
1.1.1.2 root 1101: void
1102: expand_start_loop_continue_elsewhere (exit_flag)
1103: int exit_flag;
1104: {
1105: expand_start_loop (exit_flag);
1106: loop_stack->data.loop.continue_label = gen_label_rtx ();
1107: }
1108:
1109: /* Specify the continuation point for a loop started with
1110: expand_start_loop_continue_elsewhere.
1111: Use this at the point in the code to which a continue statement
1112: should jump. */
1113:
1114: void
1115: expand_loop_continue_here ()
1116: {
1117: do_pending_stack_adjust ();
1118: emit_label (loop_stack->data.loop.continue_label);
1119: }
1120:
1121: /* Finish a loop. Generate a jump back to the top and the loop-exit label.
1122: Pop the block off of loop_stack. */
1123:
1124: void
1125: expand_end_loop ()
1126: {
1127: register rtx insn = get_last_insn ();
1128: register rtx start_label = loop_stack->data.loop.start_label;
1129:
1130: do_pending_stack_adjust ();
1131:
1132: /* If optimizing, perhaps reorder the loop. If the loop
1133: starts with a conditional exit, roll that to the end
1134: where it will optimize together with the jump back. */
1135: if (optimize
1136: &&
1137: ! (GET_CODE (insn) == JUMP_INSN
1138: && GET_CODE (PATTERN (insn)) == SET
1139: && SET_DEST (PATTERN (insn)) == pc_rtx
1140: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE))
1141: {
1142: /* Scan insns from the top of the loop looking for a qualified
1143: conditional exit. */
1144: for (insn = loop_stack->data.loop.start_label; insn; insn= NEXT_INSN (insn))
1145: if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET
1146: && SET_DEST (PATTERN (insn)) == pc_rtx
1147: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE
1148: &&
1149: ((GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == LABEL_REF
1150: && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0)
1151: == loop_stack->data.loop.end_label))
1152: ||
1153: (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 2)) == LABEL_REF
1154: && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0)
1155: == loop_stack->data.loop.end_label))))
1156: break;
1157: if (insn != 0)
1158: {
1159: /* We found one. Move everything from there up
1160: to the end of the loop, and add a jump into the loop
1161: to jump to there. */
1162: register rtx newstart_label = gen_label_rtx ();
1163:
1164: emit_label_after (newstart_label, PREV_INSN (start_label));
1165: reorder_insns (start_label, insn, get_last_insn ());
1166: emit_jump_insn_after (gen_jump (start_label), PREV_INSN (newstart_label));
1167: emit_barrier_after (PREV_INSN (newstart_label));
1168: start_label = newstart_label;
1169: }
1170: }
1171:
1172: emit_jump (start_label);
1173: emit_note (0, NOTE_INSN_LOOP_END);
1174: emit_label (loop_stack->data.loop.end_label);
1175:
1176: POPSTACK (loop_stack);
1177:
1178: last_expr_type = 0;
1179: }
1180:
1181: /* Generate a jump to the current loop's continue-point.
1182: This is usually the top of the loop, but may be specified
1183: explicitly elsewhere. If not currently inside a loop,
1184: return 0 and do nothing; caller will print an error message. */
1185:
1186: int
1187: expand_continue_loop ()
1188: {
1189: last_expr_type = 0;
1190: if (loop_stack == 0)
1191: return 0;
1.1.1.8 root 1192: expand_goto_internal (0, loop_stack->data.loop.continue_label, 0);
1.1.1.2 root 1193: return 1;
1194: }
1195:
1196: /* Generate a jump to exit the current loop. If not currently inside a loop,
1197: return 0 and do nothing; caller will print an error message. */
1198:
1199: int
1200: expand_exit_loop ()
1201: {
1202: last_expr_type = 0;
1203: if (loop_stack == 0)
1204: return 0;
1.1.1.8 root 1205: expand_goto_internal (0, loop_stack->data.loop.end_label, 0);
1.1.1.2 root 1206: return 1;
1207: }
1208:
1209: /* Generate a conditional jump to exit the current loop if COND
1210: evaluates to zero. If not currently inside a loop,
1211: return 0 and do nothing; caller will print an error message. */
1212:
1213: int
1214: expand_exit_loop_if_false (cond)
1215: tree cond;
1216: {
1217: last_expr_type = 0;
1218: if (loop_stack == 0)
1219: return 0;
1220: do_jump (cond, loop_stack->data.loop.end_label, NULL);
1221: return 1;
1222: }
1223:
1224: /* Generate a jump to exit the current loop, conditional, binding contour
1225: or case statement. Not all such constructs are visible to this function,
1226: only those started with EXIT_FLAG nonzero. Individual languages use
1227: the EXIT_FLAG parameter to control which kinds of constructs you can
1228: exit this way.
1229:
1230: If not currently inside anything that can be exited,
1231: return 0 and do nothing; caller will print an error message. */
1232:
1233: int
1234: expand_exit_something ()
1235: {
1236: struct nesting *n;
1237: last_expr_type = 0;
1238: for (n = nesting_stack; n; n = n->all)
1.1.1.7 root 1239: if (n->exit_label != 0)
1240: {
1.1.1.8 root 1241: expand_goto_internal (0, n->exit_label, 0);
1.1.1.7 root 1242: return 1;
1243: }
1244:
1.1.1.2 root 1245: return 0;
1246: }
1247:
1248: /* Generate RTL to return from the current function, with no value.
1249: (That is, we do not do anything about returning any value.) */
1250:
1251: void
1252: expand_null_return ()
1253: {
1.1.1.8 root 1254: expand_null_return_1 (0);
1255: }
1256:
1257: /* Output a return with no value. If LAST_INSN is nonzero,
1258: pretend that the return takes place after LAST_INSN. */
1259:
1260: static void
1261: expand_null_return_1 (last_insn)
1262: rtx last_insn;
1263: {
1.1.1.2 root 1264: clear_pending_stack_adjust ();
1.1.1.10 root 1265: do_pending_stack_adjust ();
1.1.1.2 root 1266: #ifdef FUNCTION_EPILOGUE
1.1.1.8 root 1267: #ifdef HAVE_return
1268: if (! HAVE_return)
1269: expand_goto_internal (0, return_label, last_insn);
1270: else
1271: {
1272: emit_jump_insn (gen_return ());
1273: emit_barrier ();
1274: }
1.1.1.2 root 1275: #else
1.1.1.8 root 1276: expand_goto_internal (0, return_label, last_insn);
1277: #endif
1278: #else /* no FUNCTION_EPILOGUE */
1.1.1.2 root 1279: emit_jump_insn (gen_return ());
1280: emit_barrier ();
1281: #endif
1282: last_expr_type = 0;
1283: }
1.1 root 1284:
1.1.1.2 root 1285: /* Generate RTL to evaluate the expression RETVAL and return it
1286: from the current function. */
1.1 root 1287:
1.1.1.2 root 1288: void
1289: expand_return (retval)
1290: tree retval;
1291: {
1.1.1.8 root 1292: /* If there are any cleanups to be performed, then they will
1293: be inserted in front of our `last_insn'. It is desirable
1294: that the last_insn, for such purposes, should be the
1295: last insn before computing the return value. Otherwise, cleanups
1296: which call functions can clobber the return value. */
1297: rtx last_insn = get_last_insn ();
1.1.1.2 root 1298: register rtx val = 0;
1299: register rtx op0;
1.1.1.7 root 1300: tree retval_rhs;
1301:
1302: if (TREE_CODE (retval) == RESULT_DECL)
1303: retval_rhs = retval;
1304: else if ((TREE_CODE (retval) == MODIFY_EXPR || TREE_CODE (retval) == INIT_EXPR)
1305: && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
1306: retval_rhs = TREE_OPERAND (retval, 1);
1307: else
1308: retval_rhs = NULL_TREE;
1.1.1.2 root 1309:
1310: /* For tail-recursive call to current function,
1311: just jump back to the beginning.
1312: It's unsafe if any auto variable in this function
1313: has its address taken; for simplicity,
1314: require stack frame to be empty. */
1.1.1.7 root 1315: if (optimize && retval_rhs != 0
1.1.1.3 root 1316: && frame_offset == STARTING_FRAME_OFFSET
1.1.1.7 root 1317: && TREE_CODE (retval_rhs) == CALL_EXPR
1318: && TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR
1319: && TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0) == this_function
1.1.1.2 root 1320: /* Finish checking validity, and if valid emit code
1321: to set the argument variables for the new call. */
1.1.1.8 root 1322: && tail_recursion_args (TREE_OPERAND (retval_rhs, 1),
1.1.1.2 root 1323: DECL_ARGUMENTS (this_function)))
1324: {
1325: ;
1326: if (tail_recursion_label == 0)
1327: {
1328: tail_recursion_label = gen_label_rtx ();
1329: emit_label_after (tail_recursion_label,
1330: tail_recursion_reentry);
1331: }
1.1.1.8 root 1332: expand_goto_internal (0, tail_recursion_label, last_insn);
1.1.1.2 root 1333: emit_barrier ();
1334: return;
1335: }
1.1.1.8 root 1336: #ifdef HAVE_return
1337: if (HAVE_return)
1338: {
1339: /* If this is return x == y; then generate
1340: if (x == y) return 1; else return 0;
1341: if we can do it with explicit return insns. */
1342: if (retval_rhs)
1343: switch (TREE_CODE (retval_rhs))
1344: {
1345: case EQ_EXPR:
1346: case NE_EXPR:
1347: case GT_EXPR:
1348: case GE_EXPR:
1349: case LT_EXPR:
1350: case LE_EXPR:
1351: case TRUTH_ANDIF_EXPR:
1352: case TRUTH_ORIF_EXPR:
1.1.1.10 root 1353: case TRUTH_AND_EXPR:
1354: case TRUTH_OR_EXPR:
1.1.1.8 root 1355: case TRUTH_NOT_EXPR:
1356: op0 = gen_label_rtx ();
1357: val = DECL_RTL (DECL_RESULT (this_function));
1358: jumpifnot (retval_rhs, op0);
1359: emit_move_insn (val, const1_rtx);
1360: emit_insn (gen_rtx (USE, VOIDmode, val));
1361: expand_null_return ();
1362: emit_label (op0);
1363: emit_move_insn (val, const0_rtx);
1364: emit_insn (gen_rtx (USE, VOIDmode, val));
1365: expand_null_return ();
1366: return;
1367: }
1368: }
1369: #endif /* HAVE_return */
1.1.1.2 root 1370: val = expand_expr (retval, 0, VOIDmode, 0);
1.1 root 1371: emit_queue ();
1.1.1.2 root 1372:
1.1.1.7 root 1373: if (retval_rhs && GET_CODE (val) == REG)
1.1.1.2 root 1374: emit_insn (gen_rtx (USE, VOIDmode, val));
1375:
1.1.1.8 root 1376: expand_null_return_1 (last_insn);
1.1.1.2 root 1377: }
1378:
1379: /* Return 1 if the end of the generated RTX is not a barrier.
1380: This means code already compiled can drop through. */
1381:
1382: int
1383: drop_through_at_end_p ()
1384: {
1385: rtx insn = get_last_insn ();
1386: while (insn && GET_CODE (insn) == NOTE)
1387: insn = PREV_INSN (insn);
1388: return insn && GET_CODE (insn) != BARRIER;
1.1 root 1389: }
1390:
1391: /* Emit code to alter this function's formal parms for a tail-recursive call.
1392: ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs).
1393: FORMALS is the chain of decls of formals.
1394: Return 1 if this can be done;
1395: otherwise return 0 and do not emit any code. */
1396:
1397: static int
1398: tail_recursion_args (actuals, formals)
1399: tree actuals, formals;
1400: {
1401: register tree a = actuals, f = formals;
1402: register int i;
1403: register rtx *argvec;
1404:
1405: /* Check that number and types of actuals are compatible
1406: with the formals. This is not always true in valid C code.
1407: Also check that no formal needs to be addressable
1408: and that all formals are scalars. */
1409:
1410: /* Also count the args. */
1411:
1412: for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)
1413: {
1414: if (TREE_TYPE (TREE_VALUE (a)) != TREE_TYPE (f))
1415: return 0;
1416: if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)
1417: return 0;
1418: }
1419: if (a != 0 || f != 0)
1420: return 0;
1421:
1422: /* Compute all the actuals. */
1423:
1424: argvec = (rtx *) alloca (i * sizeof (rtx));
1425:
1426: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
1427: argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0);
1428:
1429: /* Find which actual values refer to current values of previous formals.
1430: Copy each of them now, before any formal is changed. */
1431:
1432: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
1433: {
1434: int copy = 0;
1435: register int j;
1436: for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++)
1437: if (reg_mentioned_p (DECL_RTL (f), argvec[i]))
1438: { copy = 1; break; }
1439: if (copy)
1440: argvec[i] = copy_to_reg (argvec[i]);
1441: }
1442:
1443: /* Store the values of the actuals into the formals. */
1444:
1.1.1.2 root 1445: for (f = formals, a = actuals, i = 0; f;
1446: f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++)
1.1 root 1447: {
1448: if (DECL_MODE (f) == GET_MODE (argvec[i]))
1449: emit_move_insn (DECL_RTL (f), argvec[i]);
1450: else
1.1.1.2 root 1451: convert_move (DECL_RTL (f), argvec[i],
1452: TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a))));
1.1 root 1453: }
1454:
1455: return 1;
1456: }
1457:
1.1.1.2 root 1458: /* Generate the RTL code for entering a binding contour.
1459: The variables are declared one by one, by calls to `expand_decl'.
1.1 root 1460:
1.1.1.2 root 1461: EXIT_FLAG is nonzero if this construct should be visible to
1462: `exit_something'. */
1463:
1464: void
1465: expand_start_bindings (exit_flag)
1466: int exit_flag;
1.1 root 1467: {
1.1.1.2 root 1468: struct nesting *thisblock
1469: = (struct nesting *) xmalloc (sizeof (struct nesting));
1470:
1471: rtx note = emit_note (0, NOTE_INSN_BLOCK_BEG);
1472:
1473: /* Make an entry on block_stack for the block we are entering. */
1474:
1475: thisblock->next = block_stack;
1476: thisblock->all = nesting_stack;
1477: thisblock->depth = ++nesting_depth;
1478: thisblock->data.block.stack_level = 0;
1.1.1.7 root 1479: thisblock->data.block.cleanups = 0;
1.1.1.13! root 1480: /* We build this even if the cleanups lists are empty
! 1481: because we rely on having an element in the chain
! 1482: for each block that is pending. */
! 1483: thisblock->data.block.outer_cleanups
! 1484: = (block_stack
! 1485: ? tree_cons (NULL_TREE, block_stack->data.block.cleanups,
! 1486: block_stack->data.block.outer_cleanups)
! 1487: : 0);
1.1.1.2 root 1488: thisblock->data.block.label_chain = 0;
1489: thisblock->data.block.innermost_stack_block = stack_block_stack;
1490: thisblock->data.block.first_insn = note;
1491: thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
1492: block_stack = thisblock;
1493: nesting_stack = thisblock;
1494: }
1495:
1.1.1.3 root 1496: /* Output a USE for any register use in RTL.
1497: This is used with -noreg to mark the extent of lifespan
1498: of any registers used in a user-visible variable's DECL_RTL. */
1499:
1.1.1.13! root 1500: void
1.1.1.3 root 1501: use_variable (rtl)
1502: rtx rtl;
1503: {
1504: if (GET_CODE (rtl) == REG)
1505: /* This is a register variable. */
1506: emit_insn (gen_rtx (USE, VOIDmode, rtl));
1507: else if (GET_CODE (rtl) == MEM
1508: && GET_CODE (XEXP (rtl, 0)) == REG
1509: && XEXP (rtl, 0) != frame_pointer_rtx
1510: && XEXP (rtl, 0) != arg_pointer_rtx)
1511: /* This is a variable-sized structure. */
1512: emit_insn (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)));
1513: }
1514:
1.1.1.13! root 1515: /* Like use_variable except that it outputs the USEs after INSN
! 1516: instead of at the end of the insn-chain. */
! 1517:
! 1518: static void
! 1519: use_variable_after (rtl, insn)
! 1520: rtx rtl, insn;
! 1521: {
! 1522: if (GET_CODE (rtl) == REG)
! 1523: /* This is a register variable. */
! 1524: emit_insn_after (gen_rtx (USE, VOIDmode, rtl), insn);
! 1525: else if (GET_CODE (rtl) == MEM
! 1526: && GET_CODE (XEXP (rtl, 0)) == REG
! 1527: && XEXP (rtl, 0) != frame_pointer_rtx
! 1528: && XEXP (rtl, 0) != arg_pointer_rtx)
! 1529: /* This is a variable-sized structure. */
! 1530: emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)), insn);
! 1531: }
! 1532:
1.1.1.2 root 1533: /* Generate RTL code to terminate a binding contour.
1534: VARS is the chain of VAR_DECL nodes
1535: for the variables bound in this contour.
1.1.1.7 root 1536: MARK_ENDS is nonzero if we should put a note at the beginning
1537: and end of this binding contour.
1538:
1539: DONT_JUMP_IN is nonzero if it is not valid to jump into this contour.
1540: (That is true automatically if the contour has a saved stack level.) */
1.1.1.2 root 1541:
1542: void
1.1.1.7 root 1543: expand_end_bindings (vars, mark_ends, dont_jump_in)
1.1.1.2 root 1544: tree vars;
1545: int mark_ends;
1.1.1.7 root 1546: int dont_jump_in;
1.1.1.2 root 1547: {
1548: register struct nesting *thisblock = block_stack;
1549: register tree decl;
1550:
1.1.1.10 root 1551: if (warn_unused)
1552: for (decl = vars; decl; decl = TREE_CHAIN (decl))
1553: if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL)
1554: warning_with_decl (decl, "unused variable `%s'");
1555:
1.1.1.2 root 1556: /* Mark the beginning and end of the scope if requested. */
1557:
1558: if (mark_ends)
1559: emit_note (0, NOTE_INSN_BLOCK_END);
1560: else
1561: /* Get rid of the beginning-mark if we don't make an end-mark. */
1562: NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
1563:
1564: if (thisblock->exit_label)
1565: {
1566: do_pending_stack_adjust ();
1567: emit_label (thisblock->exit_label);
1568: }
1569:
1.1.1.13! root 1570: if (dont_jump_in
! 1571: || thisblock->data.block.stack_level != 0
! 1572: || thisblock->data.block.cleanups != 0)
1.1.1.2 root 1573: {
1574: struct label_chain *chain;
1575:
1576: /* Any labels in this block are no longer valid to go to.
1577: Mark them to cause an error message. */
1578: for (chain = thisblock->data.block.label_chain; chain; chain = chain->next)
1579: {
1580: TREE_PACKED (chain->label) = 1;
1581: /* If any goto without a fixup came to this label,
1582: that must be an error, because gotos without fixups
1.1.1.13! root 1583: come from outside all saved stack-levels and all cleanups. */
1.1.1.2 root 1584: if (TREE_ADDRESSABLE (chain->label))
1.1.1.13! root 1585: error_with_decl (chain->label,
! 1586: "label `%s' used before containing binding contour");
1.1.1.2 root 1587: }
1.1.1.7 root 1588: }
1589:
1590: /* Restore stack level in effect before the block
1591: (only if variable-size objects allocated). */
1592:
1593: if (thisblock->data.block.stack_level != 0
1594: || thisblock->data.block.cleanups != 0)
1595: {
1596: /* Perform any cleanups associated with the block. */
1597:
1598: expand_cleanups (thisblock->data.block.cleanups, 0);
1599:
1600: /* Restore the stack level. */
1601:
1602: if (thisblock->data.block.stack_level != 0)
1603: {
1604: do_pending_stack_adjust ();
1605: emit_move_insn (stack_pointer_rtx,
1606: thisblock->data.block.stack_level);
1607: }
1.1.1.2 root 1608:
1.1.1.7 root 1609: /* Any gotos out of this block must also do these things.
1.1.1.2 root 1610: Also report any gotos with fixups that came to labels in this level. */
1.1.1.13! root 1611: fixup_gotos (thisblock,
! 1612: thisblock->data.block.stack_level,
1.1.1.7 root 1613: thisblock->data.block.cleanups,
1614: thisblock->data.block.first_insn,
1615: dont_jump_in);
1.1.1.2 root 1616: }
1617:
1618: /* If doing stupid register allocation, make sure lives of all
1619: register variables declared here extend thru end of scope. */
1620:
1621: if (obey_regdecls)
1622: for (decl = vars; decl; decl = TREE_CHAIN (decl))
1623: {
1.1.1.3 root 1624: rtx rtl = DECL_RTL (decl);
1625: if (TREE_CODE (decl) == VAR_DECL && rtl != 0)
1626: use_variable (rtl);
1.1.1.2 root 1627: }
1628:
1629: /* Restore block_stack level for containing block. */
1630:
1631: stack_block_stack = thisblock->data.block.innermost_stack_block;
1632: POPSTACK (block_stack);
1633: }
1634:
1635: /* Generate RTL for the automatic variable declaration DECL.
1.1.1.7 root 1636: (Other kinds of declarations are simply ignored if seen here.)
1637: CLEANUP is an expression to be executed at exit from this binding contour;
1638: for example, in C++, it might call the destructor for this variable.
1639:
1640: If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
1641: either before or after calling `expand_decl' but before compiling
1642: any subsequent expressions. This is because CLEANUP may be expanded
1643: more than once, on different branches of execution.
1644: For the same reason, CLEANUP may not contain a CALL_EXPR
1645: except as its topmost node--else `preexpand_calls' would get confused.
1646:
1.1.1.13! root 1647: If CLEANUP is nonzero and DECL is zero, we record a cleanup
! 1648: that is not associated with any particular variable.
! 1649:
1.1.1.7 root 1650: There is no special support here for C++ constructors.
1651: They should be handled by the proper code in DECL_INITIAL. */
1.1.1.2 root 1652:
1653: void
1.1.1.7 root 1654: expand_decl (decl, cleanup)
1.1.1.2 root 1655: register tree decl;
1.1.1.7 root 1656: tree cleanup;
1.1.1.2 root 1657: {
1658: struct nesting *thisblock = block_stack;
1.1.1.13! root 1659: tree type;
! 1660:
! 1661: /* Record the cleanup if there is one. */
! 1662:
! 1663: if (cleanup != 0)
! 1664: {
! 1665: thisblock->data.block.cleanups
! 1666: = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
! 1667: /* If this block has a cleanup, it belongs in stack_block_stack. */
! 1668: stack_block_stack = thisblock;
! 1669: }
! 1670:
! 1671: if (decl == NULL_TREE)
! 1672: {
! 1673: /* This was a cleanup with no variable. */
! 1674: if (cleanup == 0)
! 1675: abort ();
! 1676: return;
! 1677: }
! 1678:
! 1679: type = TREE_TYPE (decl);
1.1.1.2 root 1680:
1681: /* External function declarations are supposed to have been
1682: handled in assemble_variable. Verify this. */
1.1.1.7 root 1683:
1.1.1.2 root 1684: if (TREE_CODE (decl) == FUNCTION_DECL)
1685: {
1686: if (DECL_RTL (decl) == 0)
1687: abort ();
1688: return;
1689: }
1690:
1691: /* Aside from that, only automatic variables need any expansion done.
1692: Static and external variables were handled by `assemble_variable'
1693: (called from finish_decl). TYPE_DECL and CONST_DECL require nothing;
1694: PARM_DECLs are handled in `assign_parms'. */
1695:
1696: if (TREE_CODE (decl) != VAR_DECL)
1697: return;
1698: if (TREE_STATIC (decl) || TREE_EXTERNAL (decl))
1699: return;
1700:
1701: /* Create the RTL representation for the variable. */
1702:
1703: if (type == error_mark_node)
1704: DECL_RTL (decl) = gen_rtx (MEM, BLKmode, const0_rtx);
1705: else if (DECL_MODE (decl) != BLKmode
1706: /* If -ffloat-store, don't put explicit float vars
1707: into regs. */
1708: && !(flag_float_store
1709: && TREE_CODE (type) == REAL_TYPE)
1710: && ! TREE_VOLATILE (decl)
1711: && ! TREE_ADDRESSABLE (decl)
1712: && (TREE_REGDECL (decl) || ! obey_regdecls))
1713: {
1714: /* Automatic variable that can go in a register. */
1715: DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
1716: if (TREE_CODE (type) == POINTER_TYPE)
1717: mark_reg_pointer (DECL_RTL (decl));
1.1.1.10 root 1718: REG_USERVAR_P (DECL_RTL (decl)) = 1;
1.1.1.2 root 1719: }
1720: else if (DECL_SIZE (decl) == 0)
1721: /* Variable with incomplete type. */
1722: /* Error message was already done; now avoid a crash. */
1723: DECL_RTL (decl) = assign_stack_local (DECL_MODE (decl), 0);
1724: else if (TREE_LITERAL (DECL_SIZE (decl)))
1725: {
1726: /* Variable of fixed size that goes on the stack. */
1727: DECL_RTL (decl)
1728: = assign_stack_local (DECL_MODE (decl),
1729: (TREE_INT_CST_LOW (DECL_SIZE (decl))
1730: * DECL_SIZE_UNIT (decl)
1731: + BITS_PER_UNIT - 1)
1732: / BITS_PER_UNIT);
1733: /* If this is a memory ref that contains aggregate components,
1734: mark it as such for cse and loop optimize. */
1.1.1.10 root 1735: MEM_IN_STRUCT_P (DECL_RTL (decl))
1.1.1.2 root 1736: = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1737: || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
1738: || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
1.1.1.8 root 1739: #if 0
1740: /* If this is in memory because of -ffloat-store,
1741: set the volatile bit, to prevent optimizations from
1742: undoing the effects. */
1743: if (flag_float_store && TREE_CODE (type) == REAL_TYPE)
1.1.1.10 root 1744: MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
1.1.1.8 root 1745: #endif
1.1.1.2 root 1746: }
1747: else
1748: /* Dynamic-size object: must push space on the stack. */
1749: {
1750: rtx address, size;
1751:
1752: frame_pointer_needed = 1;
1753:
1754: /* Record the stack pointer on entry to block, if have
1755: not already done so. */
1756: if (thisblock->data.block.stack_level == 0)
1757: {
1758: do_pending_stack_adjust ();
1759: thisblock->data.block.stack_level
1760: = copy_to_reg (stack_pointer_rtx);
1761: stack_block_stack = thisblock;
1762: }
1763:
1764: /* Compute the variable's size, in bytes. */
1765: size = expand_expr (convert_units (DECL_SIZE (decl),
1766: DECL_SIZE_UNIT (decl),
1767: BITS_PER_UNIT),
1768: 0, VOIDmode, 0);
1769:
1770: /* Round it up to this machine's required stack boundary. */
1771: #ifdef STACK_BOUNDARY
1772: /* Avoid extra code if we can prove it's a multiple already. */
1773: if (DECL_SIZE_UNIT (decl) % STACK_BOUNDARY)
1774: size = round_push (size);
1775: #endif
1776:
1777: /* Make space on the stack, and get an rtx for the address of it. */
1778: #ifdef STACK_GROWS_DOWNWARD
1779: anti_adjust_stack (size);
1780: #endif
1781: address = copy_to_reg (stack_pointer_rtx);
1.1.1.4 root 1782: #ifdef STACK_POINTER_OFFSET
1783: /* If the contents of the stack pointer reg are offset from the
1784: actual top-of-stack address, add the offset here. */
1785: emit_insn (gen_add2_insn (address, gen_rtx (CONST_INT, VOIDmode,
1786: STACK_POINTER_OFFSET)));
1787: #endif
1.1.1.2 root 1788: #ifndef STACK_GROWS_DOWNWARD
1789: anti_adjust_stack (size);
1790: #endif
1791:
1792: /* Reference the variable indirect through that rtx. */
1793: DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address);
1794: }
1795:
1796: if (TREE_VOLATILE (decl))
1.1.1.10 root 1797: MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
1.1.1.2 root 1798: if (TREE_READONLY (decl))
1.1.1.10 root 1799: RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
1.1.1.2 root 1800:
1801: /* If doing stupid register allocation, make sure life of any
1802: register variable starts here, at the start of its scope. */
1803:
1804: if (obey_regdecls
1805: && TREE_CODE (decl) == VAR_DECL
1.1.1.3 root 1806: && DECL_RTL (decl) != 0)
1807: use_variable (DECL_RTL (decl));
1.1.1.2 root 1808:
1809: /* Compute and store the initial value now. */
1810:
1.1.1.3 root 1811: if (DECL_INITIAL (decl) == error_mark_node)
1812: {
1813: enum tree_code code = TREE_CODE (TREE_TYPE (decl));
1814: if (code == INTEGER_TYPE || code == REAL_TYPE || code == ENUMERAL_TYPE
1815: || code == POINTER_TYPE)
1816: expand_assignment (decl, convert (TREE_TYPE (decl), integer_zero_node),
1817: 0, 0);
1818: emit_queue ();
1819: }
1.1.1.7 root 1820: else if (DECL_INITIAL (decl) && TREE_CODE (DECL_INITIAL (decl)) != TREE_LIST)
1.1.1.2 root 1821: {
1.1.1.12 root 1822: emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1.1.1.2 root 1823: expand_assignment (decl, DECL_INITIAL (decl), 0, 0);
1824: emit_queue ();
1825: }
1826: }
1.1.1.13! root 1827:
! 1828: /* DECL is an anonymous union. CLEANUP is a cleanup for DECL.
! 1829: DECL_ELTS is the list of elements that belong to DECL's type.
! 1830: In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup. */
! 1831:
! 1832: void
! 1833: expand_anon_union_decl (decl, cleanup, decl_elts)
! 1834: tree decl, cleanup, decl_elts;
! 1835: {
! 1836: struct nesting *thisblock = block_stack;
! 1837: rtx x;
! 1838:
! 1839: expand_decl (decl, cleanup);
! 1840: x = DECL_RTL (decl);
! 1841:
! 1842: while (decl_elts)
! 1843: {
! 1844: tree decl_elt = TREE_VALUE (decl_elts);
! 1845: tree cleanup_elt = TREE_PURPOSE (decl_elts);
! 1846:
! 1847: DECL_RTL (decl_elt)
! 1848: = (GET_MODE (x) != BLKmode
! 1849: /*
! 1850: #error broken
! 1851: /* ??? This is incorrect if X is a MEM.
! 1852: (SUBREG (MEM)) is not allowed at rtl generation time. */
! 1853: ? gen_rtx (SUBREG, TYPE_MODE (TREE_TYPE (decl_elt)), x, 0)
! 1854: : x);
! 1855:
! 1856: /* Record the cleanup if there is one. */
! 1857:
! 1858: if (cleanup != 0)
! 1859: thisblock->data.block.cleanups
! 1860: = temp_tree_cons (decl_elt, cleanup_elt,
! 1861: thisblock->data.block.cleanups);
! 1862:
! 1863: decl_elts = TREE_CHAIN (decl_elts);
! 1864: }
! 1865: }
1.1.1.2 root 1866:
1.1.1.7 root 1867: /* Expand a list of cleanups LIST.
1868: Elements may be expressions or may be nested lists.
1869:
1870: If DONT_DO is nonnull, then any list-element
1871: whose TREE_PURPOSE matches DONT_DO is omitted.
1872: This is sometimes used to avoid a cleanup associated with
1873: a value that is being returned out of the scope. */
1874:
1875: static void
1876: expand_cleanups (list, dont_do)
1877: tree list;
1878: tree dont_do;
1879: {
1880: tree tail;
1881: for (tail = list; tail; tail = TREE_CHAIN (tail))
1882: if (dont_do == 0 || TREE_PURPOSE (tail) != dont_do)
1883: {
1884: if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
1.1.1.8 root 1885: expand_cleanups (TREE_VALUE (tail), dont_do);
1.1.1.7 root 1886: else
1887: expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
1888: }
1889: }
1890:
1891: /* Expand a list of cleanups for a goto fixup.
1892: The expansion is put into the insn chain after the insn *BEFORE_JUMP
1893: and *BEFORE_JUMP is set to the insn that now comes before the jump. */
1894:
1895: static void
1896: fixup_cleanups (list, before_jump)
1897: tree list;
1898: rtx *before_jump;
1899: {
1900: rtx beyond_jump = get_last_insn ();
1901: rtx new_before_jump;
1902:
1903: expand_cleanups (list, 0);
1904: new_before_jump = get_last_insn ();
1905:
1906: reorder_insns (NEXT_INSN (beyond_jump), new_before_jump, *before_jump);
1907: *before_jump = new_before_jump;
1908: }
1.1.1.8 root 1909:
1910: /* Move all cleanups from the current block_stack
1911: to the containing block_stack, where they are assumed to
1912: have been created. If anything can cause a temporary to
1913: be created, but not expanded for more than one level of
1914: block_stacks, then this code will have to change. */
1915:
1916: void
1917: move_cleanups_up ()
1918: {
1919: struct nesting *block = block_stack;
1920: struct nesting *outer = block->next;
1921:
1922: outer->data.block.cleanups
1.1.1.13! root 1923: = chainon (block->data.block.cleanups,
! 1924: outer->data.block.cleanups);
1.1.1.8 root 1925: block->data.block.cleanups = 0;
1926: }
1.1.1.7 root 1927:
1.1.1.2 root 1928: /* Enter a case (Pascal) or switch (C) statement.
1929: Push a block onto case_stack and nesting_stack
1930: to accumulate the case-labels that are seen
1931: and to record the labels generated for the statement.
1932:
1933: EXIT_FLAG is nonzero if `exit_something' should exit this case stmt.
1934: Otherwise, this construct is transparent for `exit_something'.
1935:
1936: EXPR is the index-expression to be dispatched on.
1937: TYPE is its nominal type. We could simply convert EXPR to this type,
1938: but instead we take short cuts. */
1939:
1940: void
1941: expand_start_case (exit_flag, expr, type)
1942: int exit_flag;
1943: tree expr;
1944: tree type;
1945: {
1946: register struct nesting *thiscase
1947: = (struct nesting *) xmalloc (sizeof (struct nesting));
1948:
1949: /* Make an entry on case_stack for the case we are entering. */
1950:
1951: thiscase->next = case_stack;
1952: thiscase->all = nesting_stack;
1953: thiscase->depth = ++nesting_depth;
1954: thiscase->exit_label = exit_flag ? gen_label_rtx () : 0;
1955: thiscase->data.case_stmt.case_list = 0;
1956: thiscase->data.case_stmt.index_expr = expr;
1957: thiscase->data.case_stmt.nominal_type = type;
1.1.1.13! root 1958: thiscase->data.case_stmt.default_label = 0;
! 1959: thiscase->data.case_stmt.num_ranges = 0;
1.1.1.2 root 1960: case_stack = thiscase;
1961: nesting_stack = thiscase;
1962:
1963: do_pending_stack_adjust ();
1964:
1.1.1.6 root 1965: /* Make sure case_stmt.start points to something that won't
1966: need any transformation before expand_end_case. */
1967: if (GET_CODE (get_last_insn ()) != NOTE)
1968: emit_note (0, NOTE_INSN_DELETED);
1969:
1.1.1.2 root 1970: thiscase->data.case_stmt.start = get_last_insn ();
1971: }
1972:
1973: /* Start a "dummy case statement" within which case labels are invalid
1974: and are not connected to any larger real case statement.
1975: This can be used if you don't want to let a case statement jump
1976: into the middle of certain kinds of constructs. */
1977:
1978: void
1979: expand_start_case_dummy ()
1980: {
1981: register struct nesting *thiscase
1982: = (struct nesting *) xmalloc (sizeof (struct nesting));
1983:
1984: /* Make an entry on case_stack for the dummy. */
1985:
1986: thiscase->next = case_stack;
1987: thiscase->all = nesting_stack;
1988: thiscase->depth = ++nesting_depth;
1989: thiscase->exit_label = 0;
1990: thiscase->data.case_stmt.case_list = 0;
1991: thiscase->data.case_stmt.start = 0;
1992: thiscase->data.case_stmt.nominal_type = 0;
1.1.1.13! root 1993: thiscase->data.case_stmt.default_label = 0;
! 1994: thiscase->data.case_stmt.num_ranges = 0;
1.1.1.2 root 1995: case_stack = thiscase;
1996: nesting_stack = thiscase;
1997: }
1998:
1999: /* End a dummy case statement. */
2000:
2001: void
2002: expand_end_case_dummy ()
2003: {
2004: POPSTACK (case_stack);
2005: }
1.1.1.7 root 2006:
1.1.1.2 root 2007: /* Accumulate one case or default label inside a case or switch statement.
2008: VALUE is the value of the case (a null pointer, for a default label).
2009:
2010: If not currently inside a case or switch statement, return 1 and do
2011: nothing. The caller will print a language-specific error message.
1.1.1.7 root 2012: If VALUE is a duplicate or overlaps, return 2 and do nothing.
1.1.1.2 root 2013: If VALUE is out of range, return 3 and do nothing.
1.1.1.13! root 2014: Return 0 on success.
! 2015:
! 2016: Extended to handle range statements, should they ever
! 2017: be adopted. */
1.1.1.2 root 2018:
2019: int
2020: pushcase (value, label)
2021: register tree value;
2022: register tree label;
2023: {
1.1.1.13! root 2024: register struct case_node **l;
! 2025: register struct case_node *n;
1.1.1.2 root 2026: tree index_type;
2027: tree nominal_type;
2028:
2029: /* Fail if not inside a real case statement. */
2030: if (! (case_stack && case_stack->data.case_stmt.start))
2031: return 1;
2032:
2033: index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
2034: nominal_type = case_stack->data.case_stmt.nominal_type;
2035:
2036: /* If the index is erroneous, avoid more problems: pretend to succeed. */
2037: if (index_type == error_mark_node)
2038: return 0;
2039:
2040: /* Convert VALUE to the type in which the comparisons are nominally done. */
2041: if (value != 0)
2042: value = convert (nominal_type, value);
2043:
1.1.1.7 root 2044: /* Fail if this value is out of range for the actual type of the index
2045: (which may be narrower than NOMINAL_TYPE). */
2046: if (value != 0 && ! int_fits_type_p (value, index_type))
2047: return 3;
2048:
2049: /* Fail if this is a duplicate or overlaps another entry. */
2050: if (value == 0)
1.1.1.2 root 2051: {
1.1.1.13! root 2052: if (case_stack->data.case_stmt.default_label != 0)
1.1.1.2 root 2053: return 2;
1.1.1.13! root 2054: case_stack->data.case_stmt.default_label = label;
1.1.1.2 root 2055: }
1.1.1.7 root 2056: else
2057: {
1.1.1.13! root 2058: /* Find the elt in the chain before which to insert the new value,
! 2059: to keep the chain sorted in increasing order.
! 2060: But report an error if this element is a duplicate. */
! 2061: for (l = &case_stack->data.case_stmt.case_list;
! 2062: /* Keep going past elements distinctly less than VALUE. */
! 2063: *l != 0 && !tree_int_cst_lt (value, (*l)->high);
! 2064: l = &(*l)->right)
! 2065: ;
! 2066: if (*l)
1.1.1.7 root 2067: {
1.1.1.13! root 2068: /* Element we will insert before must be distinctly greater;
! 2069: overlap means error. */
! 2070: if (! tree_int_cst_lt (value, (*l)->low))
! 2071: return 2;
1.1.1.7 root 2072: }
1.1.1.13! root 2073:
! 2074: /* Add this label to the chain, and succeed.
! 2075: Copy VALUE so it is on temporary rather than momentary
! 2076: obstack and will thus survive till the end of the case statement. */
! 2077: n = (struct case_node *) oballoc (sizeof (struct case_node));
! 2078: n->left = 0;
! 2079: n->right = *l;
! 2080: n->high = n->low = copy_node (value);
! 2081: n->code_label = label;
! 2082: n->test_label = 0;
! 2083: *l = n;
1.1.1.7 root 2084: }
2085:
2086: expand_label (label);
2087: return 0;
2088: }
2089:
2090: /* Like pushcase but this case applies to all values
2091: between VALUE1 and VALUE2 (inclusive).
2092: The return value is the same as that of pushcase
2093: but there is one additional error code:
2094: 4 means the specified range was empty.
2095:
2096: Note that this does not currently work, since expand_end_case
2097: has yet to be extended to handle RANGE_EXPRs. */
2098:
2099: int
2100: pushcase_range (value1, value2, label)
2101: register tree value1, value2;
2102: register tree label;
2103: {
1.1.1.13! root 2104: register struct case_node **l;
! 2105: register struct case_node *n;
1.1.1.7 root 2106: tree index_type;
2107: tree nominal_type;
2108: tree value;
2109:
2110: /* Fail if not inside a real case statement. */
2111: if (! (case_stack && case_stack->data.case_stmt.start))
2112: return 1;
2113:
2114: index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
2115: nominal_type = case_stack->data.case_stmt.nominal_type;
2116:
2117: /* If the index is erroneous, avoid more problems: pretend to succeed. */
2118: if (index_type == error_mark_node)
2119: return 0;
2120:
2121: /* Convert VALUEs to type in which the comparisons are nominally done. */
2122: if (value1 != 0)
2123: value1 = convert (nominal_type, value1);
2124: if (value2 != 0)
2125: value2 = convert (nominal_type, value2);
2126:
2127: /* Fail if these values are out of range. */
2128: if (value1 != 0 && ! int_fits_type_p (value1, index_type))
2129: return 3;
2130:
2131: if (value2 != 0 && ! int_fits_type_p (value2, index_type))
1.1.1.2 root 2132: return 3;
2133:
1.1.1.7 root 2134: /* Fail if the range is empty. */
2135: if (tree_int_cst_lt (value2, value1))
2136: return 4;
2137:
1.1.1.8 root 2138: /* If the bounds are equal, turn this into the one-value case. */
2139: if (tree_int_cst_equal (value1, value2))
2140: return pushcase (value1, label);
2141:
1.1.1.13! root 2142: /* Find the elt in the chain before which to insert the new value,
! 2143: to keep the chain sorted in increasing order.
! 2144: But report an error if this element is a duplicate. */
! 2145: for (l = &case_stack->data.case_stmt.case_list;
! 2146: /* Keep going past elements distinctly less than this range. */
! 2147: *l != 0 && !tree_int_cst_lt (value1, (*l)->high);
! 2148: l = &(*l)->right)
! 2149: ;
! 2150: if (*l)
! 2151: {
! 2152: /* Element we will insert before must be distinctly greater;
! 2153: overlap means error. */
! 2154: if (! tree_int_cst_lt (value2, (*l)->low))
! 2155: return 2;
1.1.1.7 root 2156: }
2157:
1.1.1.13! root 2158: /* Add this label to the chain, and succeed.
! 2159: Copy VALUE1, VALUE2 so they are on temporary rather than momentary
! 2160: obstack and will thus survive till the end of the case statement. */
! 2161:
! 2162: n = (struct case_node *) oballoc (sizeof (struct case_node));
! 2163: n->left = 0;
! 2164: n->right = *l;
! 2165: n->low = copy_node (value1);
! 2166: n->high = copy_node (value2);
! 2167: n->code_label = label;
! 2168: n->test_label = 0;
! 2169: *l = n;
! 2170:
1.1.1.2 root 2171: expand_label (label);
1.1.1.7 root 2172:
1.1.1.13! root 2173: case_stack->data.case_stmt.num_ranges++;
! 2174:
1.1.1.2 root 2175: return 0;
2176: }
2177:
2178: /* Terminate a case (Pascal) or switch (C) statement
2179: in which CASE_INDEX is the expression to be tested.
2180: Generate the code to test it and jump to the right place. */
2181:
2182: void
2183: expand_end_case ()
2184: {
2185: tree minval, maxval, range;
2186: rtx default_label = 0;
1.1.1.13! root 2187: register struct case_node *n;
1.1.1.2 root 2188: int count;
2189: rtx index;
2190: rtx table_label = gen_label_rtx ();
2191: int ncases;
2192: rtx *labelvec;
2193: register int i;
2194: rtx before_case;
2195: register struct nesting *thiscase = case_stack;
2196: tree index_expr = thiscase->data.case_stmt.index_expr;
2197:
2198: do_pending_stack_adjust ();
2199:
1.1.1.6 root 2200: /* An ERROR_MARK occurs for various reasons including invalid data type. */
2201: if (TREE_TYPE (index_expr) != error_mark_node)
1.1.1.2 root 2202: {
2203: /* If we don't have a default-label, create one here,
2204: after the body of the switch. */
1.1.1.13! root 2205: if (thiscase->data.case_stmt.default_label == 0)
! 2206: {
! 2207: thiscase->data.case_stmt.default_label
! 2208: = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
! 2209: expand_label (thiscase->data.case_stmt.default_label);
! 2210: }
! 2211: default_label = label_rtx (thiscase->data.case_stmt.default_label);
1.1.1.2 root 2212:
2213: before_case = get_last_insn ();
2214:
1.1.1.13! root 2215: /* Simplify the case-list before we count it. */
! 2216: group_case_nodes (thiscase->data.case_stmt.case_list);
! 2217:
1.1.1.2 root 2218: /* Get upper and lower bounds of case values.
2219: Also convert all the case values to the index expr's data type. */
2220:
1.1.1.13! root 2221: count = 0;
! 2222: for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
! 2223: {
! 2224: /* Check low and high label values are integers. */
! 2225: if (TREE_CODE (n->low) != INTEGER_CST)
! 2226: abort ();
! 2227: if (TREE_CODE (n->high) != INTEGER_CST)
! 2228: abort ();
! 2229:
! 2230: n->low = convert (TREE_TYPE (index_expr), n->low);
! 2231: n->high = convert (TREE_TYPE (index_expr), n->high);
! 2232:
! 2233: /* Count the elements and track the largest and smallest
! 2234: of them (treating them as signed even if they are not). */
! 2235: if (count++ == 0)
! 2236: {
! 2237: minval = n->low;
! 2238: maxval = n->high;
! 2239: }
! 2240: else
! 2241: {
! 2242: if (INT_CST_LT (n->low, minval))
! 2243: minval = n->low;
! 2244: if (INT_CST_LT (maxval, n->high))
! 2245: maxval = n->high;
! 2246: }
! 2247: /* A range counts double, since it requires two compares. */
! 2248: if (! tree_int_cst_equal (n->low, n->high))
! 2249: count++;
! 2250: }
1.1.1.2 root 2251:
2252: /* Compute span of values. */
2253: if (count != 0)
2254: range = combine (MINUS_EXPR, maxval, minval);
2255:
2256: if (count == 0 || TREE_CODE (TREE_TYPE (index_expr)) == ERROR_MARK)
2257: {
2258: expand_expr (index_expr, const0_rtx, VOIDmode, 0);
2259: emit_queue ();
2260: emit_jump (default_label);
2261: }
2262: /* If range of values is much bigger than number of values,
2263: make a sequence of conditional branches instead of a dispatch.
2264: If the switch-index is a constant, do it this way
2265: because we can optimize it. */
2266: else if (TREE_INT_CST_HIGH (range) != 0
1.1 root 2267: #ifdef HAVE_casesi
1.1.1.2 root 2268: || count < 4
1.1 root 2269: #else
1.1.1.2 root 2270: /* If machine does not have a case insn that compares the
2271: bounds, this means extra overhead for dispatch tables
2272: which raises the threshold for using them. */
2273: || count < 5
1.1 root 2274: #endif
1.1.1.2 root 2275: || (unsigned) (TREE_INT_CST_LOW (range)) > 10 * count
2276: || TREE_CODE (index_expr) == INTEGER_CST)
2277: {
2278: index = expand_expr (index_expr, 0, VOIDmode, 0);
2279: emit_queue ();
1.1 root 2280:
1.1.1.2 root 2281: index = protect_from_queue (index, 0);
2282: if (GET_CODE (index) == MEM)
2283: index = copy_to_reg (index);
1.1.1.13! root 2284: if (TREE_CODE (index_expr) == INTEGER_CST)
1.1.1.2 root 2285: {
1.1.1.13! root 2286: /* For constant index expressions we need only
! 2287: issue a unconditional branch to the appropriate
! 2288: target code. The job of removing any unreachable
! 2289: code is left to the optimisation phase if the
! 2290: "-O" option is specified. */
! 2291: for (n = thiscase->data.case_stmt.case_list;
! 2292: n;
! 2293: n = n->right)
! 2294: {
! 2295: if (! tree_int_cst_lt (index_expr, n->low)
! 2296: && ! tree_int_cst_lt (n->high, index_expr))
! 2297: break;
! 2298: }
! 2299: if (n)
! 2300: emit_jump (default_label);
! 2301: else
! 2302: emit_jump (label_rtx (n->code_label));
! 2303: }
! 2304: else
! 2305: {
! 2306: /* If the index expression is not constant we generate
! 2307: a binary decision tree to select the appropriate
! 2308: target code. This is done as follows:
! 2309:
! 2310: The list of cases is rearranged into a binary tree,
! 2311: nearly optimal assuming equal probability for each case.
! 2312:
! 2313: The tree is transformed into RTL, eliminating
! 2314: redundant test conditions at the same time.
! 2315:
! 2316: If program flow could reach the end of the
! 2317: decision tree an unconditional jump to the
! 2318: default code is emitted. */
! 2319: balance_case_nodes (&thiscase->data.case_stmt.case_list, 0);
! 2320: emit_case_nodes (index, thiscase->data.case_stmt.case_list,
! 2321: default_label);
! 2322: emit_jump_if_reachable (default_label);
1.1.1.2 root 2323: }
2324: }
2325: else
2326: {
1.1 root 2327: #ifdef HAVE_casesi
1.1.1.3 root 2328: /* Convert the index to SImode. */
1.1.1.2 root 2329: if (TYPE_MODE (TREE_TYPE (index_expr)) == DImode)
2330: {
1.1.1.3 root 2331: index_expr = build (MINUS_EXPR, TREE_TYPE (index_expr),
2332: index_expr, minval);
1.1.1.2 root 2333: minval = integer_zero_node;
2334: }
1.1.1.3 root 2335: if (TYPE_MODE (TREE_TYPE (index_expr)) != SImode)
2336: index_expr = convert (type_for_size (GET_MODE_BITSIZE (SImode), 0),
2337: index_expr);
1.1.1.2 root 2338: index = expand_expr (index_expr, 0, VOIDmode, 0);
2339: emit_queue ();
2340: index = protect_from_queue (index, 0);
2341: do_pending_stack_adjust ();
2342:
2343: emit_jump_insn (gen_casesi (index, expand_expr (minval, 0, VOIDmode, 0),
2344: expand_expr (range, 0, VOIDmode, 0),
2345: table_label, default_label));
1.1 root 2346: #else
2347: #ifdef HAVE_tablejump
1.1.1.3 root 2348: index_expr = convert (type_for_size (GET_MODE_BITSIZE (SImode), 0),
1.1.1.2 root 2349: build (MINUS_EXPR, TREE_TYPE (index_expr),
2350: index_expr, minval));
2351: index = expand_expr (index_expr, 0, VOIDmode, 0);
2352: emit_queue ();
2353: index = protect_from_queue (index, 0);
2354: do_pending_stack_adjust ();
2355:
2356: do_tablejump (index,
2357: gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (range)),
2358: table_label, default_label);
1.1 root 2359: #else
1.1.1.2 root 2360: lossage;
2361: #endif /* not HAVE_tablejump */
2362: #endif /* not HAVE_casesi */
2363:
2364: /* Get table of labels to jump to, in order of case index. */
2365:
2366: ncases = TREE_INT_CST_LOW (range) + 1;
2367: labelvec = (rtx *) alloca (ncases * sizeof (rtx));
2368: bzero (labelvec, ncases * sizeof (rtx));
1.1 root 2369:
1.1.1.13! root 2370: for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
! 2371: {
! 2372: register int i
! 2373: = TREE_INT_CST_LOW (n->low) - TREE_INT_CST_LOW (minval);
! 2374:
! 2375: while (i + TREE_INT_CST_LOW (minval)
! 2376: <= TREE_INT_CST_LOW (n->high))
! 2377: labelvec[i++]
! 2378: = gen_rtx (LABEL_REF, Pmode, label_rtx (n->code_label));
! 2379: }
1.1.1.2 root 2380:
2381: /* Fill in the gaps with the default. */
2382: for (i = 0; i < ncases; i++)
2383: if (labelvec[i] == 0)
2384: labelvec[i] = gen_rtx (LABEL_REF, Pmode, default_label);
2385:
2386: /* Output the table */
2387: emit_label (table_label);
1.1 root 2388:
2389: #ifdef CASE_VECTOR_PC_RELATIVE
1.1.1.2 root 2390: emit_jump_insn (gen_rtx (ADDR_DIFF_VEC, CASE_VECTOR_MODE,
2391: gen_rtx (LABEL_REF, Pmode, table_label),
2392: gen_rtvec_v (ncases, labelvec)));
1.1 root 2393: #else
1.1.1.2 root 2394: emit_jump_insn (gen_rtx (ADDR_VEC, CASE_VECTOR_MODE,
2395: gen_rtvec_v (ncases, labelvec)));
1.1 root 2396: #endif
1.1.1.2 root 2397: /* If the case insn drops through the table,
2398: after the table we must jump to the default-label.
2399: Otherwise record no drop-through after the table. */
2400: #ifdef CASE_DROPS_THROUGH
2401: emit_jump (default_label);
2402: #else
2403: emit_barrier ();
2404: #endif
2405: }
2406:
2407: reorder_insns (NEXT_INSN (before_case), get_last_insn (),
2408: thiscase->data.case_stmt.start);
2409: }
2410: if (thiscase->exit_label)
2411: emit_label (thiscase->exit_label);
2412:
2413: POPSTACK (case_stack);
2414: }
2415:
2416: /* Generate code to jump to LABEL if OP1 and OP2 are equal. */
2417: /* ??? This may need an UNSIGNEDP argument to work properly ??? */
2418:
2419: void
2420: do_jump_if_equal (op1, op2, label)
2421: rtx op1, op2, label;
2422: {
2423: if (GET_CODE (op1) == CONST_INT
2424: && GET_CODE (op2) == CONST_INT)
2425: {
2426: if (INTVAL (op1) == INTVAL (op2))
2427: emit_jump (label);
2428: }
2429: else
2430: {
2431: emit_cmp_insn (op1, op2, 0, 0);
2432: emit_jump_insn (gen_beq (label));
2433: }
1.1 root 2434: }
2435:
1.1.1.13! root 2436: /* Scan an ordered list of case nodes
! 2437: combining those with consecutive values or ranges.
! 2438:
! 2439: Eg. three separate entries 1: 2: 3: become one entry 1..3: */
! 2440:
! 2441: static void
! 2442: group_case_nodes (head)
! 2443: case_node_ptr head;
! 2444: {
! 2445: case_node_ptr node = head;
! 2446:
! 2447: while (node)
! 2448: {
! 2449: rtx lb = next_real_insn (label_rtx (node->code_label));
! 2450: case_node_ptr np = node;
! 2451:
! 2452: /* Try to group the successors of NODE with NODE. */
! 2453: while (((np = np->right) != 0)
! 2454: /* Do they jump to the same place? */
! 2455: && next_real_insn (label_rtx (np->code_label)) == lb
! 2456: /* Are their ranges consecutive? */
! 2457: && tree_int_cst_equal (np->low,
! 2458: combine (PLUS_EXPR, node->high,
! 2459: build_int_2 (1, 0))))
! 2460: {
! 2461: node->high = np->high;
! 2462: }
! 2463: /* NP is the first node after NODE which can't be grouped with it.
! 2464: Delete the nodes in between, and move on to that node. */
! 2465: node->right = np;
! 2466: node = np;
! 2467: }
! 2468: }
! 2469:
! 2470: /* Take an ordered list of case nodes
! 2471: and transform them into a near optimal binary tree,
! 2472: on the assumtion that any target code selection value is as
! 2473: likely as any other.
! 2474:
! 2475: The transformation is performed by splitting the ordered
! 2476: list into two equal sections plus a pivot. The parts are
! 2477: then attached to the pivot as left and right branches. Each
! 2478: branch is is then transformed recursively. */
! 2479:
! 2480: static void
! 2481: balance_case_nodes (head, parent)
! 2482: case_node_ptr *head;
! 2483: case_node_ptr parent;
! 2484: {
! 2485: register case_node_ptr np;
! 2486:
! 2487: np = *head;
! 2488: if (np)
! 2489: {
! 2490: int i = 0;
! 2491: int ranges = 0;
! 2492: register case_node_ptr *npp;
! 2493: case_node_ptr left;
! 2494:
! 2495: /* Count the number of entries on branch.
! 2496: Also count the ranges. */
! 2497: while (np)
! 2498: {
! 2499: if (!tree_int_cst_equal (np->low, np->high))
! 2500: ranges++;
! 2501: i++;
! 2502: np = np->right;
! 2503: }
! 2504: if (i > 2)
! 2505: {
! 2506: /* Split this list if it is long enough for that to help. */
! 2507: npp = head;
! 2508: left = *npp;
! 2509: /* If there are just three nodes, split at the middle one. */
! 2510: if (i == 3)
! 2511: npp = &(*npp)->right;
! 2512: else
! 2513: {
! 2514: /* Find the place in the list that bisects the list's total cost,
! 2515: where ranges count as 2.
! 2516: Here I gets half the total cost. */
! 2517: i = (i + ranges + 1) / 2;
! 2518: while (1)
! 2519: {
! 2520: /* Skip nodes while their cost does not reach that amount. */
! 2521: if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
! 2522: i--;
! 2523: i--;
! 2524: if (i <= 0)
! 2525: break;
! 2526: npp = &(*npp)->right;
! 2527: }
! 2528: }
! 2529: *head = np = *npp;
! 2530: *npp = 0;
! 2531: np->parent = parent;
! 2532: np->left = left;
! 2533:
! 2534: /* Optimize each of the two split parts. */
! 2535: balance_case_nodes (&np->left, np);
! 2536: balance_case_nodes (&np->right, np);
! 2537: }
! 2538: else
! 2539: {
! 2540: /* Else leave this branch as one level,
! 2541: but fill in `parent' fields. */
! 2542: np = *head;
! 2543: np->parent = parent;
! 2544: for (; np->right; np = np->right)
! 2545: np->right->parent = np;
! 2546: }
! 2547: }
! 2548: }
! 2549:
! 2550: /* Search the parent sections of the case node tree
! 2551: to see if a test for the lower bound of NODE would be redundant.
! 2552:
! 2553: The instructions to synthesis the case decision tree are
! 2554: output in the same order as nodes are processed so it is
! 2555: known that if a parent node checks the range of the current
! 2556: node minus one that the current node is bounded at its lower
! 2557: span. Thus the test would be redundant. */
! 2558:
! 2559: static int
! 2560: node_has_low_bound (node)
! 2561: case_node_ptr node;
! 2562: {
! 2563: tree low_minus_one;
! 2564: case_node_ptr pnode;
! 2565:
! 2566: if (node->left)
! 2567: {
! 2568: low_minus_one = combine (MINUS_EXPR, node->low, build_int_2 (1, 0));
! 2569: for (pnode = node->parent; pnode; pnode = pnode->parent)
! 2570: {
! 2571: if (tree_int_cst_equal (low_minus_one, pnode->high))
! 2572: return 1;
! 2573: /* If a parent node has a left branch we know that none
! 2574: of its parents can have a high bound of our target
! 2575: minus one so we abort the search. */
! 2576: if (node->left)
! 2577: break;
! 2578: }
! 2579: }
! 2580: return 0;
! 2581: }
! 2582:
! 2583: /* Search the parent sections of the case node tree
! 2584: to see if a test for the upper bound of NODE would be redundant.
! 2585:
! 2586: The instructions to synthesis the case decision tree are
! 2587: output in the same order as nodes are processed so it is
! 2588: known that if a parent node checks the range of the current
! 2589: node plus one that the current node is bounded at its upper
! 2590: span. Thus the test would be redundant. */
! 2591:
! 2592: static int
! 2593: node_has_high_bound (node)
! 2594: case_node_ptr node;
! 2595: {
! 2596: tree high_plus_one;
! 2597: case_node_ptr pnode;
! 2598:
! 2599: if (node->right == 0)
! 2600: {
! 2601: high_plus_one = combine (PLUS_EXPR, node->high, build_int_2 (1, 0));
! 2602: for (pnode = node->parent; pnode; pnode = pnode->parent)
! 2603: {
! 2604: if (tree_int_cst_equal (high_plus_one, pnode->low))
! 2605: return 1;
! 2606: /* If a parent node has a right branch we know that none
! 2607: of its parents can have a low bound of our target
! 2608: plus one so we abort the search. */
! 2609: if (node->right)
! 2610: break;
! 2611: }
! 2612: }
! 2613: return 0;
! 2614: }
! 2615:
! 2616: /* Search the parent sections of the
! 2617: case node tree to see if both tests for the upper and lower
! 2618: bounds of NODE would be redundant. */
! 2619:
! 2620: static int
! 2621: node_is_bounded (node)
! 2622: case_node_ptr node;
! 2623: {
! 2624: if (node->left || node->right)
! 2625: return 0;
! 2626: return node_has_low_bound (node) && node_has_high_bound (node);
! 2627: }
! 2628:
! 2629: /* Emit an unconditional jump to LABEL unless it would be dead code. */
! 2630:
! 2631: static void
! 2632: emit_jump_if_reachable (label)
! 2633: rtx label;
! 2634: {
! 2635: rtx last_insn;
! 2636:
! 2637: if (GET_CODE (get_last_insn ()) != BARRIER)
! 2638: emit_jump (label);
! 2639: }
! 2640:
! 2641: /* Emit step-by-step code to select a case for the value of INDEX.
! 2642: The thus generated decision tree follows the form of the
! 2643: case-node binary tree NODE, whose nodes represent test conditions.
! 2644:
! 2645: Care is taken to prune redundant tests from the decision tree
! 2646: by detecting any boundary conditions already checked by
! 2647: emitted rtx. (See node_has_high_bound, node_has_low_bound
! 2648: and node_is_bounded, above.)
! 2649:
! 2650: Where the test conditions can be shown to be redundant we emit
! 2651: an unconditional jump to the target code. As a further
! 2652: optimization, the subordinates of a tree node are examined to
! 2653: check for bounded nodes. In this case conditional and/or
! 2654: unconditional jumps as a result of the boundary check for the
! 2655: current node are arranged to target the subordinates associated
! 2656: code for out of bound conditions on the current node node. */
! 2657:
! 2658: static void
! 2659: emit_case_nodes (index, node, default_label)
! 2660: tree index;
! 2661: case_node_ptr node;
! 2662: tree default_label;
! 2663: {
! 2664: if (node->test_label)
! 2665: {
! 2666: /* If this test node requires a label it follows that
! 2667: it must be preceeded by an unconditional branch.
! 2668: If control can pass to this point we can assume that
! 2669: a "br default" is in order. */
! 2670: emit_jump_if_reachable (default_label);
! 2671: expand_label (node->test_label);
! 2672: }
! 2673: if (tree_int_cst_equal (node->low, node->high))
! 2674: {
! 2675: /* Node is single valued. */
! 2676: do_jump_if_equal (index, expand_expr (node->low, 0, VOIDmode, 0),
! 2677: label_rtx (node->code_label));
! 2678: if (node->right)
! 2679: {
! 2680: if (node->left)
! 2681: {
! 2682: /* This node has children on either side. */
! 2683:
! 2684: if (node_is_bounded (node->right))
! 2685: {
! 2686: emit_jump_insn (gen_bgt (label_rtx (node->right->code_label)));
! 2687: if (node_is_bounded (node->left))
! 2688: emit_jump (label_rtx (node->left->code_label));
! 2689: else
! 2690: emit_case_nodes (index, node->left, default_label);
! 2691: }
! 2692: else
! 2693: {
! 2694: if (node_is_bounded (node->left))
! 2695: emit_jump_insn (gen_blt (label_rtx (node->left->code_label)));
! 2696: else
! 2697: {
! 2698: node->right->test_label =
! 2699: build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
! 2700: emit_jump_insn (gen_bgt (label_rtx (node->right->test_label)));
! 2701: emit_case_nodes (index, node->left, default_label);
! 2702: }
! 2703: emit_case_nodes (index, node->right, default_label);
! 2704: }
! 2705: }
! 2706: else
! 2707: {
! 2708: /* Here we have a right child but no left
! 2709: so we issue conditional branch to default
! 2710: and process the right child. */
! 2711:
! 2712: /* Omit the conditional branch to default
! 2713: if we it avoid only one right child;
! 2714: it costs too much space to save so little time. */
! 2715: if (node->right->right && !node_has_low_bound (node))
! 2716: emit_jump_insn (gen_blt (default_label));
! 2717: if (node_is_bounded (node->right))
! 2718: emit_jump (label_rtx (node->right->code_label));
! 2719: else
! 2720: emit_case_nodes (index, node->right, default_label);
! 2721: }
! 2722: }
! 2723: else if (node->left)
! 2724: {
! 2725: if (node_is_bounded (node->left))
! 2726: emit_jump (label_rtx (node->left->code_label));
! 2727: else
! 2728: emit_case_nodes (index, node->left, default_label);
! 2729: }
! 2730: }
! 2731: else
! 2732: {
! 2733: /* Node is a range. */
! 2734: if (node->right)
! 2735: {
! 2736: if (node->left)
! 2737: {
! 2738: emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0);
! 2739: if (node_is_bounded (node->right))
! 2740: {
! 2741: /* Right hand node is fully bounded so we can
! 2742: eliminate any testing and branch directly
! 2743: to the target code. */
! 2744: emit_jump_insn (gen_bgt (label_rtx (node->right->code_label)));
! 2745: }
! 2746: else
! 2747: {
! 2748: /* Right hand node requires testing so create
! 2749: a label to put on the cmp code. */
! 2750: node->right->test_label =
! 2751: build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
! 2752: emit_jump_insn (gen_bgt (label_rtx (node->right->test_label)));
! 2753: }
! 2754: emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0);
! 2755: emit_jump_insn (gen_bge (label_rtx (node->code_label)));
! 2756: if (node_is_bounded (node->left))
! 2757: {
! 2758: /* Left hand node is fully bounded so we can
! 2759: eliminate any testing and branch directly
! 2760: to the target code. */
! 2761: emit_jump (label_rtx (node->left->code_label));
! 2762: }
! 2763: else
! 2764: emit_case_nodes (index, node->left, default_label);
! 2765: /* If right node has been given a test label above
! 2766: we must process it now. */
! 2767: if (node->right->test_label)
! 2768: emit_case_nodes (index, node->right, default_label);
! 2769: }
! 2770: else
! 2771: {
! 2772: if (!node_has_low_bound (node))
! 2773: {
! 2774: emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0);
! 2775: emit_jump_insn (gen_blt (default_label));
! 2776: }
! 2777: emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0);
! 2778: emit_jump_insn (gen_ble (label_rtx (node->code_label)));
! 2779: if (node_is_bounded (node->right))
! 2780: {
! 2781: /* Right hand node is fully bounded so we can
! 2782: eliminate any testing and branch directly
! 2783: to the target code. */
! 2784: emit_jump (label_rtx (node->right->code_label));
! 2785: }
! 2786: else
! 2787: emit_case_nodes (index, node->right, default_label);
! 2788: }
! 2789: }
! 2790: else if (node->left)
! 2791: {
! 2792: if (!node_has_high_bound (node))
! 2793: {
! 2794: emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0);
! 2795: emit_jump_insn (gen_bgt (default_label));
! 2796: }
! 2797: emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0);
! 2798: emit_jump_insn (gen_bge (label_rtx (node->code_label)));
! 2799: if (node_is_bounded (node->left))
! 2800: {
! 2801: /* Left hand node is fully bounded so we can
! 2802: eliminate any testing and branch directly
! 2803: to the target code. */
! 2804: emit_jump (label_rtx (node->left->code_label));
! 2805: }
! 2806: else
! 2807: emit_case_nodes (index, node->left, default_label);
! 2808: }
! 2809: else
! 2810: {
! 2811: /* Node has no children so we check low and
! 2812: high bounds to remove redundant tests. In practice
! 2813: only one of the limits may be bounded or the parent
! 2814: node will have emmited a jump to our target code. */
! 2815: if (!node_has_high_bound (node))
! 2816: {
! 2817: emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0);
! 2818: emit_jump_insn (gen_bgt (default_label));
! 2819: }
! 2820: if (!node_has_low_bound (node))
! 2821: {
! 2822: emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0);
! 2823: emit_jump_insn (gen_bge (label_rtx (node->code_label)));
! 2824: }
! 2825: /* We allow the default case to drop through since
! 2826: it will picked up by calls to `jump_if_reachable'
! 2827: either on the next test label or at the end of
! 2828: the decision tree emission. */
! 2829: }
! 2830: }
! 2831: }
! 2832:
1.1.1.2 root 2833: /* Allocate fixed slots in the stack frame of the current function. */
1.1 root 2834:
2835: /* Return size needed for stack frame based on slots so far allocated. */
2836:
2837: int
2838: get_frame_size ()
2839: {
1.1.1.2 root 2840: #ifdef FRAME_GROWS_DOWNWARD
2841: return -frame_offset;
2842: #else
1.1 root 2843: return frame_offset;
1.1.1.2 root 2844: #endif
1.1 root 2845: }
2846:
2847: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
2848: with machine mode MODE. */
2849:
2850: rtx
2851: assign_stack_local (mode, size)
2852: enum machine_mode mode;
2853: int size;
2854: {
1.1.1.2 root 2855: register rtx x, addr;
1.1.1.4 root 2856: int bigend_correction = 0;
1.1 root 2857:
1.1.1.2 root 2858: frame_pointer_needed = 1;
1.1 root 2859:
2860: /* Make each stack slot a multiple of the main allocation unit. */
2861: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
2862: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT))
2863: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
2864:
1.1.1.4 root 2865: /* On a big-endian machine, if we are allocating more space than we will use,
2866: use the least significant bytes of those that are allocated. */
2867: #ifdef BYTES_BIG_ENDIAN
2868: if (mode != BLKmode)
2869: bigend_correction = size - GET_MODE_SIZE (mode);
2870: #endif
2871:
1.1 root 2872: #ifdef FRAME_GROWS_DOWNWARD
2873: frame_offset -= size;
2874: #endif
1.1.1.2 root 2875: addr = gen_rtx (PLUS, Pmode, frame_pointer_rtx,
1.1.1.4 root 2876: gen_rtx (CONST_INT, VOIDmode,
2877: (frame_offset + bigend_correction)));
1.1 root 2878: #ifndef FRAME_GROWS_DOWNWARD
2879: frame_offset += size;
2880: #endif
2881:
1.1.1.2 root 2882: if (! memory_address_p (mode, addr))
2883: invalid_stack_slot = 1;
2884:
2885: x = gen_rtx (MEM, mode, addr);
2886:
1.1.1.13! root 2887: stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, x, stack_slot_list);
! 2888:
1.1.1.2 root 2889: return x;
1.1 root 2890: }
2891:
1.1.1.2 root 2892: /* Retroactively move an auto variable from a register to a stack slot.
2893: This is done when an address-reference to the variable is seen. */
1.1 root 2894:
1.1.1.2 root 2895: void
2896: put_var_into_stack (decl)
2897: tree decl;
2898: {
2899: register rtx reg = DECL_RTL (decl);
2900: register rtx new;
1.1 root 2901:
1.1.1.2 root 2902: /* No need to do anything if decl has no rtx yet
2903: since in that case caller is setting TREE_ADDRESSABLE
2904: and a stack slot will be assigned when the rtl is made. */
2905: if (reg == 0)
2906: return;
2907: if (GET_CODE (reg) != REG)
2908: return;
2909:
2910: new = parm_stack_loc (reg);
2911: if (new == 0)
2912: new = assign_stack_local (GET_MODE (reg), GET_MODE_SIZE (GET_MODE (reg)));
2913:
1.1.1.10 root 2914: XEXP (reg, 0) = XEXP (new, 0);
2915: /* `volatil' bit means one thing for MEMs, another entirely for REGs. */
2916: REG_USERVAR_P (reg) = 0;
2917: PUT_CODE (reg, MEM);
2918:
1.1.1.2 root 2919: /* If this is a memory ref that contains aggregate components,
2920: mark it as such for cse and loop optimize. */
1.1.1.10 root 2921: MEM_IN_STRUCT_P (reg)
1.1.1.2 root 2922: = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2923: || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
2924: || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
2925:
2926: fixup_var_refs (reg);
2927: }
2928:
1.1 root 2929: static void
1.1.1.2 root 2930: fixup_var_refs (var)
2931: rtx var;
1.1 root 2932: {
1.1.1.2 root 2933: register rtx insn;
1.1.1.10 root 2934: extern rtx sequence_stack;
2935: rtx stack = sequence_stack;
2936: tree pending;
2937:
2938: stack = sequence_stack;
2939:
2940: /* Must scan all insns for stack-refs that exceed the limit. */
2941: fixup_var_refs_insns (var, get_insns (), stack == 0);
2942:
2943: /* Scan all pending sequences too. */
2944: for (; stack; stack = XEXP (XEXP (stack, 1), 1))
2945: {
2946: push_to_sequence (XEXP (stack, 0));
2947: fixup_var_refs_insns (var, XEXP (stack, 0),
2948: XEXP (XEXP (stack, 1), 1) == 0);
2949: end_sequence ();
2950: }
2951:
2952: /* Scan all waiting RTL_EXPRs too. */
2953: for (pending = rtl_expr_chain; pending; pending = TREE_CHAIN (pending))
2954: {
2955: rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));
2956: if (seq != const0_rtx && seq != 0)
2957: {
2958: push_to_sequence (seq);
2959: fixup_var_refs_insns (var, seq, 0);
2960: end_sequence ();
2961: }
2962: }
2963: }
1.1.1.2 root 2964:
1.1.1.10 root 2965: /* Scan the insn-chain starting with INSN for refs to VAR
2966: and fix them up. TOPLEVEL is nonzero if this chain is the
2967: main chain of insns for the current function. */
2968:
2969: static void
2970: fixup_var_refs_insns (var, insn, toplevel)
2971: rtx var;
2972: rtx insn;
2973: int toplevel;
2974: {
2975: while (insn)
1.1.1.2 root 2976: {
2977: rtx next = NEXT_INSN (insn);
1.1.1.13! root 2978: rtx note;
1.1.1.2 root 2979: if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
2980: || GET_CODE (insn) == JUMP_INSN)
2981: {
2982: /* The insn to load VAR from a home in the arglist
2983: is now a no-op. When we see it, just delete it. */
1.1.1.10 root 2984: if (toplevel
2985: && GET_CODE (PATTERN (insn)) == SET
1.1.1.2 root 2986: && SET_DEST (PATTERN (insn)) == var
2987: && rtx_equal_p (SET_SRC (PATTERN (insn)), var))
1.1.1.8 root 2988: {
2989: next = delete_insn (insn);
2990: if (insn == last_parm_insn)
2991: last_parm_insn = PREV_INSN (next);
2992: }
1.1.1.2 root 2993: else
2994: fixup_var_refs_1 (var, PATTERN (insn), insn);
1.1.1.13! root 2995: /* Also fix up any invalid exprs in the REG_NOTES of this insn.
! 2996: But don't touch other insns referred to by reg-notes;
! 2997: we will get them elsewhere. */
! 2998: for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
! 2999: if (GET_CODE (note) != INSN_LIST)
! 3000: XEXP (note, 0) = walk_fixup_memory_subreg (XEXP (note, 0), insn);
1.1.1.2 root 3001: }
3002: insn = next;
3003: }
3004: }
1.1.1.13! root 3005:
1.1.1.2 root 3006: static rtx
3007: fixup_var_refs_1 (var, x, insn)
3008: register rtx var;
3009: register rtx x;
3010: rtx insn;
3011: {
3012: register int i;
3013: RTX_CODE code = GET_CODE (x);
3014: register char *fmt;
3015: register rtx tem;
3016:
3017: switch (code)
3018: {
3019: case MEM:
3020: if (var == x)
3021: {
3022: x = fixup_stack_1 (x, insn);
3023: tem = gen_reg_rtx (GET_MODE (x));
3024: emit_insn_before (gen_move_insn (tem, x), insn);
3025: return tem;
3026: }
3027: break;
3028:
3029: case REG:
3030: case CC0:
3031: case PC:
3032: case CONST_INT:
3033: case CONST:
3034: case SYMBOL_REF:
3035: case LABEL_REF:
3036: case CONST_DOUBLE:
3037: return x;
3038:
3039: case SIGN_EXTRACT:
3040: case ZERO_EXTRACT:
3041: /* Note that in some cases those types of expressions are altered
3042: by optimize_bit_field, and do not survive to get here. */
3043: case SUBREG:
3044: tem = x;
3045: while (GET_CODE (tem) == SUBREG || GET_CODE (tem) == SIGN_EXTRACT
3046: || GET_CODE (tem) == ZERO_EXTRACT)
3047: tem = XEXP (tem, 0);
3048: if (tem == var)
3049: {
3050: x = fixup_stack_1 (x, insn);
3051: tem = gen_reg_rtx (GET_MODE (x));
1.1.1.7 root 3052: if (GET_CODE (x) == SUBREG)
1.1.1.13! root 3053: x = fixup_memory_subreg (x, insn);
1.1.1.2 root 3054: emit_insn_before (gen_move_insn (tem, x), insn);
3055: return tem;
3056: }
3057: break;
3058:
3059: case SET:
3060: /* First do special simplification of bit-field references. */
3061: if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
3062: || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
3063: optimize_bit_field (x, insn, 0);
3064: if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
3065: || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
3066: optimize_bit_field (x, insn, 0);
3067:
3068: {
3069: rtx dest = SET_DEST (x);
3070: rtx src = SET_SRC (x);
3071: rtx outerdest = dest;
3072: rtx outersrc = src;
3073:
3074: while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
3075: || GET_CODE (dest) == SIGN_EXTRACT
3076: || GET_CODE (dest) == ZERO_EXTRACT)
3077: dest = XEXP (dest, 0);
3078: while (GET_CODE (src) == SUBREG
3079: || GET_CODE (src) == SIGN_EXTRACT
3080: || GET_CODE (src) == ZERO_EXTRACT)
3081: src = XEXP (src, 0);
3082:
3083: /* If VAR does not appear at the top level of the SET
3084: just scan the lower levels of the tree. */
3085:
3086: if (src != var && dest != var)
3087: break;
3088:
3089: /* Clean up (SUBREG:SI (MEM:mode ...) 0)
3090: that may appear inside a SIGN_EXTRACT or ZERO_EXTRACT.
3091: This was legitimate when the MEM was a REG. */
3092:
3093: if ((GET_CODE (outerdest) == SIGN_EXTRACT
3094: || GET_CODE (outerdest) == ZERO_EXTRACT)
3095: && GET_CODE (XEXP (outerdest, 0)) == SUBREG
3096: && SUBREG_REG (XEXP (outerdest, 0)) == var)
1.1.1.13! root 3097: XEXP (outerdest, 0) = fixup_memory_subreg (XEXP (outerdest, 0), insn);
1.1.1.2 root 3098:
3099: if ((GET_CODE (outersrc) == SIGN_EXTRACT
3100: || GET_CODE (outersrc) == ZERO_EXTRACT)
3101: && GET_CODE (XEXP (outersrc, 0)) == SUBREG
3102: && SUBREG_REG (XEXP (outersrc, 0)) == var)
1.1.1.13! root 3103: XEXP (outersrc, 0) = fixup_memory_subreg (XEXP (outersrc, 0), insn);
1.1.1.2 root 3104:
3105: /* Make sure a MEM inside a SIGN_EXTRACT has QImode
3106: since that's what bit-field insns want. */
3107:
3108: if ((GET_CODE (outerdest) == SIGN_EXTRACT
3109: || GET_CODE (outerdest) == ZERO_EXTRACT)
3110: && GET_CODE (XEXP (outerdest, 0)) == MEM
3111: && GET_MODE (XEXP (outerdest, 0)) != QImode)
3112: {
3113: XEXP (outerdest, 0) = copy_rtx (XEXP (outerdest, 0));
3114: PUT_MODE (XEXP (outerdest, 0), QImode);
3115: }
3116:
3117: if ((GET_CODE (outersrc) == SIGN_EXTRACT
3118: || GET_CODE (outersrc) == ZERO_EXTRACT)
3119: && GET_CODE (XEXP (outersrc, 0)) == MEM
3120: && GET_MODE (XEXP (outersrc, 0)) != QImode)
3121: {
3122: XEXP (outersrc, 0) = copy_rtx (XEXP (outersrc, 0));
3123: PUT_MODE (XEXP (outersrc, 0), QImode);
3124: }
3125:
3126: /* STRICT_LOW_PART is a no-op on memory references
3127: and it can cause combinations to be unrecognizable,
3128: so eliminate it. */
3129:
3130: if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
3131: SET_DEST (x) = XEXP (SET_DEST (x), 0);
3132:
3133: /* An insn to copy VAR into or out of a register
3134: must be left alone, to avoid an infinite loop here.
1.1.1.9 root 3135: But do fix up the address of VAR's stack slot if nec,
3136: and fix up SUBREGs containing VAR
3137: (since they are now memory subregs). */
3138:
3139: if (GET_CODE (SET_SRC (x)) == REG || GET_CODE (SET_DEST (x)) == REG
3140: || (GET_CODE (SET_SRC (x)) == SUBREG
3141: && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG)
1.1.1.2 root 3142: || (GET_CODE (SET_DEST (x)) == SUBREG
3143: && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
1.1.1.9 root 3144: {
3145: if (src == var && GET_CODE (SET_SRC (x)) == SUBREG)
1.1.1.13! root 3146: SET_SRC (x) = fixup_memory_subreg (SET_SRC (x), insn);
1.1.1.9 root 3147: if (dest == var && GET_CODE (SET_DEST (x)) == SUBREG)
1.1.1.13! root 3148: SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn);
1.1.1.9 root 3149: return fixup_stack_1 (x, insn);
3150: }
1.1.1.2 root 3151:
3152: /* Otherwise, storing into VAR must be handled specially
3153: by storing into a temporary and copying that into VAR
3154: with a new insn after this one. */
3155:
3156: if (dest == var)
3157: {
3158: rtx temp;
3159: rtx fixeddest;
3160: tem = SET_DEST (x);
1.1.1.12 root 3161: /* STRICT_LOW_PART can be discarded, around a MEM. */
1.1.1.2 root 3162: if (GET_CODE (tem) == STRICT_LOW_PART)
3163: tem = XEXP (tem, 0);
1.1.1.12 root 3164: /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
3165: if (GET_CODE (tem) == SUBREG)
1.1.1.13! root 3166: tem = fixup_memory_subreg (tem, insn);
1.1.1.12 root 3167: fixeddest = fixup_stack_1 (tem, insn);
1.1.1.2 root 3168: temp = gen_reg_rtx (GET_MODE (tem));
3169: emit_insn_after (gen_move_insn (fixeddest, temp), insn);
3170: SET_DEST (x) = temp;
3171: }
3172: }
3173: }
3174:
3175: /* Nothing special about this RTX; fix its operands. */
3176:
3177: fmt = GET_RTX_FORMAT (code);
3178: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3179: {
3180: if (fmt[i] == 'e')
3181: XEXP (x, i) = fixup_var_refs_1 (var, XEXP (x, i), insn);
3182: if (fmt[i] == 'E')
3183: {
3184: register int j;
3185: for (j = 0; j < XVECLEN (x, i); j++)
3186: XVECEXP (x, i, j)
3187: = fixup_var_refs_1 (var, XVECEXP (x, i, j), insn);
3188: }
3189: }
3190: return x;
3191: }
1.1.1.13! root 3192:
1.1.1.2 root 3193: /* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
1.1.1.13! root 3194: return an rtx (MEM:m1 newaddr) which is equivalent.
! 3195: If any insns must be emitted to compute NEWADDR, put them before INSN. */
1.1.1.2 root 3196:
3197: static rtx
1.1.1.13! root 3198: fixup_memory_subreg (x, insn)
1.1.1.2 root 3199: rtx x;
1.1.1.13! root 3200: rtx insn;
1.1.1.2 root 3201: {
3202: int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
3203: rtx addr = XEXP (SUBREG_REG (x), 0);
1.1.1.7 root 3204: enum machine_mode mode = GET_MODE (x);
1.1.1.13! root 3205: rtx saved, result;
1.1.1.2 root 3206:
3207: #ifdef BYTES_BIG_ENDIAN
1.1.1.8 root 3208: offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
1.1.1.2 root 3209: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
3210: #endif
1.1.1.13! root 3211: addr = plus_constant (addr, offset);
! 3212: if (memory_address_p (mode, addr))
! 3213: return change_address (SUBREG_REG (x), mode, addr);
! 3214: saved = start_sequence ();
! 3215: result = change_address (SUBREG_REG (x), mode, addr);
! 3216: emit_insn_before (gen_sequence (), insn);
! 3217: end_sequence (saved);
! 3218: return result;
! 3219: }
! 3220:
! 3221: /* Do fixup_memory_subreg on all (SUBREG (MEM ...) ...) contained in X.
! 3222: Replace subexpressions of X in place.
! 3223: If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
! 3224: Otherwise return X, with its contents possibly altered.
! 3225:
! 3226: If any insns must be emitted to compute NEWADDR, put them before INSN. */
! 3227:
! 3228: static rtx
! 3229: walk_fixup_memory_subreg (x, insn)
! 3230: register rtx x;
! 3231: rtx insn;
! 3232: {
! 3233: register enum rtx_code code;
! 3234: register char *fmt;
! 3235: register int i;
! 3236:
! 3237: code = GET_CODE (x);
! 3238:
! 3239: if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
! 3240: return fixup_memory_subreg (x, insn);
! 3241:
! 3242: /* Nothing special about this RTX; fix its operands. */
! 3243:
! 3244: fmt = GET_RTX_FORMAT (code);
! 3245: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
! 3246: {
! 3247: if (fmt[i] == 'e')
! 3248: XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn);
! 3249: if (fmt[i] == 'E')
! 3250: {
! 3251: register int j;
! 3252: for (j = 0; j < XVECLEN (x, i); j++)
! 3253: XVECEXP (x, i, j)
! 3254: = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn);
! 3255: }
! 3256: }
! 3257: return x;
1.1.1.2 root 3258: }
3259:
3260: #if 0
3261: /* Fix up any references to stack slots that are invalid memory addresses
3262: because they exceed the maximum range of a displacement. */
3263:
3264: void
3265: fixup_stack_slots ()
3266: {
3267: register rtx insn;
3268:
3269: /* Did we generate a stack slot that is out of range
3270: or otherwise has an invalid address? */
3271: if (invalid_stack_slot)
3272: {
3273: /* Yes. Must scan all insns for stack-refs that exceed the limit. */
3274: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3275: if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
3276: || GET_CODE (insn) == JUMP_INSN)
3277: fixup_stack_1 (PATTERN (insn), insn);
3278: }
3279: }
3280: #endif
3281:
3282: /* For each memory ref within X, if it refers to a stack slot
3283: with an out of range displacement, put the address in a temp register
3284: (emitting new insns before INSN to load these registers)
3285: and alter the memory ref to use that register.
3286: Replace each such MEM rtx with a copy, to avoid clobberage. */
3287:
3288: static rtx
3289: fixup_stack_1 (x, insn)
3290: rtx x;
3291: rtx insn;
3292: {
3293: register int i;
3294: register RTX_CODE code = GET_CODE (x);
3295: register char *fmt;
3296:
3297: if (code == MEM)
3298: {
3299: register rtx ad = XEXP (x, 0);
3300: /* If we have address of a stack slot but it's not valid
3301: (displacement is too large), compute the sum in a register. */
3302: if (GET_CODE (ad) == PLUS
3303: && XEXP (ad, 0) == frame_pointer_rtx
3304: && GET_CODE (XEXP (ad, 1)) == CONST_INT)
3305: {
3306: rtx temp;
3307: if (memory_address_p (GET_MODE (x), ad))
3308: return x;
3309: temp = gen_reg_rtx (GET_MODE (ad));
3310: emit_insn_before (gen_move_insn (temp, ad), insn);
3311: return change_address (x, VOIDmode, temp);
3312: }
3313: return x;
3314: }
3315:
3316: fmt = GET_RTX_FORMAT (code);
3317: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3318: {
3319: if (fmt[i] == 'e')
3320: XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
3321: if (fmt[i] == 'E')
3322: {
3323: register int j;
3324: for (j = 0; j < XVECLEN (x, i); j++)
3325: XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
3326: }
3327: }
3328: return x;
1.1 root 3329: }
1.1.1.2 root 3330:
3331: /* Optimization: a bit-field instruction whose field
3332: happens to be a byte or halfword in memory
3333: can be changed to a move instruction.
1.1 root 3334:
1.1.1.2 root 3335: We call here when INSN is an insn to examine or store into a bit-field.
3336: BODY is the SET-rtx to be altered.
3337:
3338: EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.
3339: (Currently this is called only from stmt.c, and EQUIV_MEM is always 0.) */
1.1 root 3340:
3341: static void
1.1.1.2 root 3342: optimize_bit_field (body, insn, equiv_mem)
3343: rtx body;
3344: rtx insn;
3345: rtx *equiv_mem;
1.1 root 3346: {
1.1.1.2 root 3347: register rtx bitfield;
3348: int destflag;
1.1 root 3349:
1.1.1.2 root 3350: if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
3351: || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
3352: bitfield = SET_DEST (body), destflag = 1;
3353: else
3354: bitfield = SET_SRC (body), destflag = 0;
3355:
3356: /* First check that the field being stored has constant size and position
3357: and is in fact a byte or halfword suitably aligned. */
3358:
3359: if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
3360: && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
3361: && (INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (QImode)
3362: || INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (HImode))
3363: && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
1.1 root 3364: {
1.1.1.2 root 3365: register rtx memref = 0;
3366:
1.1.1.10 root 3367: /* Now check that the containing word is memory, not a register,
1.1.1.2 root 3368: and that it is safe to change the machine mode and to
3369: add something to the address. */
3370:
3371: if (GET_CODE (XEXP (bitfield, 0)) == MEM)
3372: memref = XEXP (bitfield, 0);
3373: else if (GET_CODE (XEXP (bitfield, 0)) == REG
1.1.1.8 root 3374: && equiv_mem != 0)
3375: memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
1.1.1.2 root 3376: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
3377: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)
3378: memref = SUBREG_REG (XEXP (bitfield, 0));
3379: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
3380: && equiv_mem != 0
1.1.1.8 root 3381: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)
3382: memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
1.1.1.2 root 3383:
3384: if (memref
3385: && ! mode_dependent_address_p (XEXP (memref, 0))
3386: && offsetable_address_p (GET_MODE (bitfield), XEXP (memref, 0)))
1.1 root 3387: {
1.1.1.2 root 3388: /* Now adjust the address, first for any subreg'ing
3389: that we are now getting rid of,
3390: and then for which byte of the word is wanted. */
3391:
3392: register int offset
3393: = INTVAL (XEXP (bitfield, 2)) / GET_MODE_BITSIZE (QImode);
3394: if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
3395: {
3396: offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
3397: #ifdef BYTES_BIG_ENDIAN
3398: offset -= (MIN (UNITS_PER_WORD,
3399: GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
3400: - MIN (UNITS_PER_WORD,
3401: GET_MODE_SIZE (GET_MODE (memref))));
3402: #endif
3403: }
1.1.1.8 root 3404:
1.1.1.2 root 3405: memref = gen_rtx (MEM,
3406: (INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (QImode)
3407: ? QImode : HImode),
3408: XEXP (memref, 0));
1.1 root 3409:
1.1.1.2 root 3410: /* Store this memory reference where
3411: we found the bit field reference. */
1.1 root 3412:
1.1.1.2 root 3413: if (destflag)
1.1 root 3414: {
1.1.1.2 root 3415: SET_DEST (body)
3416: = adj_offsetable_operand (memref, offset);
3417: if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
1.1 root 3418: {
1.1.1.2 root 3419: rtx src = SET_SRC (body);
3420: while (GET_CODE (src) == SUBREG
3421: && SUBREG_WORD (src) == 0)
3422: src = SUBREG_REG (src);
3423: if (GET_MODE (src) != GET_MODE (memref))
1.1.1.10 root 3424: src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
1.1.1.2 root 3425: SET_SRC (body) = src;
1.1 root 3426: }
1.1.1.2 root 3427: else if (GET_MODE (SET_SRC (body)) != VOIDmode
3428: && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
3429: /* This shouldn't happen because anything that didn't have
3430: one of these modes should have got converted explicitly
3431: and then referenced through a subreg.
3432: This is so because the original bit-field was
3433: handled by agg_mode and so its tree structure had
3434: the same mode that memref now has. */
3435: abort ();
3436: }
3437: else
3438: {
1.1.1.8 root 3439: rtx dest = SET_DEST (body);
3440:
3441: while (GET_CODE (dest) == SUBREG
3442: && SUBREG_WORD (dest) == 0)
3443: dest = SUBREG_REG (dest);
3444: SET_DEST (body) = dest;
3445:
3446: memref = adj_offsetable_operand (memref, offset);
3447: if (GET_MODE (dest) == GET_MODE (memref))
3448: SET_SRC (body) = memref;
3449: else
3450: {
1.1.1.10 root 3451: /* Convert the mem ref to the destination mode. */
3452: rtx last = get_last_insn ();
1.1.1.8 root 3453: rtx newreg = gen_reg_rtx (GET_MODE (dest));
1.1.1.10 root 3454: convert_move (newreg, memref,
3455: GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
3456: /* Put the conversion before the insn being fixed. */
3457: reorder_insns (NEXT_INSN (last), get_last_insn (),
3458: PREV_INSN (insn));
1.1.1.8 root 3459: SET_SRC (body) = newreg;
3460: }
1.1 root 3461: }
1.1.1.2 root 3462:
3463: /* Cause the insn to be re-recognized. */
3464:
3465: INSN_CODE (insn) = -1;
1.1 root 3466: }
3467: }
3468: }
3469:
3470: /* 1 + last pseudo register number used for loading a copy
3471: of a parameter of this function. */
3472:
3473: static int max_parm_reg;
3474:
1.1.1.2 root 3475: /* Vector indexed by REGNO, containing location on stack in which
3476: to put the parm which is nominally in pseudo register REGNO,
3477: if we discover that that parm must go in the stack. */
3478: static rtx *parm_reg_stack_loc;
3479:
3480: int
3481: max_parm_reg_num ()
3482: {
3483: return max_parm_reg;
3484: }
3485:
3486: /* Return the first insn following those generated by `assign_parms'. */
3487:
3488: rtx
3489: get_first_nonparm_insn ()
3490: {
3491: if (last_parm_insn)
3492: return NEXT_INSN (last_parm_insn);
3493: return get_insns ();
3494: }
3495:
3496: /* Get the stack home of a REG rtx that is one of this function's parameters.
3497: This is called rather than assign a new stack slot as a local.
3498: Return 0 if there is no existing stack home suitable for such use. */
3499:
3500: static rtx
3501: parm_stack_loc (reg)
3502: rtx reg;
3503: {
3504: if (REGNO (reg) < max_parm_reg)
3505: return parm_reg_stack_loc[REGNO (reg)];
3506: return 0;
3507: }
3508:
1.1 root 3509: /* Assign RTL expressions to the function's parameters.
3510: This may involve copying them into registers and using
3511: those registers as the RTL for them. */
3512:
3513: static void
3514: assign_parms (fndecl)
3515: tree fndecl;
3516: {
3517: register tree parm;
1.1.1.2 root 3518: register rtx entry_parm;
3519: register rtx stack_parm;
3520: register CUMULATIVE_ARGS args_so_far;
3521: enum machine_mode passed_mode, nominal_mode;
3522: /* Total space needed so far for args on the stack,
3523: given as a constant and a tree-expression. */
3524: struct args_size stack_args_size;
1.1.1.8 root 3525: int first_parm_offset = FIRST_PARM_OFFSET (fndecl);
1.1.1.13! root 3526: tree fntype = TREE_TYPE (fndecl);
1.1.1.2 root 3527:
3528: int nparmregs
3529: = list_length (DECL_ARGUMENTS (fndecl)) + FIRST_PSEUDO_REGISTER;
3530:
3531: /* Nonzero if function takes extra anonymous args.
3532: This means the last named arg must be on the stack
1.1.1.4 root 3533: right before the anonymous ones.
3534: Also nonzero if the first arg is named `__builtin_va_alist',
3535: which is used on some machines for old-fashioned non-ANSI varargs.h;
3536: this too should be stuck onto the stack as if it had arrived there. */
1.1.1.2 root 3537: int vararg
1.1.1.4 root 3538: = ((DECL_ARGUMENTS (fndecl) != 0
1.1.1.13! root 3539: && DECL_NAME (DECL_ARGUMENTS (fndecl))
1.1.1.4 root 3540: && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (DECL_ARGUMENTS (fndecl))),
3541: "__builtin_va_alist")))
3542: ||
1.1.1.13! root 3543: (TYPE_ARG_TYPES (fntype) != 0
! 3544: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1.1.1.4 root 3545: != void_type_node)));
1.1.1.2 root 3546:
3547: stack_args_size.constant = 0;
3548: stack_args_size.var = 0;
3549:
1.1.1.6 root 3550: /* If struct value address comes on the stack, count it in size of args. */
3551: if (DECL_MODE (DECL_RESULT (fndecl)) == BLKmode
3552: && GET_CODE (struct_value_incoming_rtx) == MEM)
3553: stack_args_size.constant += GET_MODE_SIZE (Pmode);
3554:
1.1.1.2 root 3555: parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx));
3556: bzero (parm_reg_stack_loc, nparmregs * sizeof (rtx));
3557:
1.1.1.13! root 3558: INIT_CUMULATIVE_ARGS (args_so_far, fntype);
1.1 root 3559:
1.1.1.2 root 3560: for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
1.1 root 3561: {
1.1.1.2 root 3562: int aggregate
3563: = (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE
3564: || TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE
3565: || TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE);
3566: struct args_size stack_offset;
3567: rtx stack_offset_rtx;
1.1.1.6 root 3568: enum direction where_pad;
1.1.1.2 root 3569:
3570: DECL_OFFSET (parm) = -1;
3571:
1.1.1.8 root 3572: if (TREE_TYPE (parm) == error_mark_node
1.1.1.10 root 3573: /* This can happen after weird syntax errors
3574: or if an enum type is defined among the parms. */
1.1.1.8 root 3575: || TREE_CODE (parm) != PARM_DECL
3576: || DECL_ARG_TYPE (parm) == NULL)
1.1.1.2 root 3577: {
3578: DECL_RTL (parm) = gen_rtx (MEM, BLKmode, const0_rtx);
1.1.1.13! root 3579: TREE_USED (parm) = 1;
1.1.1.2 root 3580: continue;
3581: }
3582:
3583: /* Find mode of arg as it is passed, and mode of arg
3584: as it should be during execution of this function. */
3585: passed_mode = TYPE_MODE (DECL_ARG_TYPE (parm));
3586: nominal_mode = TYPE_MODE (TREE_TYPE (parm));
3587:
1.1.1.6 root 3588: /* Get this parm's offset as an rtx. */
3589: stack_offset = stack_args_size;
1.1.1.8 root 3590: stack_offset.constant += first_parm_offset;
1.1.1.6 root 3591:
3592: /* Find out if the parm needs padding, and whether above or below. */
3593: where_pad
3594: = FUNCTION_ARG_PADDING (passed_mode,
3595: expand_expr (size_in_bytes (DECL_ARG_TYPE (parm)),
3596: 0, VOIDmode, 0));
3597:
3598: /* If it is padded below, adjust the stack address
3599: upward over the padding. */
3600: if (where_pad == downward)
3601: {
3602: if (passed_mode != BLKmode)
3603: {
3604: if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
3605: stack_offset.constant
3606: += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
3607: / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
3608: - GET_MODE_SIZE (passed_mode));
3609: }
3610: else
3611: {
3612: tree sizetree = size_in_bytes (DECL_ARG_TYPE (parm));
3613: /* Round the size up to multiple of PARM_BOUNDARY bits. */
3614: tree s1 = convert_units (sizetree, BITS_PER_UNIT, PARM_BOUNDARY);
3615: tree s2 = convert_units (s1, PARM_BOUNDARY, BITS_PER_UNIT);
3616: /* Add it in. */
3617: ADD_PARM_SIZE (stack_offset, s2);
3618: SUB_PARM_SIZE (stack_offset, sizetree);
3619: }
3620: }
3621:
3622: stack_offset_rtx = ARGS_SIZE_RTX (stack_offset);
3623:
1.1.1.2 root 3624: /* Determine parm's home in the stack,
3625: in case it arrives in the stack or we should pretend it did. */
3626: stack_parm
3627: = gen_rtx (MEM, passed_mode,
3628: memory_address (passed_mode,
3629: gen_rtx (PLUS, Pmode,
3630: arg_pointer_rtx, stack_offset_rtx)));
3631:
3632: /* If this is a memory ref that contains aggregate components,
3633: mark it as such for cse and loop optimize. */
1.1.1.10 root 3634: MEM_IN_STRUCT_P (stack_parm) = aggregate;
1.1.1.2 root 3635:
3636: /* Let machine desc say which reg (if any) the parm arrives in.
3637: 0 means it arrives on the stack. */
3638: entry_parm = 0;
3639: /* Variable-size args, and args following such, are never in regs. */
3640: if (TREE_CODE (TYPE_SIZE (TREE_TYPE (parm))) == INTEGER_CST
3641: || stack_offset.var != 0)
3642: {
3643: #ifdef FUNCTION_INCOMING_ARG
3644: entry_parm
3645: = FUNCTION_INCOMING_ARG (args_so_far, passed_mode,
3646: DECL_ARG_TYPE (parm), 1);
3647: #else
3648: entry_parm
3649: = FUNCTION_ARG (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1);
3650: #endif
3651: }
3652: /* If this parm was passed part in regs and part in memory,
3653: pretend it arrived entirely in memory
3654: by pushing the register-part onto the stack.
3655:
3656: In the special case of a DImode or DFmode that is split,
3657: we could put it together in a pseudoreg directly,
3658: but for now that's not worth bothering with. */
3659:
3660: /* If this is the last named arg and anonymous args follow,
3661: likewise pretend this arg arrived on the stack
3662: so varargs can find the anonymous args following it. */
3663: {
3664: int nregs = 0;
3665: int i;
3666: #ifdef FUNCTION_ARG_PARTIAL_NREGS
3667: nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, passed_mode,
3668: DECL_ARG_TYPE (parm), 1);
3669: #endif
3670: if (TREE_CHAIN (parm) == 0 && vararg && entry_parm != 0)
1.1.1.4 root 3671: {
3672: if (GET_MODE (entry_parm) == BLKmode)
3673: nregs = GET_MODE_SIZE (GET_MODE (entry_parm)) / UNITS_PER_WORD;
3674: else
3675: nregs = (int_size_in_bytes (DECL_ARG_TYPE (parm))
3676: / UNITS_PER_WORD);
3677: }
1.1.1.2 root 3678:
3679: if (nregs > 0)
1.1.1.4 root 3680: {
3681: current_function_pretend_args_size
3682: = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
3683: / (PARM_BOUNDARY / BITS_PER_UNIT)
3684: * (PARM_BOUNDARY / BITS_PER_UNIT));
3685:
3686: i = nregs;
3687: while (--i >= 0)
3688: emit_move_insn (gen_rtx (MEM, SImode,
3689: plus_constant (XEXP (stack_parm, 0),
3690: i * GET_MODE_SIZE (SImode))),
3691: gen_rtx (REG, SImode, REGNO (entry_parm) + i));
3692: entry_parm = stack_parm;
3693: }
1.1.1.2 root 3694: }
3695:
1.1.1.4 root 3696: /* If we didn't decide this parm came in a register,
3697: by default it came on the stack. */
1.1.1.2 root 3698: if (entry_parm == 0)
3699: entry_parm = stack_parm;
3700:
1.1.1.4 root 3701: /* For a stack parm, record in DECL_OFFSET the arglist offset
3702: of the parm at the time it is passed (before conversion). */
1.1.1.2 root 3703: if (entry_parm == stack_parm)
1.1.1.4 root 3704: DECL_OFFSET (parm) = stack_offset.constant * BITS_PER_UNIT;
3705:
3706: /* If there is actually space on the stack for this parm,
3707: count it in stack_args_size; otherwise set stack_parm to 0
3708: to indicate there is no preallocated stack slot for the parm. */
3709:
3710: if (entry_parm == stack_parm
3711: #ifdef REG_PARM_STACK_SPACE
3712: /* On some machines, even if a parm value arrives in a register
3713: there is still an (uninitialized) stack slot allocated for it. */
3714: || 1
3715: #endif
3716: )
1.1.1.2 root 3717: {
3718: tree sizetree = size_in_bytes (DECL_ARG_TYPE (parm));
1.1.1.6 root 3719: if (where_pad != none)
3720: {
3721: /* Round the size up to multiple of PARM_BOUNDARY bits. */
3722: tree s1 = convert_units (sizetree, BITS_PER_UNIT, PARM_BOUNDARY);
3723: sizetree = convert_units (s1, PARM_BOUNDARY, BITS_PER_UNIT);
3724: }
1.1.1.2 root 3725: /* Add it in. */
1.1.1.6 root 3726: ADD_PARM_SIZE (stack_args_size, sizetree);
1.1.1.2 root 3727: }
1.1.1.4 root 3728: else
3729: /* No stack slot was pushed for this parm. */
3730: stack_parm = 0;
1.1.1.2 root 3731:
1.1.1.4 root 3732: /* Now adjust STACK_PARM to the mode and precise location
1.1.1.2 root 3733: where this parameter should live during execution,
3734: if we discover that it must live in the stack during execution.
3735: To make debuggers happier on big-endian machines, we store
3736: the value in the last bytes of the space available. */
3737:
1.1.1.4 root 3738: if (nominal_mode != BLKmode && nominal_mode != passed_mode
3739: && stack_parm != 0)
1.1.1.2 root 3740: {
3741: #ifdef BYTES_BIG_ENDIAN
1.1.1.6 root 3742: if (GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
3743: {
3744: stack_offset.constant
3745: += GET_MODE_SIZE (passed_mode)
3746: - GET_MODE_SIZE (nominal_mode);
3747: stack_offset_rtx = ARGS_SIZE_RTX (stack_offset);
3748: }
1.1.1.2 root 3749: #endif
3750:
3751: stack_parm
3752: = gen_rtx (MEM, nominal_mode,
3753: memory_address (nominal_mode,
3754: gen_rtx (PLUS, Pmode,
3755: arg_pointer_rtx,
3756: stack_offset_rtx)));
3757:
3758: /* If this is a memory ref that contains aggregate components,
3759: mark it as such for cse and loop optimize. */
1.1.1.10 root 3760: MEM_IN_STRUCT_P (stack_parm) = aggregate;
1.1.1.2 root 3761: }
3762:
3763: /* ENTRY_PARM is an RTX for the parameter as it arrives,
3764: in the mode in which it arrives.
1.1.1.4 root 3765: STACK_PARM is an RTX for a stack slot where the parameter can live
3766: during the function (in case we want to put it there).
3767: STACK_PARM is 0 if no stack slot was pushed for it.
1.1 root 3768:
1.1.1.4 root 3769: Now output code if necessary to convert ENTRY_PARM to
1.1 root 3770: the type in which this function declares it,
1.1.1.4 root 3771: and store that result in an appropriate place,
3772: which may be a pseudo reg, may be STACK_PARM,
3773: or may be a local stack slot if STACK_PARM is 0.
3774:
3775: Set DECL_RTL to that place. */
1.1.1.2 root 3776:
3777: if (nominal_mode == BLKmode)
3778: {
3779: /* If a BLKmode arrives in registers, copy it to a stack slot. */
1.1.1.4 root 3780: if (GET_CODE (entry_parm) == REG)
1.1.1.2 root 3781: {
1.1.1.4 root 3782: if (stack_parm == 0)
3783: stack_parm
3784: = assign_stack_local (GET_MODE (entry_parm),
3785: int_size_in_bytes (TREE_TYPE (parm)));
1.1.1.2 root 3786:
3787: move_block_from_reg (REGNO (entry_parm), stack_parm,
3788: int_size_in_bytes (TREE_TYPE (parm))
3789: / UNITS_PER_WORD);
3790: }
3791: DECL_RTL (parm) = stack_parm;
3792: }
1.1.1.10 root 3793: else if (! ((obey_regdecls && ! TREE_REGDECL (parm)
3794: && ! TREE_INLINE (fndecl))
1.1.1.2 root 3795: /* If -ffloat-store specified, don't put explicit
3796: float variables into registers. */
3797: || (flag_float_store
3798: && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)))
1.1 root 3799: {
1.1.1.2 root 3800: /* Store the parm in a pseudoregister during the function. */
3801: register rtx parmreg = gen_reg_rtx (nominal_mode);
1.1 root 3802:
1.1.1.10 root 3803: REG_USERVAR_P (parmreg) = 1;
1.1 root 3804: DECL_RTL (parm) = parmreg;
3805:
3806: /* Copy the value into the register. */
1.1.1.2 root 3807: if (GET_MODE (parmreg) != GET_MODE (entry_parm))
3808: convert_move (parmreg, entry_parm, 0);
1.1 root 3809: else
1.1.1.2 root 3810: emit_move_insn (parmreg, entry_parm);
3811:
3812: /* In any case, record the parm's desired stack location
3813: in case we later discover it must live in the stack. */
3814: if (REGNO (parmreg) >= nparmregs)
3815: {
3816: rtx *new;
3817: nparmregs = REGNO (parmreg) + 5;
3818: new = (rtx *) oballoc (nparmregs * sizeof (rtx));
3819: bcopy (parm_reg_stack_loc, new, nparmregs * sizeof (rtx));
3820: parm_reg_stack_loc = new;
3821: }
3822: parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
1.1 root 3823:
1.1.1.2 root 3824: /* Mark the register as eliminable if we did no conversion
3825: and it was copied from memory at a fixed offset. */
3826: if (nominal_mode == passed_mode
3827: && GET_CODE (entry_parm) == MEM
3828: && stack_offset.var == 0)
1.1.1.10 root 3829: REG_NOTES (get_last_insn ())
3830: = gen_rtx (EXPR_LIST, REG_EQUIV,
3831: entry_parm, REG_NOTES (get_last_insn ()));
1.1 root 3832:
3833: /* For pointer data type, suggest pointer register. */
3834: if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
3835: mark_reg_pointer (parmreg);
3836: }
1.1.1.2 root 3837: else
1.1 root 3838: {
1.1.1.2 root 3839: /* Value must be stored in the stack slot STACK_PARM
3840: during function execution. */
3841:
3842: if (passed_mode != nominal_mode)
3843: /* Conversion is required. */
3844: entry_parm = convert_to_mode (nominal_mode, entry_parm, 0);
3845:
3846: if (entry_parm != stack_parm)
3847: {
3848: if (stack_parm == 0)
3849: stack_parm = assign_stack_local (GET_MODE (entry_parm),
3850: GET_MODE_SIZE (GET_MODE (entry_parm)));
3851: emit_move_insn (stack_parm, entry_parm);
3852: }
3853:
3854: DECL_RTL (parm) = stack_parm;
3855: frame_pointer_needed = 1;
1.1 root 3856: }
1.1.1.2 root 3857:
3858: if (TREE_VOLATILE (parm))
1.1.1.10 root 3859: MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
1.1.1.2 root 3860: if (TREE_READONLY (parm))
1.1.1.10 root 3861: RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
1.1.1.2 root 3862:
3863: /* Update info on where next arg arrives in registers. */
3864:
3865: FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1);
1.1 root 3866: }
1.1.1.4 root 3867:
1.1 root 3868: max_parm_reg = max_reg_num ();
1.1.1.2 root 3869: last_parm_insn = get_last_insn ();
3870:
3871: current_function_args_size = stack_args_size.constant;
1.1 root 3872: }
3873:
3874: /* Allocation of space for returned structure values.
3875: During the rtl generation pass, `get_structure_value_addr'
3876: is called from time to time to request the address of a block in our
3877: stack frame in which called functions will store the structures
3878: they are returning. The same space is used for all of these blocks.
3879:
1.1.1.2 root 3880: We allocate these blocks like stack locals. We keep reusing
3881: the same block until a bigger one is needed. */
3882:
3883: /* Length in bytes of largest structure value returned by
3884: any function called so far in this function. */
3885: static int max_structure_value_size;
1.1 root 3886:
1.1.1.2 root 3887: /* An rtx for the addr we are currently using for structure values.
3888: This is typically (PLUS (REG:SI stackptr) (CONST_INT...)). */
3889: static rtx structure_value;
1.1 root 3890:
3891: rtx
3892: get_structure_value_addr (sizex)
3893: rtx sizex;
3894: {
3895: register int size;
3896: if (GET_CODE (sizex) != CONST_INT)
3897: abort ();
3898: size = INTVAL (sizex);
3899:
3900: /* Round up to a multiple of the main allocation unit. */
3901: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
3902: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT))
3903: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
3904:
1.1.1.2 root 3905: /* If this size is bigger than space we know to use,
3906: get a bigger piece of space. */
1.1 root 3907: if (size > max_structure_value_size)
3908: {
3909: max_structure_value_size = size;
1.1.1.2 root 3910: structure_value = assign_stack_local (BLKmode, size);
3911: if (GET_CODE (structure_value) == MEM)
3912: structure_value = XEXP (structure_value, 0);
1.1 root 3913: }
1.1.1.2 root 3914:
3915: return structure_value;
1.1 root 3916: }
1.1.1.2 root 3917:
3918: /* Walk the tree of LET_STMTs describing the binding levels within a function
3919: and warn about uninitialized variables.
3920: This is done after calling flow_analysis and before global_alloc
3921: clobbers the pseudo-regs to hard regs. */
1.1 root 3922:
1.1.1.2 root 3923: void
3924: uninitialized_vars_warning (block)
3925: tree block;
1.1 root 3926: {
1.1.1.2 root 3927: register tree decl, sub;
3928: for (decl = STMT_VARS (block); decl; decl = TREE_CHAIN (decl))
3929: {
3930: if (TREE_CODE (decl) == VAR_DECL
3931: /* These warnings are unreliable for and aggregates
3932: because assigning the fields one by one can fail to convince
3933: flow.c that the entire aggregate was initialized.
3934: Unions are troublesome because members may be shorter. */
3935: && TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
3936: && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE
3937: && TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE
3938: && GET_CODE (DECL_RTL (decl)) == REG
3939: && regno_uninitialized (REGNO (DECL_RTL (decl))))
3940: warning_with_decl (decl,
3941: "variable `%s' used uninitialized in this function");
3942: if (TREE_CODE (decl) == VAR_DECL
3943: && GET_CODE (DECL_RTL (decl)) == REG
3944: && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
3945: warning_with_decl (decl,
3946: "variable `%s' may be clobbered by `longjmp'");
3947: }
3948: for (sub = STMT_BODY (block); sub; sub = TREE_CHAIN (sub))
3949: uninitialized_vars_warning (sub);
1.1 root 3950: }
1.1.1.11 root 3951:
3952: /* If this function call setjmp, put all vars into the stack
3953: unless they were declared `register'. */
3954:
3955: void
3956: setjmp_protect (block)
3957: tree block;
3958: {
3959: register tree decl, sub;
3960: for (decl = STMT_VARS (block); decl; decl = TREE_CHAIN (decl))
3961: if ((TREE_CODE (decl) == VAR_DECL
3962: || TREE_CODE (decl) == PARM_DECL)
3963: && DECL_RTL (decl) != 0
3964: && GET_CODE (DECL_RTL (decl)) == REG
3965: && ! TREE_REGDECL (decl))
3966: put_var_into_stack (decl);
3967: for (sub = STMT_BODY (block); sub; sub = TREE_CHAIN (sub))
3968: setjmp_protect (sub);
3969: }
1.1 root 3970:
1.1.1.2 root 3971: /* Generate RTL for the start of the function FUNC (a FUNCTION_DECL tree node)
3972: and initialize static variables for generating RTL for the statements
3973: of the function. */
1.1 root 3974:
1.1.1.2 root 3975: void
3976: expand_function_start (subr)
1.1 root 3977: tree subr;
3978: {
3979: register int i;
1.1.1.2 root 3980: tree tem;
1.1 root 3981:
3982: this_function = subr;
1.1.1.2 root 3983: cse_not_expected = ! optimize;
3984:
3985: /* We have not yet found a reason why a frame pointer cannot
3986: be omitted for this function in particular, but maybe we know
3987: a priori that it is required.
3988: `flag_omit_frame_pointer' has its main effect here. */
3989: frame_pointer_needed = FRAME_POINTER_REQUIRED || ! flag_omit_frame_pointer;
1.1 root 3990:
1.1.1.2 root 3991: /* No gotos have been expanded yet. */
3992: goto_fixup_chain = 0;
1.1 root 3993:
1.1.1.13! root 3994: /* No stack slots have been made yet. */
! 3995: stack_slot_list = 0;
! 3996:
1.1.1.2 root 3997: /* No invalid stack slots have been made yet. */
3998: invalid_stack_slot = 0;
3999:
4000: /* Initialize the RTL mechanism. */
4001: init_emit (write_symbols);
4002:
4003: /* Initialize the queue of pending postincrement and postdecrements,
4004: and some other info in expr.c. */
4005: init_expr ();
4006:
4007: init_const_rtx_hash_table ();
4008:
4009: /* Decide whether function should try to pop its args on return. */
4010:
4011: current_function_pops_args = RETURN_POPS_ARGS (TREE_TYPE (subr));
4012:
4013: current_function_name = IDENTIFIER_POINTER (DECL_NAME (subr));
4014:
1.1.1.10 root 4015: /* Nonzero if this is a nested function that uses a static chain. */
4016:
1.1.1.13! root 4017: current_function_needs_context
! 4018: = (DECL_CONTEXT (current_function_decl) != 0
! 4019: && TREE_CODE (DECL_CONTEXT (current_function_decl)) == LET_STMT);
1.1.1.10 root 4020:
1.1.1.11 root 4021: /* Set if a call to setjmp is seen. */
4022:
4023: current_function_calls_setjmp = 0;
4024:
1.1.1.10 root 4025: /* Nonzero if this function needs an arg saying where to store value. */
4026: current_function_returns_struct
4027: = (DECL_MODE (DECL_RESULT (current_function_decl)) == BLKmode);
4028:
1.1.1.2 root 4029: /* Make the label for return statements to jump to, if this machine
4030: does not have a one-instruction return. */
1.1.1.8 root 4031: #ifdef HAVE_return
4032: if (HAVE_return)
4033: return_label = 0;
4034: else
4035: return_label = gen_label_rtx ();
1.1.1.2 root 4036: #else
1.1.1.8 root 4037: return_label = gen_label_rtx ();
1.1 root 4038: #endif
4039:
1.1.1.2 root 4040: /* No space assigned yet for structure values. */
1.1 root 4041: max_structure_value_size = 0;
1.1.1.2 root 4042: structure_value = 0;
1.1 root 4043:
1.1.1.2 root 4044: /* We are not currently within any block, conditional, loop or case. */
1.1 root 4045: block_stack = 0;
1.1.1.2 root 4046: loop_stack = 0;
4047: case_stack = 0;
4048: cond_stack = 0;
4049: nesting_stack = 0;
4050: nesting_depth = 0;
4051:
4052: /* We have not yet needed to make a label to jump to for tail-recursion. */
1.1 root 4053: tail_recursion_label = 0;
4054:
1.1.1.2 root 4055: /* No stack slots allocated yet. */
4056: frame_offset = STARTING_FRAME_OFFSET;
4057:
1.1.1.5 root 4058: /* No SAVE_EXPRs in this function yet. */
4059: save_expr_regs = 0;
4060:
1.1.1.10 root 4061: /* No RTL_EXPRs in this function yet. */
4062: rtl_expr_chain = 0;
4063:
1.1.1.4 root 4064: /* Within function body, compute a type's size as soon it is laid out. */
4065: immediate_size_expand++;
4066:
1.1.1.2 root 4067: init_pending_stack_adjust ();
1.1 root 4068: clear_current_args_size ();
1.1.1.7 root 4069: current_function_pretend_args_size = 0;
1.1 root 4070:
4071: /* Prevent ever trying to delete the first instruction of a function.
4072: Also tell final how to output a linenum before the function prologue. */
1.1.1.12 root 4073: emit_line_note (DECL_SOURCE_FILE (subr), DECL_SOURCE_LINE (subr));
1.1 root 4074: /* Make sure first insn is a note even if we don't want linenums.
4075: This makes sure the first insn will never be deleted.
4076: Also, final expects a note to appear there. */
4077: emit_note (0, NOTE_INSN_DELETED);
4078:
4079: /* Initialize rtx for parameters and local variables.
4080: In some cases this requires emitting insns. */
4081:
4082: assign_parms (subr);
1.1.1.2 root 4083:
1.1 root 4084: /* Initialize rtx used to return the value. */
4085:
4086: if (DECL_MODE (DECL_RESULT (subr)) == BLKmode)
4087: {
4088: /* Returning something that won't go in a register. */
4089: register rtx value_address;
4090:
1.1.1.2 root 4091: /* Expect to be passed the address of a place to store the value. */
1.1 root 4092: value_address = gen_reg_rtx (Pmode);
1.1.1.2 root 4093: emit_move_insn (value_address, struct_value_incoming_rtx);
1.1 root 4094: DECL_RTL (DECL_RESULT (subr))
4095: = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)),
4096: value_address);
4097: }
4098: else
1.1.1.2 root 4099: #ifdef FUNCTION_OUTGOING_VALUE
1.1 root 4100: DECL_RTL (DECL_RESULT (subr))
1.1.1.2 root 4101: = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
4102: #else
4103: DECL_RTL (DECL_RESULT (subr))
4104: = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
4105: #endif
1.1.1.6 root 4106:
4107: /* Mark this reg as the function's return value. */
4108: if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
4109: REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
1.1.1.8 root 4110:
1.1.1.10 root 4111: /* If doing stupid allocation, mark parms as born here. */
4112:
4113: if (obey_regdecls)
4114: {
4115: parm_birth_insn = get_last_insn ();
4116: for (i = FIRST_PSEUDO_REGISTER; i < max_parm_reg; i++)
4117: use_variable (regno_reg_rtx[i]);
4118: }
4119:
1.1.1.8 root 4120: /* After the parm initializations is where the tail-recursion label
4121: should go, if we end up needing one. */
4122: tail_recursion_reentry = get_last_insn ();
4123:
4124: /* Evaluate now the sizes of any types declared among the arguments. */
4125: for (tem = get_pending_sizes (); tem; tem = TREE_CHAIN (tem))
4126: expand_expr (TREE_VALUE (tem), 0, VOIDmode, 0);
1.1.1.2 root 4127: }
1.1 root 4128:
1.1.1.6 root 4129: /* Generate RTL for the end of the current function.
1.1.1.13! root 4130: FILENAME and LINE are the current position in the source file. */
1.1 root 4131:
1.1.1.2 root 4132: void
1.1.1.6 root 4133: expand_function_end (filename, line)
4134: char *filename;
4135: int line;
1.1.1.2 root 4136: {
4137: register int i;
1.1.1.13! root 4138: extern rtx sequence_stack;
! 4139:
! 4140: /* End any sequences that failed to be closed due to syntax errors. */
! 4141: while (sequence_stack)
! 4142: end_sequence (0);
1.1 root 4143:
1.1.1.4 root 4144: /* Outside function body, can't compute type's actual size
4145: until next function's body starts. */
4146: immediate_size_expand--;
4147:
1.1.1.13! root 4148: /* If returning a structure, arrange to return the address of the value
! 4149: in a place where debuggers expect to find it. */
! 4150: if (DECL_MODE (DECL_RESULT (current_function_decl)) == BLKmode)
! 4151: {
! 4152: rtx value_address = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
! 4153: tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
! 4154: rtx outgoing
! 4155: = hard_function_value (build_pointer_type (type),
! 4156: current_function_decl);
! 4157:
! 4158: emit_move_insn (outgoing, value_address);
! 4159: }
! 4160:
1.1 root 4161: /* If doing stupid register allocation,
1.1.1.2 root 4162: mark register parms as dying here. */
4163:
1.1 root 4164: if (obey_regdecls)
1.1.1.5 root 4165: {
4166: rtx tem;
4167: for (i = FIRST_PSEUDO_REGISTER; i < max_parm_reg; i++)
4168: use_variable (regno_reg_rtx[i]);
4169:
4170: /* Likewise for the regs of all the SAVE_EXPRs in the function. */
4171:
4172: for (tem = save_expr_regs; tem; tem = XEXP (tem, 1))
1.1.1.13! root 4173: {
! 4174: /* ??? Tiemann thinks this does not work. */
! 4175: use_variable (XEXP (tem, 0));
! 4176: use_variable_after (XEXP (tem, 0), parm_birth_insn);
! 4177: }
1.1.1.5 root 4178: }
1.1 root 4179:
4180: clear_pending_stack_adjust ();
1.1.1.2 root 4181: do_pending_stack_adjust ();
1.1 root 4182:
1.1.1.2 root 4183: /* Mark the end of the function body.
4184: If control reaches this insn, the function can drop through
4185: without returning a value. */
4186: emit_note (0, NOTE_INSN_FUNCTION_END);
4187:
1.1.1.6 root 4188: /* Output a linenumber for the end of the function.
4189: SDB depends on this. */
1.1.1.13! root 4190: emit_line_note_force (filename, line);
1.1.1.6 root 4191:
1.1.1.2 root 4192: /* If we require a true epilogue,
4193: put here the label that return statements jump to.
4194: If there will be no epilogue, write a return instruction. */
1.1.1.8 root 4195: #ifdef HAVE_return
4196: if (HAVE_return)
4197: emit_jump_insn (gen_return ());
4198: else
1.1 root 4199: #endif
1.1.1.8 root 4200: emit_label (return_label);
1.1.1.6 root 4201:
4202: /* Fix up any gotos that jumped out to the outermost
4203: binding level of the function.
4204: Must follow emitting RETURN_LABEL. */
1.1.1.8 root 4205:
4206: /* If you have any cleanups to do at this point,
4207: and they need to create temporary variables,
4208: then you will lose. */
1.1.1.7 root 4209: fixup_gotos (0, 0, get_insns (), 0);
1.1 root 4210: }
1.1.1.6 root 4211:
4212:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.