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