|
|
1.1 root 1: /* Expands front end tree to back end RTL for GNU C-Compiler
1.1.1.8 root 2: Copyright (C) 1987, 88, 89, 91-94, 1995 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
1.1.1.8 root 18: the Free Software Foundation, 59 Temple Place - Suite 330,
19: Boston, MA 02111-1307, USA. */
1.1 root 20:
21:
22: /* This file handles the generation of rtl code from tree structure
23: at the level of the function as a whole.
24: It creates the rtl expressions for parameters and auto variables
25: and has full responsibility for allocating stack slots.
26:
27: `expand_function_start' is called at the beginning of a function,
28: before the function body is parsed, and `expand_function_end' is
29: called after parsing the body.
30:
31: Call `assign_stack_local' to allocate a stack slot for a local variable.
32: This is usually done during the RTL generation for the function body,
33: but it can also be done in the reload pass when a pseudo-register does
34: not get a hard register.
35:
36: Call `put_var_into_stack' when you learn, belatedly, that a variable
37: previously given a pseudo-register must in fact go in the stack.
38: This function changes the DECL_RTL to be a stack slot instead of a reg
39: then scans all the RTL instructions so far generated to correct them. */
40:
41: #include "config.h"
42:
43: #include <stdio.h>
44:
45: #include "rtl.h"
46: #include "tree.h"
47: #include "flags.h"
48: #include "function.h"
49: #include "insn-flags.h"
50: #include "expr.h"
51: #include "insn-codes.h"
52: #include "regs.h"
53: #include "hard-reg-set.h"
54: #include "insn-config.h"
55: #include "recog.h"
56: #include "output.h"
1.1.1.4 root 57: #include "basic-block.h"
1.1.1.6 root 58: #include "obstack.h"
59: #include "bytecode.h"
60:
61: /* Some systems use __main in a way incompatible with its use in gcc, in these
62: cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
63: give the same symbol without quotes for an alternative entry point. You
1.1.1.8 root 64: must define both, or neither. */
1.1.1.6 root 65: #ifndef NAME__MAIN
66: #define NAME__MAIN "__main"
67: #define SYMBOL__MAIN __main
68: #endif
1.1 root 69:
70: /* Round a value to the lowest integer less than it that is a multiple of
71: the required alignment. Avoid using division in case the value is
72: negative. Assume the alignment is a power of two. */
73: #define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
74:
75: /* Similar, but round to the next highest integer that meets the
76: alignment. */
77: #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
78:
79: /* NEED_SEPARATE_AP means that we cannot derive ap from the value of fp
80: during rtl generation. If they are different register numbers, this is
81: always true. It may also be true if
82: FIRST_PARM_OFFSET - STARTING_FRAME_OFFSET is not a constant during rtl
83: generation. See fix_lexical_addr for details. */
84:
85: #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
86: #define NEED_SEPARATE_AP
87: #endif
88:
89: /* Number of bytes of args popped by function being compiled on its return.
90: Zero if no bytes are to be popped.
91: May affect compilation of return insn or of function epilogue. */
92:
93: int current_function_pops_args;
94:
95: /* Nonzero if function being compiled needs to be given an address
96: where the value should be stored. */
97:
98: int current_function_returns_struct;
99:
100: /* Nonzero if function being compiled needs to
101: return the address of where it has put a structure value. */
102:
103: int current_function_returns_pcc_struct;
104:
105: /* Nonzero if function being compiled needs to be passed a static chain. */
106:
107: int current_function_needs_context;
108:
109: /* Nonzero if function being compiled can call setjmp. */
110:
111: int current_function_calls_setjmp;
112:
113: /* Nonzero if function being compiled can call longjmp. */
114:
115: int current_function_calls_longjmp;
116:
117: /* Nonzero if function being compiled receives nonlocal gotos
118: from nested functions. */
119:
120: int current_function_has_nonlocal_label;
121:
1.1.1.6 root 122: /* Nonzero if function being compiled has nonlocal gotos to parent
123: function. */
124:
125: int current_function_has_nonlocal_goto;
126:
1.1 root 127: /* Nonzero if function being compiled contains nested functions. */
128:
129: int current_function_contains_functions;
130:
131: /* Nonzero if function being compiled can call alloca,
132: either as a subroutine or builtin. */
133:
134: int current_function_calls_alloca;
135:
136: /* Nonzero if the current function returns a pointer type */
137:
138: int current_function_returns_pointer;
139:
140: /* If some insns can be deferred to the delay slots of the epilogue, the
141: delay list for them is recorded here. */
142:
143: rtx current_function_epilogue_delay_list;
144:
145: /* If function's args have a fixed size, this is that size, in bytes.
146: Otherwise, it is -1.
147: May affect compilation of return insn or of function epilogue. */
148:
149: int current_function_args_size;
150:
151: /* # bytes the prologue should push and pretend that the caller pushed them.
152: The prologue must do this, but only if parms can be passed in registers. */
153:
154: int current_function_pretend_args_size;
155:
1.1.1.7 root 156: /* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
157: defined, the needed space is pushed by the prologue. */
1.1 root 158:
159: int current_function_outgoing_args_size;
160:
161: /* This is the offset from the arg pointer to the place where the first
162: anonymous arg can be found, if there is one. */
163:
164: rtx current_function_arg_offset_rtx;
165:
166: /* Nonzero if current function uses varargs.h or equivalent.
167: Zero for functions that use stdarg.h. */
168:
169: int current_function_varargs;
170:
1.1.1.8 root 171: /* Nonzero if current function uses stdarg.h or equivalent.
172: Zero for functions that use varargs.h. */
173:
174: int current_function_stdarg;
175:
1.1 root 176: /* Quantities of various kinds of registers
177: used for the current function's args. */
178:
179: CUMULATIVE_ARGS current_function_args_info;
180:
181: /* Name of function now being compiled. */
182:
183: char *current_function_name;
184:
185: /* If non-zero, an RTL expression for that location at which the current
186: function returns its result. Always equal to
187: DECL_RTL (DECL_RESULT (current_function_decl)), but provided
188: independently of the tree structures. */
189:
190: rtx current_function_return_rtx;
191:
192: /* Nonzero if the current function uses the constant pool. */
193:
194: int current_function_uses_const_pool;
195:
196: /* Nonzero if the current function uses pic_offset_table_rtx. */
197: int current_function_uses_pic_offset_table;
198:
199: /* The arg pointer hard register, or the pseudo into which it was copied. */
200: rtx current_function_internal_arg_pointer;
201:
202: /* The FUNCTION_DECL for an inline function currently being expanded. */
203: tree inline_function_decl;
204:
205: /* Number of function calls seen so far in current function. */
206:
207: int function_call_count;
208:
209: /* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels
210: (labels to which there can be nonlocal gotos from nested functions)
211: in this function. */
212:
213: tree nonlocal_labels;
214:
215: /* RTX for stack slot that holds the current handler for nonlocal gotos.
216: Zero when function does not have nonlocal labels. */
217:
218: rtx nonlocal_goto_handler_slot;
219:
220: /* RTX for stack slot that holds the stack pointer value to restore
221: for a nonlocal goto.
222: Zero when function does not have nonlocal labels. */
223:
224: rtx nonlocal_goto_stack_level;
225:
226: /* Label that will go on parm cleanup code, if any.
227: Jumping to this label runs cleanup code for parameters, if
228: such code must be run. Following this code is the logical return label. */
229:
230: rtx cleanup_label;
231:
232: /* Label that will go on function epilogue.
233: Jumping to this label serves as a "return" instruction
234: on machines which require execution of the epilogue on all returns. */
235:
236: rtx return_label;
237:
238: /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
239: So we can mark them all live at the end of the function, if nonopt. */
240: rtx save_expr_regs;
241:
242: /* List (chain of EXPR_LISTs) of all stack slots in this function.
243: Made for the sake of unshare_all_rtl. */
244: rtx stack_slot_list;
245:
246: /* Chain of all RTL_EXPRs that have insns in them. */
247: tree rtl_expr_chain;
248:
249: /* Label to jump back to for tail recursion, or 0 if we have
250: not yet needed one for this function. */
251: rtx tail_recursion_label;
252:
253: /* Place after which to insert the tail_recursion_label if we need one. */
254: rtx tail_recursion_reentry;
255:
256: /* Location at which to save the argument pointer if it will need to be
257: referenced. There are two cases where this is done: if nonlocal gotos
258: exist, or if vars stored at an offset from the argument pointer will be
259: needed by inner routines. */
260:
261: rtx arg_pointer_save_area;
262:
263: /* Offset to end of allocated area of stack frame.
264: If stack grows down, this is the address of the last stack slot allocated.
265: If stack grows up, this is the address for the next slot. */
266: int frame_offset;
267:
268: /* List (chain of TREE_LISTs) of static chains for containing functions.
269: Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
270: in an RTL_EXPR in the TREE_VALUE. */
271: static tree context_display;
272:
273: /* List (chain of TREE_LISTs) of trampolines for nested functions.
274: The trampoline sets up the static chain and jumps to the function.
275: We supply the trampoline's address when the function's address is requested.
276:
277: Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
278: in an RTL_EXPR in the TREE_VALUE. */
279: static tree trampoline_list;
280:
281: /* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */
282: static rtx parm_birth_insn;
283:
284: #if 0
285: /* Nonzero if a stack slot has been generated whose address is not
286: actually valid. It means that the generated rtl must all be scanned
287: to detect and correct the invalid addresses where they occur. */
288: static int invalid_stack_slot;
289: #endif
290:
291: /* Last insn of those whose job was to put parms into their nominal homes. */
292: static rtx last_parm_insn;
293:
294: /* 1 + last pseudo register number used for loading a copy
295: of a parameter of this function. */
296: static int max_parm_reg;
297:
298: /* Vector indexed by REGNO, containing location on stack in which
299: to put the parm which is nominally in pseudo register REGNO,
300: if we discover that that parm must go in the stack. */
301: static rtx *parm_reg_stack_loc;
302:
303: #if 0 /* Turned off because 0 seems to work just as well. */
304: /* Cleanup lists are required for binding levels regardless of whether
305: that binding level has cleanups or not. This node serves as the
306: cleanup list whenever an empty list is required. */
307: static tree empty_cleanup_list;
308: #endif
309:
310: /* Nonzero once virtual register instantiation has been done.
311: assign_stack_local uses frame_pointer_rtx when this is nonzero. */
312: static int virtuals_instantiated;
313:
1.1.1.6 root 314: /* These variables hold pointers to functions to
315: save and restore machine-specific data,
316: in push_function_context and pop_function_context. */
317: void (*save_machine_status) ();
318: void (*restore_machine_status) ();
319:
1.1 root 320: /* Nonzero if we need to distinguish between the return value of this function
321: and the return value of a function called by this function. This helps
322: integrate.c */
323:
324: extern int rtx_equal_function_value_matters;
1.1.1.6 root 325: extern tree sequence_rtl_expr;
326: extern tree bc_runtime_type_code ();
327: extern rtx bc_build_calldesc ();
328: extern char *bc_emit_trampoline ();
329: extern char *bc_end_function ();
1.1 root 330:
331: /* In order to evaluate some expressions, such as function calls returning
332: structures in memory, we need to temporarily allocate stack locations.
333: We record each allocated temporary in the following structure.
334:
335: Associated with each temporary slot is a nesting level. When we pop up
336: one level, all temporaries associated with the previous level are freed.
337: Normally, all temporaries are freed after the execution of the statement
338: in which they were created. However, if we are inside a ({...}) grouping,
339: the result may be in a temporary and hence must be preserved. If the
340: result could be in a temporary, we preserve it if we can determine which
341: one it is in. If we cannot determine which temporary may contain the
342: result, all temporaries are preserved. A temporary is preserved by
343: pretending it was allocated at the previous nesting level.
344:
345: Automatic variables are also assigned temporary slots, at the nesting
346: level where they are defined. They are marked a "kept" so that
347: free_temp_slots will not free them. */
348:
349: struct temp_slot
350: {
351: /* Points to next temporary slot. */
352: struct temp_slot *next;
353: /* The rtx to used to reference the slot. */
354: rtx slot;
1.1.1.7 root 355: /* The rtx used to represent the address if not the address of the
356: slot above. May be an EXPR_LIST if multiple addresses exist. */
357: rtx address;
1.1 root 358: /* The size, in units, of the slot. */
359: int size;
1.1.1.6 root 360: /* The value of `sequence_rtl_expr' when this temporary is allocated. */
361: tree rtl_expr;
1.1 root 362: /* Non-zero if this temporary is currently in use. */
363: char in_use;
1.1.1.7 root 364: /* Non-zero if this temporary has its address taken. */
365: char addr_taken;
1.1 root 366: /* Nesting level at which this slot is being used. */
367: int level;
368: /* Non-zero if this should survive a call to free_temp_slots. */
369: int keep;
1.1.1.8 root 370: /* The offset of the slot from the frame_pointer, including extra space
371: for alignment. This info is for combine_temp_slots. */
372: int base_offset;
373: /* The size of the slot, including extra space for alignment. This
374: info is for combine_temp_slots. */
375: int full_size;
1.1 root 376: };
377:
378: /* List of all temporaries allocated, both available and in use. */
379:
380: struct temp_slot *temp_slots;
381:
382: /* Current nesting level for temporaries. */
383:
384: int temp_slot_level;
385:
1.1.1.6 root 386: /* The FUNCTION_DECL node for the current function. */
387: static tree this_function_decl;
388:
389: /* Callinfo pointer for the current function. */
390: static rtx this_function_callinfo;
391:
392: /* The label in the bytecode file of this function's actual bytecode.
393: Not an rtx. */
394: static char *this_function_bytecode;
395:
396: /* The call description vector for the current function. */
397: static rtx this_function_calldesc;
398:
399: /* Size of the local variables allocated for the current function. */
400: int local_vars_size;
401:
402: /* Current depth of the bytecode evaluation stack. */
403: int stack_depth;
404:
405: /* Maximum depth of the evaluation stack in this function. */
406: int max_stack_depth;
407:
408: /* Current depth in statement expressions. */
409: static int stmt_expr_depth;
1.1.1.7 root 410:
411: /* This structure is used to record MEMs or pseudos used to replace VAR, any
412: SUBREGs of VAR, and any MEMs containing VAR as an address. We need to
413: maintain this list in case two operands of an insn were required to match;
414: in that case we must ensure we use the same replacement. */
415:
416: struct fixup_replacement
417: {
418: rtx old;
419: rtx new;
420: struct fixup_replacement *next;
421: };
422:
423: /* Forward declarations. */
424:
425: static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
426: static void put_reg_into_stack PROTO((struct function *, rtx, tree,
1.1.1.8 root 427: enum machine_mode, enum machine_mode,
428: int));
1.1.1.7 root 429: static void fixup_var_refs PROTO((rtx, enum machine_mode, int));
430: static struct fixup_replacement
431: *find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
432: static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
433: rtx, int));
434: static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx,
435: struct fixup_replacement **));
436: static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
437: static rtx walk_fixup_memory_subreg PROTO((rtx, rtx, int));
438: static rtx fixup_stack_1 PROTO((rtx, rtx));
439: static void optimize_bit_field PROTO((rtx, rtx, rtx *));
440: static void instantiate_decls PROTO((tree, int));
441: static void instantiate_decls_1 PROTO((tree, int));
442: static void instantiate_decl PROTO((rtx, int, int));
443: static int instantiate_virtual_regs_1 PROTO((rtx *, rtx, int));
444: static void delete_handlers PROTO((void));
445: static void pad_to_arg_alignment PROTO((struct args_size *, int));
446: static void pad_below PROTO((struct args_size *, enum machine_mode,
447: tree));
448: static tree round_down PROTO((tree, int));
449: static rtx round_trampoline_addr PROTO((rtx));
450: static tree blocks_nreverse PROTO((tree));
451: static int all_blocks PROTO((tree, tree *));
452: static int *record_insns PROTO((rtx));
453: static int contains PROTO((rtx, int *));
1.1.1.6 root 454:
1.1 root 455: /* Pointer to chain of `struct function' for containing functions. */
456: struct function *outer_function_chain;
457:
458: /* Given a function decl for a containing function,
459: return the `struct function' for it. */
460:
461: struct function *
462: find_function_data (decl)
463: tree decl;
464: {
465: struct function *p;
466: for (p = outer_function_chain; p; p = p->next)
467: if (p->decl == decl)
468: return p;
469: abort ();
470: }
471:
472: /* Save the current context for compilation of a nested function.
473: This is called from language-specific code.
474: The caller is responsible for saving any language-specific status,
1.1.1.3 root 475: since this function knows only about language-independent variables. */
1.1 root 476:
477: void
1.1.1.8 root 478: push_function_context_to (context)
479: tree context;
1.1 root 480: {
481: struct function *p = (struct function *) xmalloc (sizeof (struct function));
482:
483: p->next = outer_function_chain;
484: outer_function_chain = p;
485:
486: p->name = current_function_name;
487: p->decl = current_function_decl;
488: p->pops_args = current_function_pops_args;
489: p->returns_struct = current_function_returns_struct;
490: p->returns_pcc_struct = current_function_returns_pcc_struct;
491: p->needs_context = current_function_needs_context;
492: p->calls_setjmp = current_function_calls_setjmp;
493: p->calls_longjmp = current_function_calls_longjmp;
494: p->calls_alloca = current_function_calls_alloca;
495: p->has_nonlocal_label = current_function_has_nonlocal_label;
1.1.1.6 root 496: p->has_nonlocal_goto = current_function_has_nonlocal_goto;
1.1.1.8 root 497: p->contains_functions = current_function_contains_functions;
1.1 root 498: p->args_size = current_function_args_size;
499: p->pretend_args_size = current_function_pretend_args_size;
500: p->arg_offset_rtx = current_function_arg_offset_rtx;
1.1.1.7 root 501: p->varargs = current_function_varargs;
1.1.1.8 root 502: p->stdarg = current_function_stdarg;
1.1 root 503: p->uses_const_pool = current_function_uses_const_pool;
504: p->uses_pic_offset_table = current_function_uses_pic_offset_table;
505: p->internal_arg_pointer = current_function_internal_arg_pointer;
506: p->max_parm_reg = max_parm_reg;
507: p->parm_reg_stack_loc = parm_reg_stack_loc;
508: p->outgoing_args_size = current_function_outgoing_args_size;
509: p->return_rtx = current_function_return_rtx;
510: p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
511: p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
512: p->nonlocal_labels = nonlocal_labels;
513: p->cleanup_label = cleanup_label;
514: p->return_label = return_label;
515: p->save_expr_regs = save_expr_regs;
516: p->stack_slot_list = stack_slot_list;
517: p->parm_birth_insn = parm_birth_insn;
518: p->frame_offset = frame_offset;
519: p->tail_recursion_label = tail_recursion_label;
520: p->tail_recursion_reentry = tail_recursion_reentry;
521: p->arg_pointer_save_area = arg_pointer_save_area;
522: p->rtl_expr_chain = rtl_expr_chain;
523: p->last_parm_insn = last_parm_insn;
524: p->context_display = context_display;
525: p->trampoline_list = trampoline_list;
526: p->function_call_count = function_call_count;
527: p->temp_slots = temp_slots;
528: p->temp_slot_level = temp_slot_level;
529: p->fixup_var_refs_queue = 0;
1.1.1.4 root 530: p->epilogue_delay_list = current_function_epilogue_delay_list;
1.1 root 531:
1.1.1.8 root 532: save_tree_status (p, context);
1.1 root 533: save_storage_status (p);
534: save_emit_status (p);
535: init_emit ();
536: save_expr_status (p);
537: save_stmt_status (p);
1.1.1.4 root 538: save_varasm_status (p);
1.1.1.6 root 539:
540: if (save_machine_status)
541: (*save_machine_status) (p);
1.1 root 542: }
543:
1.1.1.7 root 544: void
545: push_function_context ()
546: {
1.1.1.8 root 547: push_function_context_to (current_function_decl);
1.1.1.7 root 548: }
549:
1.1 root 550: /* Restore the last saved context, at the end of a nested function.
551: This function is called from language-specific code. */
552:
553: void
1.1.1.8 root 554: pop_function_context_from (context)
555: tree context;
1.1 root 556: {
557: struct function *p = outer_function_chain;
558:
559: outer_function_chain = p->next;
560:
1.1.1.8 root 561: current_function_contains_functions
562: = p->contains_functions || p->inline_obstacks
563: || context == current_function_decl;
1.1 root 564: current_function_name = p->name;
565: current_function_decl = p->decl;
566: current_function_pops_args = p->pops_args;
567: current_function_returns_struct = p->returns_struct;
568: current_function_returns_pcc_struct = p->returns_pcc_struct;
569: current_function_needs_context = p->needs_context;
570: current_function_calls_setjmp = p->calls_setjmp;
571: current_function_calls_longjmp = p->calls_longjmp;
572: current_function_calls_alloca = p->calls_alloca;
573: current_function_has_nonlocal_label = p->has_nonlocal_label;
1.1.1.6 root 574: current_function_has_nonlocal_goto = p->has_nonlocal_goto;
1.1 root 575: current_function_args_size = p->args_size;
576: current_function_pretend_args_size = p->pretend_args_size;
577: current_function_arg_offset_rtx = p->arg_offset_rtx;
1.1.1.7 root 578: current_function_varargs = p->varargs;
1.1.1.8 root 579: current_function_stdarg = p->stdarg;
1.1 root 580: current_function_uses_const_pool = p->uses_const_pool;
581: current_function_uses_pic_offset_table = p->uses_pic_offset_table;
582: current_function_internal_arg_pointer = p->internal_arg_pointer;
583: max_parm_reg = p->max_parm_reg;
584: parm_reg_stack_loc = p->parm_reg_stack_loc;
585: current_function_outgoing_args_size = p->outgoing_args_size;
586: current_function_return_rtx = p->return_rtx;
587: nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
588: nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
589: nonlocal_labels = p->nonlocal_labels;
590: cleanup_label = p->cleanup_label;
591: return_label = p->return_label;
592: save_expr_regs = p->save_expr_regs;
593: stack_slot_list = p->stack_slot_list;
594: parm_birth_insn = p->parm_birth_insn;
595: frame_offset = p->frame_offset;
596: tail_recursion_label = p->tail_recursion_label;
597: tail_recursion_reentry = p->tail_recursion_reentry;
598: arg_pointer_save_area = p->arg_pointer_save_area;
599: rtl_expr_chain = p->rtl_expr_chain;
600: last_parm_insn = p->last_parm_insn;
601: context_display = p->context_display;
602: trampoline_list = p->trampoline_list;
603: function_call_count = p->function_call_count;
604: temp_slots = p->temp_slots;
605: temp_slot_level = p->temp_slot_level;
1.1.1.4 root 606: current_function_epilogue_delay_list = p->epilogue_delay_list;
1.1.1.7 root 607: reg_renumber = 0;
1.1 root 608:
1.1.1.8 root 609: restore_tree_status (p);
1.1 root 610: restore_storage_status (p);
611: restore_expr_status (p);
612: restore_emit_status (p);
613: restore_stmt_status (p);
1.1.1.4 root 614: restore_varasm_status (p);
1.1 root 615:
1.1.1.6 root 616: if (restore_machine_status)
617: (*restore_machine_status) (p);
618:
1.1 root 619: /* Finish doing put_var_into_stack for any of our variables
620: which became addressable during the nested function. */
621: {
622: struct var_refs_queue *queue = p->fixup_var_refs_queue;
623: for (; queue; queue = queue->next)
1.1.1.4 root 624: fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
1.1 root 625: }
626:
627: free (p);
628:
629: /* Reset variables that have known state during rtx generation. */
630: rtx_equal_function_value_matters = 1;
631: virtuals_instantiated = 0;
632: }
1.1.1.7 root 633:
634: void pop_function_context ()
635: {
1.1.1.8 root 636: pop_function_context_from (current_function_decl);
1.1.1.7 root 637: }
1.1 root 638:
639: /* Allocate fixed slots in the stack frame of the current function. */
640:
641: /* Return size needed for stack frame based on slots so far allocated.
642: This size counts from zero. It is not rounded to STACK_BOUNDARY;
643: the caller may have to do that. */
644:
645: int
646: get_frame_size ()
647: {
648: #ifdef FRAME_GROWS_DOWNWARD
649: return -frame_offset;
650: #else
651: return frame_offset;
652: #endif
653: }
654:
655: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
656: with machine mode MODE.
657:
658: ALIGN controls the amount of alignment for the address of the slot:
659: 0 means according to MODE,
660: -1 means use BIGGEST_ALIGNMENT and round size to multiple of that,
661: positive specifies alignment boundary in bits.
662:
663: We do not round to stack_boundary here. */
664:
665: rtx
666: assign_stack_local (mode, size, align)
667: enum machine_mode mode;
668: int size;
669: int align;
670: {
671: register rtx x, addr;
672: int bigend_correction = 0;
673: int alignment;
674:
675: if (align == 0)
676: {
677: alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
678: if (mode == BLKmode)
679: alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
680: }
681: else if (align == -1)
682: {
683: alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
684: size = CEIL_ROUND (size, alignment);
685: }
686: else
687: alignment = align / BITS_PER_UNIT;
688:
689: /* Round frame offset to that alignment.
690: We must be careful here, since FRAME_OFFSET might be negative and
691: division with a negative dividend isn't as well defined as we might
692: like. So we instead assume that ALIGNMENT is a power of two and
693: use logical operations which are unambiguous. */
694: #ifdef FRAME_GROWS_DOWNWARD
695: frame_offset = FLOOR_ROUND (frame_offset, alignment);
696: #else
697: frame_offset = CEIL_ROUND (frame_offset, alignment);
698: #endif
699:
700: /* On a big-endian machine, if we are allocating more space than we will use,
701: use the least significant bytes of those that are allocated. */
1.1.1.8 root 702: if (BYTES_BIG_ENDIAN && mode != BLKmode)
1.1 root 703: bigend_correction = size - GET_MODE_SIZE (mode);
704:
705: #ifdef FRAME_GROWS_DOWNWARD
706: frame_offset -= size;
707: #endif
708:
709: /* If we have already instantiated virtual registers, return the actual
710: address relative to the frame pointer. */
711: if (virtuals_instantiated)
712: addr = plus_constant (frame_pointer_rtx,
713: (frame_offset + bigend_correction
714: + STARTING_FRAME_OFFSET));
715: else
716: addr = plus_constant (virtual_stack_vars_rtx,
717: frame_offset + bigend_correction);
718:
719: #ifndef FRAME_GROWS_DOWNWARD
720: frame_offset += size;
721: #endif
722:
723: x = gen_rtx (MEM, mode, addr);
724:
725: stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, x, stack_slot_list);
726:
727: return x;
728: }
729:
730: /* Assign a stack slot in a containing function.
731: First three arguments are same as in preceding function.
732: The last argument specifies the function to allocate in. */
733:
734: rtx
735: assign_outer_stack_local (mode, size, align, function)
736: enum machine_mode mode;
737: int size;
738: int align;
739: struct function *function;
740: {
741: register rtx x, addr;
742: int bigend_correction = 0;
743: int alignment;
744:
745: /* Allocate in the memory associated with the function in whose frame
746: we are assigning. */
747: push_obstacks (function->function_obstack,
748: function->function_maybepermanent_obstack);
749:
750: if (align == 0)
751: {
752: alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
753: if (mode == BLKmode)
754: alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
755: }
756: else if (align == -1)
757: {
758: alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
759: size = CEIL_ROUND (size, alignment);
760: }
761: else
762: alignment = align / BITS_PER_UNIT;
763:
764: /* Round frame offset to that alignment. */
765: #ifdef FRAME_GROWS_DOWNWARD
1.1.1.4 root 766: function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);
1.1 root 767: #else
1.1.1.4 root 768: function->frame_offset = CEIL_ROUND (function->frame_offset, alignment);
1.1 root 769: #endif
770:
771: /* On a big-endian machine, if we are allocating more space than we will use,
772: use the least significant bytes of those that are allocated. */
1.1.1.8 root 773: if (BYTES_BIG_ENDIAN && mode != BLKmode)
1.1 root 774: bigend_correction = size - GET_MODE_SIZE (mode);
775:
776: #ifdef FRAME_GROWS_DOWNWARD
777: function->frame_offset -= size;
778: #endif
779: addr = plus_constant (virtual_stack_vars_rtx,
780: function->frame_offset + bigend_correction);
781: #ifndef FRAME_GROWS_DOWNWARD
782: function->frame_offset += size;
783: #endif
784:
785: x = gen_rtx (MEM, mode, addr);
786:
787: function->stack_slot_list
788: = gen_rtx (EXPR_LIST, VOIDmode, x, function->stack_slot_list);
789:
790: pop_obstacks ();
791:
792: return x;
793: }
794:
795: /* Allocate a temporary stack slot and record it for possible later
796: reuse.
797:
798: MODE is the machine mode to be given to the returned rtx.
799:
800: SIZE is the size in units of the space required. We do no rounding here
801: since assign_stack_local will do any required rounding.
802:
1.1.1.7 root 803: KEEP is 1 if this slot is to be retained after a call to
804: free_temp_slots. Automatic variables for a block are allocated
805: with this flag. KEEP is 2, if we allocate a longer term temporary,
806: whose lifetime is controlled by CLEANUP_POINT_EXPRs. */
1.1 root 807:
808: rtx
809: assign_stack_temp (mode, size, keep)
810: enum machine_mode mode;
811: int size;
812: int keep;
813: {
814: struct temp_slot *p, *best_p = 0;
815:
1.1.1.7 root 816: /* If SIZE is -1 it means that somebody tried to allocate a temporary
817: of a variable size. */
818: if (size == -1)
819: abort ();
820:
1.1 root 821: /* First try to find an available, already-allocated temporary that is the
822: exact size we require. */
823: for (p = temp_slots; p; p = p->next)
824: if (p->size == size && GET_MODE (p->slot) == mode && ! p->in_use)
825: break;
826:
827: /* If we didn't find, one, try one that is larger than what we want. We
828: find the smallest such. */
829: if (p == 0)
830: for (p = temp_slots; p; p = p->next)
831: if (p->size > size && GET_MODE (p->slot) == mode && ! p->in_use
832: && (best_p == 0 || best_p->size > p->size))
833: best_p = p;
834:
835: /* Make our best, if any, the one to use. */
836: if (best_p)
1.1.1.6 root 837: {
838: /* If there are enough aligned bytes left over, make them into a new
839: temp_slot so that the extra bytes don't get wasted. Do this only
840: for BLKmode slots, so that we can be sure of the alignment. */
841: if (GET_MODE (best_p->slot) == BLKmode)
842: {
843: int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
844: int rounded_size = CEIL_ROUND (size, alignment);
845:
846: if (best_p->size - rounded_size >= alignment)
847: {
848: p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
1.1.1.7 root 849: p->in_use = p->addr_taken = 0;
1.1.1.6 root 850: p->size = best_p->size - rounded_size;
1.1.1.8 root 851: p->base_offset = best_p->base_offset + rounded_size;
852: p->full_size = best_p->full_size - rounded_size;
1.1.1.6 root 853: p->slot = gen_rtx (MEM, BLKmode,
854: plus_constant (XEXP (best_p->slot, 0),
855: rounded_size));
1.1.1.7 root 856: p->address = 0;
857: p->rtl_expr = 0;
1.1.1.6 root 858: p->next = temp_slots;
859: temp_slots = p;
860:
861: stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, p->slot,
862: stack_slot_list);
863:
864: best_p->size = rounded_size;
1.1.1.8 root 865: best_p->full_size = rounded_size;
1.1.1.6 root 866: }
867: }
868:
869: p = best_p;
870: }
871:
1.1 root 872: /* If we still didn't find one, make a new temporary. */
873: if (p == 0)
874: {
1.1.1.8 root 875: int frame_offset_old = frame_offset;
1.1 root 876: p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
877: /* If the temp slot mode doesn't indicate the alignment,
878: use the largest possible, so no one will be disappointed. */
1.1.1.7 root 879: p->slot = assign_stack_local (mode, size, mode == BLKmode ? -1 : 0);
1.1.1.8 root 880: /* The following slot size computation is necessary because we don't
881: know the actual size of the temporary slot until assign_stack_local
882: has performed all the frame alignment and size rounding for the
883: requested temporary. Note that extra space added for alignment
884: can be either above or below this stack slot depending on which
885: way the frame grows. We include the extra space if and only if it
886: is above this slot. */
887: #ifdef FRAME_GROWS_DOWNWARD
888: p->size = frame_offset_old - frame_offset;
889: #else
890: p->size = size;
891: #endif
892: /* Now define the fields used by combine_temp_slots. */
893: #ifdef FRAME_GROWS_DOWNWARD
894: p->base_offset = frame_offset;
895: p->full_size = frame_offset_old - frame_offset;
896: #else
897: p->base_offset = frame_offset_old;
898: p->full_size = frame_offset - frame_offset_old;
899: #endif
1.1.1.7 root 900: p->address = 0;
1.1 root 901: p->next = temp_slots;
902: temp_slots = p;
903: }
904:
905: p->in_use = 1;
1.1.1.7 root 906: p->addr_taken = 0;
1.1.1.6 root 907: p->rtl_expr = sequence_rtl_expr;
1.1.1.7 root 908:
909: if (keep == 2)
910: {
911: p->level = target_temp_slot_level;
912: p->keep = 0;
913: }
914: else
915: {
916: p->level = temp_slot_level;
917: p->keep = keep;
918: }
1.1 root 919: return p->slot;
920: }
1.1.1.6 root 921:
922: /* Combine temporary stack slots which are adjacent on the stack.
923:
924: This allows for better use of already allocated stack space. This is only
925: done for BLKmode slots because we can be sure that we won't have alignment
926: problems in this case. */
927:
928: void
929: combine_temp_slots ()
930: {
931: struct temp_slot *p, *q;
932: struct temp_slot *prev_p, *prev_q;
933: /* Determine where to free back to after this function. */
934: rtx free_pointer = rtx_alloc (CONST_INT);
935:
936: for (p = temp_slots, prev_p = 0; p; p = prev_p ? prev_p->next : temp_slots)
937: {
938: int delete_p = 0;
939: if (! p->in_use && GET_MODE (p->slot) == BLKmode)
940: for (q = p->next, prev_q = p; q; q = prev_q->next)
941: {
942: int delete_q = 0;
943: if (! q->in_use && GET_MODE (q->slot) == BLKmode)
944: {
1.1.1.8 root 945: if (p->base_offset + p->full_size == q->base_offset)
1.1.1.6 root 946: {
947: /* Q comes after P; combine Q into P. */
948: p->size += q->size;
1.1.1.8 root 949: p->full_size += q->full_size;
1.1.1.6 root 950: delete_q = 1;
951: }
1.1.1.8 root 952: else if (q->base_offset + q->full_size == p->base_offset)
1.1.1.6 root 953: {
954: /* P comes after Q; combine P into Q. */
955: q->size += p->size;
1.1.1.8 root 956: q->full_size += p->full_size;
1.1.1.6 root 957: delete_p = 1;
958: break;
959: }
960: }
961: /* Either delete Q or advance past it. */
962: if (delete_q)
963: prev_q->next = q->next;
964: else
965: prev_q = q;
966: }
967: /* Either delete P or advance past it. */
968: if (delete_p)
969: {
970: if (prev_p)
971: prev_p->next = p->next;
972: else
973: temp_slots = p->next;
974: }
975: else
976: prev_p = p;
977: }
978:
979: /* Free all the RTL made by plus_constant. */
980: rtx_free (free_pointer);
981: }
1.1 root 982:
1.1.1.7 root 983: /* Find the temp slot corresponding to the object at address X. */
984:
985: static struct temp_slot *
986: find_temp_slot_from_address (x)
987: rtx x;
988: {
989: struct temp_slot *p;
990: rtx next;
991:
992: for (p = temp_slots; p; p = p->next)
993: {
994: if (! p->in_use)
995: continue;
996: else if (XEXP (p->slot, 0) == x
997: || p->address == x)
998: return p;
999:
1000: else if (p->address != 0 && GET_CODE (p->address) == EXPR_LIST)
1001: for (next = p->address; next; next = XEXP (next, 1))
1002: if (XEXP (next, 0) == x)
1003: return p;
1004: }
1005:
1006: return 0;
1007: }
1008:
1.1.1.8 root 1009: /* Indicate that NEW is an alternate way of referring to the temp slot
1.1.1.7 root 1010: that previous was known by OLD. */
1011:
1012: void
1013: update_temp_slot_address (old, new)
1014: rtx old, new;
1015: {
1016: struct temp_slot *p = find_temp_slot_from_address (old);
1017:
1018: /* If none, return. Else add NEW as an alias. */
1019: if (p == 0)
1020: return;
1021: else if (p->address == 0)
1022: p->address = new;
1023: else
1024: {
1025: if (GET_CODE (p->address) != EXPR_LIST)
1026: p->address = gen_rtx (EXPR_LIST, VOIDmode, p->address, NULL_RTX);
1027:
1028: p->address = gen_rtx (EXPR_LIST, VOIDmode, new, p->address);
1029: }
1030: }
1031:
1032: /* If X could be a reference to a temporary slot, mark the fact that its
1.1.1.8 root 1033: address was taken. */
1.1.1.7 root 1034:
1035: void
1036: mark_temp_addr_taken (x)
1037: rtx x;
1038: {
1039: struct temp_slot *p;
1040:
1041: if (x == 0)
1042: return;
1043:
1044: /* If X is not in memory or is at a constant address, it cannot be in
1045: a temporary slot. */
1046: if (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
1047: return;
1048:
1049: p = find_temp_slot_from_address (XEXP (x, 0));
1050: if (p != 0)
1051: p->addr_taken = 1;
1052: }
1053:
1.1 root 1054: /* If X could be a reference to a temporary slot, mark that slot as belonging
1055: to the to one level higher. If X matched one of our slots, just mark that
1056: one. Otherwise, we can't easily predict which it is, so upgrade all of
1057: them. Kept slots need not be touched.
1058:
1059: This is called when an ({...}) construct occurs and a statement
1060: returns a value in memory. */
1061:
1062: void
1063: preserve_temp_slots (x)
1064: rtx x;
1065: {
1.1.1.7 root 1066: struct temp_slot *p = 0;
1067:
1068: /* If there is no result, we still might have some objects whose address
1069: were taken, so we need to make sure they stay around. */
1070: if (x == 0)
1071: {
1072: for (p = temp_slots; p; p = p->next)
1073: if (p->in_use && p->level == temp_slot_level && p->addr_taken)
1074: p->level--;
1075:
1076: return;
1077: }
1078:
1079: /* If X is a register that is being used as a pointer, see if we have
1080: a temporary slot we know it points to. To be consistent with
1081: the code below, we really should preserve all non-kept slots
1082: if we can't find a match, but that seems to be much too costly. */
1083: if (GET_CODE (x) == REG && REGNO_POINTER_FLAG (REGNO (x)))
1084: p = find_temp_slot_from_address (x);
1.1 root 1085:
1086: /* If X is not in memory or is at a constant address, it cannot be in
1.1.1.7 root 1087: a temporary slot, but it can contain something whose address was
1088: taken. */
1089: if (p == 0 && (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0))))
1090: {
1091: for (p = temp_slots; p; p = p->next)
1092: if (p->in_use && p->level == temp_slot_level && p->addr_taken)
1093: p->level--;
1094:
1095: return;
1096: }
1.1 root 1097:
1098: /* First see if we can find a match. */
1.1.1.7 root 1099: if (p == 0)
1100: p = find_temp_slot_from_address (XEXP (x, 0));
1101:
1102: if (p != 0)
1103: {
1104: /* Move everything at our level whose address was taken to our new
1105: level in case we used its address. */
1106: struct temp_slot *q;
1107:
1108: for (q = temp_slots; q; q = q->next)
1109: if (q != p && q->addr_taken && q->level == p->level)
1110: q->level--;
1111:
1112: p->level--;
1.1.1.8 root 1113: p->addr_taken = 0;
1.1.1.7 root 1114: return;
1115: }
1.1 root 1116:
1117: /* Otherwise, preserve all non-kept slots at this level. */
1118: for (p = temp_slots; p; p = p->next)
1119: if (p->in_use && p->level == temp_slot_level && ! p->keep)
1120: p->level--;
1121: }
1122:
1.1.1.6 root 1123: /* X is the result of an RTL_EXPR. If it is a temporary slot associated
1124: with that RTL_EXPR, promote it into a temporary slot at the present
1125: level so it will not be freed when we free slots made in the
1126: RTL_EXPR. */
1127:
1128: void
1129: preserve_rtl_expr_result (x)
1130: rtx x;
1131: {
1132: struct temp_slot *p;
1133:
1134: /* If X is not in memory or is at a constant address, it cannot be in
1135: a temporary slot. */
1136: if (x == 0 || GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
1137: return;
1138:
1.1.1.7 root 1139: /* If we can find a match, move it to our level unless it is already at
1140: an upper level. */
1141: p = find_temp_slot_from_address (XEXP (x, 0));
1142: if (p != 0)
1143: {
1144: p->level = MIN (p->level, temp_slot_level);
1145: p->rtl_expr = 0;
1146: }
1.1.1.6 root 1147:
1148: return;
1149: }
1150:
1.1 root 1151: /* Free all temporaries used so far. This is normally called at the end
1.1.1.6 root 1152: of generating code for a statement. Don't free any temporaries
1153: currently in use for an RTL_EXPR that hasn't yet been emitted.
1154: We could eventually do better than this since it can be reused while
1155: generating the same RTL_EXPR, but this is complex and probably not
1156: worthwhile. */
1.1 root 1157:
1158: void
1159: free_temp_slots ()
1160: {
1161: struct temp_slot *p;
1162:
1163: for (p = temp_slots; p; p = p->next)
1.1.1.6 root 1164: if (p->in_use && p->level == temp_slot_level && ! p->keep
1165: && p->rtl_expr == 0)
1.1 root 1166: p->in_use = 0;
1.1.1.6 root 1167:
1168: combine_temp_slots ();
1169: }
1170:
1171: /* Free all temporary slots used in T, an RTL_EXPR node. */
1172:
1173: void
1174: free_temps_for_rtl_expr (t)
1175: tree t;
1176: {
1177: struct temp_slot *p;
1178:
1179: for (p = temp_slots; p; p = p->next)
1180: if (p->rtl_expr == t)
1181: p->in_use = 0;
1182:
1183: combine_temp_slots ();
1.1 root 1184: }
1185:
1186: /* Push deeper into the nesting level for stack temporaries. */
1187:
1188: void
1189: push_temp_slots ()
1190: {
1191: temp_slot_level++;
1192: }
1193:
1194: /* Pop a temporary nesting level. All slots in use in the current level
1195: are freed. */
1196:
1197: void
1198: pop_temp_slots ()
1199: {
1200: struct temp_slot *p;
1201:
1202: for (p = temp_slots; p; p = p->next)
1.1.1.6 root 1203: if (p->in_use && p->level == temp_slot_level && p->rtl_expr == 0)
1.1 root 1204: p->in_use = 0;
1205:
1.1.1.6 root 1206: combine_temp_slots ();
1207:
1.1 root 1208: temp_slot_level--;
1209: }
1210:
1211: /* Retroactively move an auto variable from a register to a stack slot.
1212: This is done when an address-reference to the variable is seen. */
1213:
1214: void
1215: put_var_into_stack (decl)
1216: tree decl;
1217: {
1218: register rtx reg;
1.1.1.4 root 1219: enum machine_mode promoted_mode, decl_mode;
1.1 root 1220: struct function *function = 0;
1.1.1.6 root 1221: tree context;
1222:
1223: if (output_bytecode)
1224: return;
1225:
1226: context = decl_function_context (decl);
1.1 root 1227:
1.1.1.4 root 1228: /* Get the current rtl used for this object and it's original mode. */
1.1 root 1229: reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl);
1230:
1.1.1.4 root 1231: /* No need to do anything if decl has no rtx yet
1232: since in that case caller is setting TREE_ADDRESSABLE
1233: and a stack slot will be assigned when the rtl is made. */
1234: if (reg == 0)
1235: return;
1236:
1237: /* Get the declared mode for this object. */
1238: decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
1239: : DECL_MODE (decl));
1240: /* Get the mode it's actually stored in. */
1241: promoted_mode = GET_MODE (reg);
1242:
1.1 root 1243: /* If this variable comes from an outer function,
1244: find that function's saved context. */
1245: if (context != current_function_decl)
1246: for (function = outer_function_chain; function; function = function->next)
1247: if (function->decl == context)
1248: break;
1249:
1250: /* If this is a variable-size object with a pseudo to address it,
1251: put that pseudo into the stack, if the var is nonlocal. */
1.1.1.4 root 1252: if (DECL_NONLOCAL (decl)
1.1 root 1253: && GET_CODE (reg) == MEM
1254: && GET_CODE (XEXP (reg, 0)) == REG
1255: && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
1.1.1.4 root 1256: {
1257: reg = XEXP (reg, 0);
1258: decl_mode = promoted_mode = GET_MODE (reg);
1259: }
1.1.1.5 root 1260:
1.1.1.6 root 1261: /* Now we should have a value that resides in one or more pseudo regs. */
1262:
1263: if (GET_CODE (reg) == REG)
1264: put_reg_into_stack (function, reg, TREE_TYPE (decl),
1.1.1.8 root 1265: promoted_mode, decl_mode, TREE_SIDE_EFFECTS (decl));
1.1.1.6 root 1266: else if (GET_CODE (reg) == CONCAT)
1267: {
1268: /* A CONCAT contains two pseudos; put them both in the stack.
1269: We do it so they end up consecutive. */
1270: enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
1271: tree part_type = TREE_TYPE (TREE_TYPE (decl));
1.1.1.8 root 1272: #ifdef FRAME_GROWS_DOWNWARD
1.1.1.6 root 1273: /* Since part 0 should have a lower address, do it second. */
1.1.1.8 root 1274: put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
1275: part_mode, TREE_SIDE_EFFECTS (decl));
1276: put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
1277: part_mode, TREE_SIDE_EFFECTS (decl));
1.1.1.6 root 1278: #else
1.1.1.8 root 1279: put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
1280: part_mode, TREE_SIDE_EFFECTS (decl));
1281: put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
1282: part_mode, TREE_SIDE_EFFECTS (decl));
1.1.1.6 root 1283: #endif
1284:
1285: /* Change the CONCAT into a combined MEM for both parts. */
1286: PUT_CODE (reg, MEM);
1.1.1.8 root 1287: MEM_VOLATILE_P (reg) = MEM_VOLATILE_P (XEXP (reg, 0));
1288:
1.1.1.6 root 1289: /* The two parts are in memory order already.
1290: Use the lower parts address as ours. */
1291: XEXP (reg, 0) = XEXP (XEXP (reg, 0), 0);
1292: /* Prevent sharing of rtl that might lose. */
1293: if (GET_CODE (XEXP (reg, 0)) == PLUS)
1294: XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
1295: }
1296: }
1297:
1298: /* Subroutine of put_var_into_stack. This puts a single pseudo reg REG
1299: into the stack frame of FUNCTION (0 means the current function).
1300: DECL_MODE is the machine mode of the user-level data type.
1.1.1.8 root 1301: PROMOTED_MODE is the machine mode of the register.
1302: VOLATILE_P is nonzero if this is for a "volatile" decl. */
1.1.1.6 root 1303:
1304: static void
1.1.1.8 root 1305: put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p)
1.1.1.6 root 1306: struct function *function;
1307: rtx reg;
1308: tree type;
1309: enum machine_mode promoted_mode, decl_mode;
1.1.1.8 root 1310: int volatile_p;
1.1.1.6 root 1311: {
1312: rtx new = 0;
1.1 root 1313:
1314: if (function)
1315: {
1316: if (REGNO (reg) < function->max_parm_reg)
1317: new = function->parm_reg_stack_loc[REGNO (reg)];
1318: if (new == 0)
1.1.1.5 root 1319: new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),
1.1 root 1320: 0, function);
1321: }
1322: else
1323: {
1324: if (REGNO (reg) < max_parm_reg)
1325: new = parm_reg_stack_loc[REGNO (reg)];
1326: if (new == 0)
1.1.1.5 root 1327: new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
1.1 root 1328: }
1329:
1.1.1.8 root 1330: PUT_MODE (reg, decl_mode);
1.1 root 1331: XEXP (reg, 0) = XEXP (new, 0);
1332: /* `volatil' bit means one thing for MEMs, another entirely for REGs. */
1.1.1.8 root 1333: MEM_VOLATILE_P (reg) = volatile_p;
1.1 root 1334: PUT_CODE (reg, MEM);
1335:
1336: /* If this is a memory ref that contains aggregate components,
1337: mark it as such for cse and loop optimize. */
1.1.1.7 root 1338: MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
1.1 root 1339:
1340: /* Now make sure that all refs to the variable, previously made
1341: when it was a register, are fixed up to be valid again. */
1342: if (function)
1343: {
1344: struct var_refs_queue *temp;
1345:
1346: /* Variable is inherited; fix it up when we get back to its function. */
1347: push_obstacks (function->function_obstack,
1348: function->function_maybepermanent_obstack);
1.1.1.6 root 1349:
1350: /* See comment in restore_tree_status in tree.c for why this needs to be
1351: on saveable obstack. */
1.1 root 1352: temp
1.1.1.6 root 1353: = (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));
1.1 root 1354: temp->modified = reg;
1.1.1.4 root 1355: temp->promoted_mode = promoted_mode;
1.1.1.6 root 1356: temp->unsignedp = TREE_UNSIGNED (type);
1.1 root 1357: temp->next = function->fixup_var_refs_queue;
1358: function->fixup_var_refs_queue = temp;
1359: pop_obstacks ();
1360: }
1361: else
1362: /* Variable is local; fix it up now. */
1.1.1.6 root 1363: fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type));
1.1 root 1364: }
1365:
1366: static void
1.1.1.4 root 1367: fixup_var_refs (var, promoted_mode, unsignedp)
1.1 root 1368: rtx var;
1.1.1.4 root 1369: enum machine_mode promoted_mode;
1370: int unsignedp;
1.1 root 1371: {
1372: tree pending;
1373: rtx first_insn = get_insns ();
1374: struct sequence_stack *stack = sequence_stack;
1375: tree rtl_exps = rtl_expr_chain;
1376:
1377: /* Must scan all insns for stack-refs that exceed the limit. */
1.1.1.4 root 1378: fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
1.1 root 1379:
1380: /* Scan all pending sequences too. */
1381: for (; stack; stack = stack->next)
1382: {
1383: push_to_sequence (stack->first);
1.1.1.4 root 1384: fixup_var_refs_insns (var, promoted_mode, unsignedp,
1385: stack->first, stack->next != 0);
1.1 root 1386: /* Update remembered end of sequence
1387: in case we added an insn at the end. */
1388: stack->last = get_last_insn ();
1389: end_sequence ();
1390: }
1391:
1392: /* Scan all waiting RTL_EXPRs too. */
1393: for (pending = rtl_exps; pending; pending = TREE_CHAIN (pending))
1394: {
1395: rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));
1396: if (seq != const0_rtx && seq != 0)
1397: {
1398: push_to_sequence (seq);
1.1.1.4 root 1399: fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);
1.1 root 1400: end_sequence ();
1401: }
1402: }
1403: }
1404:
1.1.1.7 root 1405: /* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
1.1 root 1406: some part of an insn. Return a struct fixup_replacement whose OLD
1407: value is equal to X. Allocate a new structure if no such entry exists. */
1408:
1409: static struct fixup_replacement *
1.1.1.4 root 1410: find_fixup_replacement (replacements, x)
1.1 root 1411: struct fixup_replacement **replacements;
1412: rtx x;
1413: {
1414: struct fixup_replacement *p;
1415:
1416: /* See if we have already replaced this. */
1417: for (p = *replacements; p && p->old != x; p = p->next)
1418: ;
1419:
1420: if (p == 0)
1421: {
1422: p = (struct fixup_replacement *) oballoc (sizeof (struct fixup_replacement));
1423: p->old = x;
1424: p->new = 0;
1425: p->next = *replacements;
1426: *replacements = p;
1427: }
1428:
1429: return p;
1430: }
1431:
1432: /* Scan the insn-chain starting with INSN for refs to VAR
1433: and fix them up. TOPLEVEL is nonzero if this chain is the
1434: main chain of insns for the current function. */
1435:
1436: static void
1.1.1.4 root 1437: fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
1.1 root 1438: rtx var;
1.1.1.4 root 1439: enum machine_mode promoted_mode;
1440: int unsignedp;
1.1 root 1441: rtx insn;
1442: int toplevel;
1443: {
1.1.1.5 root 1444: rtx call_dest = 0;
1445:
1.1 root 1446: while (insn)
1447: {
1448: rtx next = NEXT_INSN (insn);
1449: rtx note;
1.1.1.5 root 1450: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
1.1 root 1451: {
1.1.1.7 root 1452: /* If this is a CLOBBER of VAR, delete it.
1453:
1454: If it has a REG_LIBCALL note, delete the REG_LIBCALL
1455: and REG_RETVAL notes too. */
1.1.1.8 root 1456: if (GET_CODE (PATTERN (insn)) == CLOBBER
1.1.1.7 root 1457: && XEXP (PATTERN (insn), 0) == var)
1458: {
1459: if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
1460: /* The REG_LIBCALL note will go away since we are going to
1461: turn INSN into a NOTE, so just delete the
1462: corresponding REG_RETVAL note. */
1463: remove_note (XEXP (note, 0),
1464: find_reg_note (XEXP (note, 0), REG_RETVAL,
1465: NULL_RTX));
1466:
1467: /* In unoptimized compilation, we shouldn't call delete_insn
1468: except in jump.c doing warnings. */
1469: PUT_CODE (insn, NOTE);
1470: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
1471: NOTE_SOURCE_FILE (insn) = 0;
1472: }
1473:
1.1 root 1474: /* The insn to load VAR from a home in the arglist
1475: is now a no-op. When we see it, just delete it. */
1.1.1.7 root 1476: else if (toplevel
1477: && GET_CODE (PATTERN (insn)) == SET
1478: && SET_DEST (PATTERN (insn)) == var
1479: /* If this represents the result of an insn group,
1480: don't delete the insn. */
1481: && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
1482: && rtx_equal_p (SET_SRC (PATTERN (insn)), var))
1.1 root 1483: {
1.1.1.4 root 1484: /* In unoptimized compilation, we shouldn't call delete_insn
1485: except in jump.c doing warnings. */
1486: PUT_CODE (insn, NOTE);
1487: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
1488: NOTE_SOURCE_FILE (insn) = 0;
1.1 root 1489: if (insn == last_parm_insn)
1490: last_parm_insn = PREV_INSN (next);
1491: }
1492: else
1493: {
1.1.1.5 root 1494: struct fixup_replacement *replacements = 0;
1495: rtx next_insn = NEXT_INSN (insn);
1496:
1497: #ifdef SMALL_REGISTER_CLASSES
1498: /* If the insn that copies the results of a CALL_INSN
1499: into a pseudo now references VAR, we have to use an
1500: intermediate pseudo since we want the life of the
1501: return value register to be only a single insn.
1502:
1503: If we don't use an intermediate pseudo, such things as
1504: address computations to make the address of VAR valid
1.1.1.8 root 1505: if it is not can be placed between the CALL_INSN and INSN.
1.1.1.5 root 1506:
1507: To make sure this doesn't happen, we record the destination
1508: of the CALL_INSN and see if the next insn uses both that
1509: and VAR. */
1510:
1511: if (call_dest != 0 && GET_CODE (insn) == INSN
1512: && reg_mentioned_p (var, PATTERN (insn))
1513: && reg_mentioned_p (call_dest, PATTERN (insn)))
1514: {
1515: rtx temp = gen_reg_rtx (GET_MODE (call_dest));
1516:
1517: emit_insn_before (gen_move_insn (temp, call_dest), insn);
1518:
1519: PATTERN (insn) = replace_rtx (PATTERN (insn),
1520: call_dest, temp);
1521: }
1522:
1523: if (GET_CODE (insn) == CALL_INSN
1524: && GET_CODE (PATTERN (insn)) == SET)
1525: call_dest = SET_DEST (PATTERN (insn));
1526: else if (GET_CODE (insn) == CALL_INSN
1527: && GET_CODE (PATTERN (insn)) == PARALLEL
1528: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
1529: call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
1530: else
1531: call_dest = 0;
1532: #endif
1533:
1.1 root 1534: /* See if we have to do anything to INSN now that VAR is in
1535: memory. If it needs to be loaded into a pseudo, use a single
1536: pseudo for the entire insn in case there is a MATCH_DUP
1537: between two operands. We pass a pointer to the head of
1538: a list of struct fixup_replacements. If fixup_var_refs_1
1539: needs to allocate pseudos or replacement MEMs (for SUBREGs),
1540: it will record them in this list.
1541:
1542: If it allocated a pseudo for any replacement, we copy into
1543: it here. */
1544:
1.1.1.4 root 1545: fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
1546: &replacements);
1.1 root 1547:
1.1.1.5 root 1548: /* If this is last_parm_insn, and any instructions were output
1549: after it to fix it up, then we must set last_parm_insn to
1550: the last such instruction emitted. */
1551: if (insn == last_parm_insn)
1552: last_parm_insn = PREV_INSN (next_insn);
1553:
1.1 root 1554: while (replacements)
1555: {
1556: if (GET_CODE (replacements->new) == REG)
1557: {
1558: rtx insert_before;
1.1.1.4 root 1559: rtx seq;
1.1 root 1560:
1561: /* OLD might be a (subreg (mem)). */
1562: if (GET_CODE (replacements->old) == SUBREG)
1563: replacements->old
1564: = fixup_memory_subreg (replacements->old, insn, 0);
1565: else
1566: replacements->old
1567: = fixup_stack_1 (replacements->old, insn);
1568:
1.1.1.7 root 1569: insert_before = insn;
1.1 root 1570:
1.1.1.4 root 1571: /* If we are changing the mode, do a conversion.
1572: This might be wasteful, but combine.c will
1573: eliminate much of the waste. */
1574:
1575: if (GET_MODE (replacements->new)
1576: != GET_MODE (replacements->old))
1577: {
1578: start_sequence ();
1579: convert_move (replacements->new,
1580: replacements->old, unsignedp);
1581: seq = gen_sequence ();
1582: end_sequence ();
1583: }
1584: else
1585: seq = gen_move_insn (replacements->new,
1586: replacements->old);
1587:
1588: emit_insn_before (seq, insert_before);
1.1 root 1589: }
1590:
1591: replacements = replacements->next;
1592: }
1593: }
1594:
1595: /* Also fix up any invalid exprs in the REG_NOTES of this insn.
1596: But don't touch other insns referred to by reg-notes;
1597: we will get them elsewhere. */
1598: for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1599: if (GET_CODE (note) != INSN_LIST)
1.1.1.5 root 1600: XEXP (note, 0)
1601: = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
1.1 root 1602: }
1603: insn = next;
1604: }
1605: }
1606:
1.1.1.4 root 1607: /* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE.
1608: See if the rtx expression at *LOC in INSN needs to be changed.
1.1 root 1609:
1610: REPLACEMENTS is a pointer to a list head that starts out zero, but may
1611: contain a list of original rtx's and replacements. If we find that we need
1612: to modify this insn by replacing a memory reference with a pseudo or by
1613: making a new MEM to implement a SUBREG, we consult that list to see if
1614: we have already chosen a replacement. If none has already been allocated,
1615: we allocate it and update the list. fixup_var_refs_insns will copy VAR
1616: or the SUBREG, as appropriate, to the pseudo. */
1617:
1618: static void
1.1.1.4 root 1619: fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
1.1 root 1620: register rtx var;
1.1.1.4 root 1621: enum machine_mode promoted_mode;
1.1 root 1622: register rtx *loc;
1623: rtx insn;
1624: struct fixup_replacement **replacements;
1625: {
1626: register int i;
1627: register rtx x = *loc;
1628: RTX_CODE code = GET_CODE (x);
1629: register char *fmt;
1630: register rtx tem, tem1;
1631: struct fixup_replacement *replacement;
1632:
1633: switch (code)
1634: {
1635: case MEM:
1636: if (var == x)
1637: {
1638: /* If we already have a replacement, use it. Otherwise,
1639: try to fix up this address in case it is invalid. */
1640:
1.1.1.4 root 1641: replacement = find_fixup_replacement (replacements, var);
1.1 root 1642: if (replacement->new)
1643: {
1644: *loc = replacement->new;
1645: return;
1646: }
1647:
1648: *loc = replacement->new = x = fixup_stack_1 (x, insn);
1649:
1.1.1.4 root 1650: /* Unless we are forcing memory to register or we changed the mode,
1651: we can leave things the way they are if the insn is valid. */
1.1 root 1652:
1653: INSN_CODE (insn) = -1;
1.1.1.4 root 1654: if (! flag_force_mem && GET_MODE (x) == promoted_mode
1655: && recog_memoized (insn) >= 0)
1.1 root 1656: return;
1657:
1.1.1.4 root 1658: *loc = replacement->new = gen_reg_rtx (promoted_mode);
1.1 root 1659: return;
1660: }
1661:
1662: /* If X contains VAR, we need to unshare it here so that we update
1663: each occurrence separately. But all identical MEMs in one insn
1664: must be replaced with the same rtx because of the possibility of
1665: MATCH_DUPs. */
1666:
1667: if (reg_mentioned_p (var, x))
1668: {
1.1.1.4 root 1669: replacement = find_fixup_replacement (replacements, x);
1.1 root 1670: if (replacement->new == 0)
1671: replacement->new = copy_most_rtx (x, var);
1672:
1673: *loc = x = replacement->new;
1674: }
1675: break;
1676:
1677: case REG:
1678: case CC0:
1679: case PC:
1680: case CONST_INT:
1681: case CONST:
1682: case SYMBOL_REF:
1683: case LABEL_REF:
1684: case CONST_DOUBLE:
1685: return;
1686:
1687: case SIGN_EXTRACT:
1688: case ZERO_EXTRACT:
1689: /* Note that in some cases those types of expressions are altered
1690: by optimize_bit_field, and do not survive to get here. */
1691: if (XEXP (x, 0) == var
1692: || (GET_CODE (XEXP (x, 0)) == SUBREG
1693: && SUBREG_REG (XEXP (x, 0)) == var))
1694: {
1695: /* Get TEM as a valid MEM in the mode presently in the insn.
1696:
1697: We don't worry about the possibility of MATCH_DUP here; it
1698: is highly unlikely and would be tricky to handle. */
1699:
1700: tem = XEXP (x, 0);
1701: if (GET_CODE (tem) == SUBREG)
1702: tem = fixup_memory_subreg (tem, insn, 1);
1703: tem = fixup_stack_1 (tem, insn);
1704:
1705: /* Unless we want to load from memory, get TEM into the proper mode
1706: for an extract from memory. This can only be done if the
1707: extract is at a constant position and length. */
1708:
1709: if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT
1710: && GET_CODE (XEXP (x, 2)) == CONST_INT
1711: && ! mode_dependent_address_p (XEXP (tem, 0))
1712: && ! MEM_VOLATILE_P (tem))
1713: {
1714: enum machine_mode wanted_mode = VOIDmode;
1715: enum machine_mode is_mode = GET_MODE (tem);
1716: int width = INTVAL (XEXP (x, 1));
1717: int pos = INTVAL (XEXP (x, 2));
1718:
1719: #ifdef HAVE_extzv
1720: if (GET_CODE (x) == ZERO_EXTRACT)
1721: wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
1722: #endif
1723: #ifdef HAVE_extv
1724: if (GET_CODE (x) == SIGN_EXTRACT)
1725: wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
1726: #endif
1.1.1.3 root 1727: /* If we have a narrower mode, we can do something. */
1.1 root 1728: if (wanted_mode != VOIDmode
1729: && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
1730: {
1731: int offset = pos / BITS_PER_UNIT;
1732: rtx old_pos = XEXP (x, 2);
1733: rtx newmem;
1734:
1735: /* If the bytes and bits are counted differently, we
1736: must adjust the offset. */
1.1.1.8 root 1737: if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
1738: offset = (GET_MODE_SIZE (is_mode)
1739: - GET_MODE_SIZE (wanted_mode) - offset);
1.1 root 1740:
1741: pos %= GET_MODE_BITSIZE (wanted_mode);
1742:
1743: newmem = gen_rtx (MEM, wanted_mode,
1744: plus_constant (XEXP (tem, 0), offset));
1745: RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
1746: MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
1747: MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
1748:
1749: /* Make the change and see if the insn remains valid. */
1750: INSN_CODE (insn) = -1;
1751: XEXP (x, 0) = newmem;
1.1.1.4 root 1752: XEXP (x, 2) = GEN_INT (pos);
1.1 root 1753:
1754: if (recog_memoized (insn) >= 0)
1755: return;
1756:
1757: /* Otherwise, restore old position. XEXP (x, 0) will be
1758: restored later. */
1759: XEXP (x, 2) = old_pos;
1760: }
1761: }
1762:
1763: /* If we get here, the bitfield extract insn can't accept a memory
1764: reference. Copy the input into a register. */
1765:
1766: tem1 = gen_reg_rtx (GET_MODE (tem));
1767: emit_insn_before (gen_move_insn (tem1, tem), insn);
1768: XEXP (x, 0) = tem1;
1769: return;
1770: }
1771: break;
1772:
1773: case SUBREG:
1774: if (SUBREG_REG (x) == var)
1775: {
1.1.1.4 root 1776: /* If this is a special SUBREG made because VAR was promoted
1777: from a wider mode, replace it with VAR and call ourself
1778: recursively, this time saying that the object previously
1779: had its current mode (by virtue of the SUBREG). */
1780:
1781: if (SUBREG_PROMOTED_VAR_P (x))
1782: {
1783: *loc = var;
1784: fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);
1785: return;
1786: }
1787:
1.1 root 1788: /* If this SUBREG makes VAR wider, it has become a paradoxical
1789: SUBREG with VAR in memory, but these aren't allowed at this
1790: stage of the compilation. So load VAR into a pseudo and take
1791: a SUBREG of that pseudo. */
1792: if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))
1793: {
1.1.1.4 root 1794: replacement = find_fixup_replacement (replacements, var);
1.1 root 1795: if (replacement->new == 0)
1796: replacement->new = gen_reg_rtx (GET_MODE (var));
1797: SUBREG_REG (x) = replacement->new;
1798: return;
1799: }
1800:
1801: /* See if we have already found a replacement for this SUBREG.
1802: If so, use it. Otherwise, make a MEM and see if the insn
1803: is recognized. If not, or if we should force MEM into a register,
1804: make a pseudo for this SUBREG. */
1.1.1.4 root 1805: replacement = find_fixup_replacement (replacements, x);
1.1 root 1806: if (replacement->new)
1807: {
1808: *loc = replacement->new;
1809: return;
1810: }
1811:
1812: replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
1813:
1.1.1.5 root 1814: INSN_CODE (insn) = -1;
1.1 root 1815: if (! flag_force_mem && recog_memoized (insn) >= 0)
1816: return;
1817:
1818: *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
1819: return;
1820: }
1821: break;
1822:
1823: case SET:
1824: /* First do special simplification of bit-field references. */
1825: if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
1826: || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
1827: optimize_bit_field (x, insn, 0);
1828: if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
1829: || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
1.1.1.4 root 1830: optimize_bit_field (x, insn, NULL_PTR);
1.1 root 1831:
1832: /* If SET_DEST is now a paradoxical SUBREG, put the result of this
1833: insn into a pseudo and store the low part of the pseudo into VAR. */
1834: if (GET_CODE (SET_DEST (x)) == SUBREG
1835: && SUBREG_REG (SET_DEST (x)) == var
1836: && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
1837: > GET_MODE_SIZE (GET_MODE (var))))
1838: {
1839: SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));
1840: emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),
1841: tem)),
1842: insn);
1843: break;
1844: }
1845:
1846: {
1847: rtx dest = SET_DEST (x);
1848: rtx src = SET_SRC (x);
1849: rtx outerdest = dest;
1850:
1851: while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
1852: || GET_CODE (dest) == SIGN_EXTRACT
1853: || GET_CODE (dest) == ZERO_EXTRACT)
1854: dest = XEXP (dest, 0);
1855:
1856: if (GET_CODE (src) == SUBREG)
1857: src = XEXP (src, 0);
1858:
1859: /* If VAR does not appear at the top level of the SET
1860: just scan the lower levels of the tree. */
1861:
1862: if (src != var && dest != var)
1863: break;
1864:
1865: /* We will need to rerecognize this insn. */
1866: INSN_CODE (insn) = -1;
1867:
1868: #ifdef HAVE_insv
1869: if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var)
1870: {
1871: /* Since this case will return, ensure we fixup all the
1872: operands here. */
1.1.1.4 root 1873: fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
1874: insn, replacements);
1875: fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
1876: insn, replacements);
1877: fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
1878: insn, replacements);
1.1 root 1879:
1880: tem = XEXP (outerdest, 0);
1881:
1882: /* Clean up (SUBREG:SI (MEM:mode ...) 0)
1883: that may appear inside a ZERO_EXTRACT.
1884: This was legitimate when the MEM was a REG. */
1885: if (GET_CODE (tem) == SUBREG
1886: && SUBREG_REG (tem) == var)
1887: tem = fixup_memory_subreg (tem, insn, 1);
1888: else
1889: tem = fixup_stack_1 (tem, insn);
1890:
1891: if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT
1892: && GET_CODE (XEXP (outerdest, 2)) == CONST_INT
1893: && ! mode_dependent_address_p (XEXP (tem, 0))
1894: && ! MEM_VOLATILE_P (tem))
1895: {
1896: enum machine_mode wanted_mode
1897: = insn_operand_mode[(int) CODE_FOR_insv][0];
1898: enum machine_mode is_mode = GET_MODE (tem);
1899: int width = INTVAL (XEXP (outerdest, 1));
1900: int pos = INTVAL (XEXP (outerdest, 2));
1901:
1.1.1.3 root 1902: /* If we have a narrower mode, we can do something. */
1.1 root 1903: if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
1904: {
1905: int offset = pos / BITS_PER_UNIT;
1906: rtx old_pos = XEXP (outerdest, 2);
1907: rtx newmem;
1908:
1.1.1.8 root 1909: if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
1910: offset = (GET_MODE_SIZE (is_mode)
1911: - GET_MODE_SIZE (wanted_mode) - offset);
1.1 root 1912:
1913: pos %= GET_MODE_BITSIZE (wanted_mode);
1914:
1915: newmem = gen_rtx (MEM, wanted_mode,
1916: plus_constant (XEXP (tem, 0), offset));
1917: RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
1918: MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
1919: MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
1920:
1921: /* Make the change and see if the insn remains valid. */
1922: INSN_CODE (insn) = -1;
1923: XEXP (outerdest, 0) = newmem;
1.1.1.4 root 1924: XEXP (outerdest, 2) = GEN_INT (pos);
1.1 root 1925:
1926: if (recog_memoized (insn) >= 0)
1927: return;
1928:
1929: /* Otherwise, restore old position. XEXP (x, 0) will be
1930: restored later. */
1931: XEXP (outerdest, 2) = old_pos;
1932: }
1933: }
1934:
1935: /* If we get here, the bit-field store doesn't allow memory
1936: or isn't located at a constant position. Load the value into
1937: a register, do the store, and put it back into memory. */
1938:
1939: tem1 = gen_reg_rtx (GET_MODE (tem));
1940: emit_insn_before (gen_move_insn (tem1, tem), insn);
1941: emit_insn_after (gen_move_insn (tem, tem1), insn);
1942: XEXP (outerdest, 0) = tem1;
1943: return;
1944: }
1945: #endif
1946:
1947: /* STRICT_LOW_PART is a no-op on memory references
1948: and it can cause combinations to be unrecognizable,
1949: so eliminate it. */
1950:
1951: if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
1952: SET_DEST (x) = XEXP (SET_DEST (x), 0);
1953:
1954: /* A valid insn to copy VAR into or out of a register
1955: must be left alone, to avoid an infinite loop here.
1956: If the reference to VAR is by a subreg, fix that up,
1957: since SUBREG is not valid for a memref.
1.1.1.5 root 1958: Also fix up the address of the stack slot.
1959:
1960: Note that we must not try to recognize the insn until
1961: after we know that we have valid addresses and no
1962: (subreg (mem ...) ...) constructs, since these interfere
1963: with determining the validity of the insn. */
1.1 root 1964:
1965: if ((SET_SRC (x) == var
1966: || (GET_CODE (SET_SRC (x)) == SUBREG
1967: && SUBREG_REG (SET_SRC (x)) == var))
1968: && (GET_CODE (SET_DEST (x)) == REG
1969: || (GET_CODE (SET_DEST (x)) == SUBREG
1970: && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
1.1.1.5 root 1971: && x == single_set (PATTERN (insn)))
1.1 root 1972: {
1.1.1.5 root 1973: rtx pat;
1974:
1.1.1.4 root 1975: replacement = find_fixup_replacement (replacements, SET_SRC (x));
1.1 root 1976: if (replacement->new)
1977: SET_SRC (x) = replacement->new;
1978: else if (GET_CODE (SET_SRC (x)) == SUBREG)
1979: SET_SRC (x) = replacement->new
1980: = fixup_memory_subreg (SET_SRC (x), insn, 0);
1981: else
1982: SET_SRC (x) = replacement->new
1983: = fixup_stack_1 (SET_SRC (x), insn);
1.1.1.5 root 1984:
1985: if (recog_memoized (insn) >= 0)
1986: return;
1987:
1988: /* INSN is not valid, but we know that we want to
1989: copy SET_SRC (x) to SET_DEST (x) in some way. So
1990: we generate the move and see whether it requires more
1991: than one insn. If it does, we emit those insns and
1992: delete INSN. Otherwise, we an just replace the pattern
1993: of INSN; we have already verified above that INSN has
1994: no other function that to do X. */
1995:
1996: pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
1997: if (GET_CODE (pat) == SEQUENCE)
1998: {
1999: emit_insn_after (pat, insn);
2000: PUT_CODE (insn, NOTE);
2001: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
2002: NOTE_SOURCE_FILE (insn) = 0;
2003: }
2004: else
2005: PATTERN (insn) = pat;
2006:
1.1 root 2007: return;
2008: }
2009:
2010: if ((SET_DEST (x) == var
2011: || (GET_CODE (SET_DEST (x)) == SUBREG
2012: && SUBREG_REG (SET_DEST (x)) == var))
2013: && (GET_CODE (SET_SRC (x)) == REG
2014: || (GET_CODE (SET_SRC (x)) == SUBREG
2015: && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))
1.1.1.5 root 2016: && x == single_set (PATTERN (insn)))
1.1 root 2017: {
1.1.1.5 root 2018: rtx pat;
2019:
1.1 root 2020: if (GET_CODE (SET_DEST (x)) == SUBREG)
2021: SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
2022: else
2023: SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
1.1.1.5 root 2024:
2025: if (recog_memoized (insn) >= 0)
2026: return;
2027:
2028: pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
2029: if (GET_CODE (pat) == SEQUENCE)
2030: {
2031: emit_insn_after (pat, insn);
2032: PUT_CODE (insn, NOTE);
2033: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
2034: NOTE_SOURCE_FILE (insn) = 0;
2035: }
2036: else
2037: PATTERN (insn) = pat;
2038:
1.1 root 2039: return;
2040: }
2041:
2042: /* Otherwise, storing into VAR must be handled specially
2043: by storing into a temporary and copying that into VAR
1.1.1.4 root 2044: with a new insn after this one. Note that this case
2045: will be used when storing into a promoted scalar since
2046: the insn will now have different modes on the input
2047: and output and hence will be invalid (except for the case
2048: of setting it to a constant, which does not need any
2049: change if it is valid). We generate extra code in that case,
2050: but combine.c will eliminate it. */
1.1 root 2051:
2052: if (dest == var)
2053: {
2054: rtx temp;
1.1.1.4 root 2055: rtx fixeddest = SET_DEST (x);
2056:
1.1 root 2057: /* STRICT_LOW_PART can be discarded, around a MEM. */
1.1.1.4 root 2058: if (GET_CODE (fixeddest) == STRICT_LOW_PART)
2059: fixeddest = XEXP (fixeddest, 0);
1.1 root 2060: /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
1.1.1.4 root 2061: if (GET_CODE (fixeddest) == SUBREG)
1.1.1.8 root 2062: {
2063: fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
2064: promoted_mode = GET_MODE (fixeddest);
2065: }
1.1 root 2066: else
1.1.1.4 root 2067: fixeddest = fixup_stack_1 (fixeddest, insn);
2068:
1.1.1.8 root 2069: temp = gen_reg_rtx (promoted_mode);
1.1.1.4 root 2070:
2071: emit_insn_after (gen_move_insn (fixeddest,
2072: gen_lowpart (GET_MODE (fixeddest),
2073: temp)),
2074: insn);
1.1 root 2075:
2076: SET_DEST (x) = temp;
2077: }
2078: }
2079: }
2080:
2081: /* Nothing special about this RTX; fix its operands. */
2082:
2083: fmt = GET_RTX_FORMAT (code);
2084: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2085: {
2086: if (fmt[i] == 'e')
1.1.1.4 root 2087: fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);
1.1 root 2088: if (fmt[i] == 'E')
2089: {
2090: register int j;
2091: for (j = 0; j < XVECLEN (x, i); j++)
1.1.1.4 root 2092: fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
2093: insn, replacements);
1.1 root 2094: }
2095: }
2096: }
2097:
2098: /* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
2099: return an rtx (MEM:m1 newaddr) which is equivalent.
2100: If any insns must be emitted to compute NEWADDR, put them before INSN.
2101:
2102: UNCRITICAL nonzero means accept paradoxical subregs.
1.1.1.5 root 2103: This is used for subregs found inside of ZERO_EXTRACTs and in REG_NOTES. */
1.1 root 2104:
2105: static rtx
2106: fixup_memory_subreg (x, insn, uncritical)
2107: rtx x;
2108: rtx insn;
2109: int uncritical;
2110: {
2111: int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
2112: rtx addr = XEXP (SUBREG_REG (x), 0);
2113: enum machine_mode mode = GET_MODE (x);
2114: rtx saved, result;
2115:
2116: /* Paradoxical SUBREGs are usually invalid during RTL generation. */
2117: if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
2118: && ! uncritical)
2119: abort ();
2120:
1.1.1.8 root 2121: if (BYTES_BIG_ENDIAN)
2122: offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
2123: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
1.1 root 2124: addr = plus_constant (addr, offset);
2125: if (!flag_force_addr && memory_address_p (mode, addr))
2126: /* Shortcut if no insns need be emitted. */
2127: return change_address (SUBREG_REG (x), mode, addr);
2128: start_sequence ();
2129: result = change_address (SUBREG_REG (x), mode, addr);
2130: emit_insn_before (gen_sequence (), insn);
2131: end_sequence ();
2132: return result;
2133: }
2134:
2135: /* Do fixup_memory_subreg on all (SUBREG (MEM ...) ...) contained in X.
2136: Replace subexpressions of X in place.
2137: If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
2138: Otherwise return X, with its contents possibly altered.
2139:
1.1.1.5 root 2140: If any insns must be emitted to compute NEWADDR, put them before INSN.
2141:
2142: UNCRITICAL is as in fixup_memory_subreg. */
1.1 root 2143:
2144: static rtx
1.1.1.5 root 2145: walk_fixup_memory_subreg (x, insn, uncritical)
1.1 root 2146: register rtx x;
2147: rtx insn;
1.1.1.5 root 2148: int uncritical;
1.1 root 2149: {
2150: register enum rtx_code code;
2151: register char *fmt;
2152: register int i;
2153:
2154: if (x == 0)
2155: return 0;
2156:
2157: code = GET_CODE (x);
2158:
2159: if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
1.1.1.5 root 2160: return fixup_memory_subreg (x, insn, uncritical);
1.1 root 2161:
2162: /* Nothing special about this RTX; fix its operands. */
2163:
2164: fmt = GET_RTX_FORMAT (code);
2165: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2166: {
2167: if (fmt[i] == 'e')
1.1.1.5 root 2168: XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical);
1.1 root 2169: if (fmt[i] == 'E')
2170: {
2171: register int j;
2172: for (j = 0; j < XVECLEN (x, i); j++)
2173: XVECEXP (x, i, j)
1.1.1.5 root 2174: = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical);
1.1 root 2175: }
2176: }
2177: return x;
2178: }
2179:
2180: /* For each memory ref within X, if it refers to a stack slot
2181: with an out of range displacement, put the address in a temp register
2182: (emitting new insns before INSN to load these registers)
2183: and alter the memory ref to use that register.
2184: Replace each such MEM rtx with a copy, to avoid clobberage. */
2185:
2186: static rtx
2187: fixup_stack_1 (x, insn)
2188: rtx x;
2189: rtx insn;
2190: {
2191: register int i;
2192: register RTX_CODE code = GET_CODE (x);
2193: register char *fmt;
2194:
2195: if (code == MEM)
2196: {
2197: register rtx ad = XEXP (x, 0);
2198: /* If we have address of a stack slot but it's not valid
2199: (displacement is too large), compute the sum in a register. */
2200: if (GET_CODE (ad) == PLUS
2201: && GET_CODE (XEXP (ad, 0)) == REG
1.1.1.6 root 2202: && ((REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
2203: && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER)
2204: || XEXP (ad, 0) == current_function_internal_arg_pointer)
1.1 root 2205: && GET_CODE (XEXP (ad, 1)) == CONST_INT)
2206: {
2207: rtx temp, seq;
2208: if (memory_address_p (GET_MODE (x), ad))
2209: return x;
2210:
2211: start_sequence ();
2212: temp = copy_to_reg (ad);
2213: seq = gen_sequence ();
2214: end_sequence ();
2215: emit_insn_before (seq, insn);
2216: return change_address (x, VOIDmode, temp);
2217: }
2218: return x;
2219: }
2220:
2221: fmt = GET_RTX_FORMAT (code);
2222: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2223: {
2224: if (fmt[i] == 'e')
2225: XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
2226: if (fmt[i] == 'E')
2227: {
2228: register int j;
2229: for (j = 0; j < XVECLEN (x, i); j++)
2230: XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
2231: }
2232: }
2233: return x;
2234: }
2235:
2236: /* Optimization: a bit-field instruction whose field
2237: happens to be a byte or halfword in memory
2238: can be changed to a move instruction.
2239:
2240: We call here when INSN is an insn to examine or store into a bit-field.
2241: BODY is the SET-rtx to be altered.
2242:
2243: EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.
2244: (Currently this is called only from function.c, and EQUIV_MEM
2245: is always 0.) */
2246:
2247: static void
2248: optimize_bit_field (body, insn, equiv_mem)
2249: rtx body;
2250: rtx insn;
2251: rtx *equiv_mem;
2252: {
2253: register rtx bitfield;
2254: int destflag;
2255: rtx seq = 0;
2256: enum machine_mode mode;
2257:
2258: if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
2259: || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
2260: bitfield = SET_DEST (body), destflag = 1;
2261: else
2262: bitfield = SET_SRC (body), destflag = 0;
2263:
2264: /* First check that the field being stored has constant size and position
2265: and is in fact a byte or halfword suitably aligned. */
2266:
2267: if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
2268: && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
2269: && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))
2270: != BLKmode)
2271: && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
2272: {
2273: register rtx memref = 0;
2274:
2275: /* Now check that the containing word is memory, not a register,
2276: and that it is safe to change the machine mode. */
2277:
2278: if (GET_CODE (XEXP (bitfield, 0)) == MEM)
2279: memref = XEXP (bitfield, 0);
2280: else if (GET_CODE (XEXP (bitfield, 0)) == REG
2281: && equiv_mem != 0)
2282: memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
2283: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
2284: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)
2285: memref = SUBREG_REG (XEXP (bitfield, 0));
2286: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
2287: && equiv_mem != 0
2288: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)
2289: memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
2290:
2291: if (memref
2292: && ! mode_dependent_address_p (XEXP (memref, 0))
2293: && ! MEM_VOLATILE_P (memref))
2294: {
2295: /* Now adjust the address, first for any subreg'ing
2296: that we are now getting rid of,
2297: and then for which byte of the word is wanted. */
2298:
2299: register int offset = INTVAL (XEXP (bitfield, 2));
1.1.1.7 root 2300: rtx insns;
2301:
1.1 root 2302: /* Adjust OFFSET to count bits from low-address byte. */
1.1.1.8 root 2303: if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
2304: offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
2305: - offset - INTVAL (XEXP (bitfield, 1)));
2306:
1.1 root 2307: /* Adjust OFFSET to count bytes from low-address byte. */
2308: offset /= BITS_PER_UNIT;
2309: if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
2310: {
2311: offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
1.1.1.8 root 2312: if (BYTES_BIG_ENDIAN)
2313: offset -= (MIN (UNITS_PER_WORD,
2314: GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
2315: - MIN (UNITS_PER_WORD,
2316: GET_MODE_SIZE (GET_MODE (memref))));
1.1 root 2317: }
2318:
1.1.1.7 root 2319: start_sequence ();
2320: memref = change_address (memref, mode,
1.1 root 2321: plus_constant (XEXP (memref, 0), offset));
1.1.1.7 root 2322: insns = get_insns ();
2323: end_sequence ();
2324: emit_insns_before (insns, insn);
1.1 root 2325:
2326: /* Store this memory reference where
2327: we found the bit field reference. */
2328:
2329: if (destflag)
2330: {
2331: validate_change (insn, &SET_DEST (body), memref, 1);
2332: if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
2333: {
2334: rtx src = SET_SRC (body);
2335: while (GET_CODE (src) == SUBREG
2336: && SUBREG_WORD (src) == 0)
2337: src = SUBREG_REG (src);
2338: if (GET_MODE (src) != GET_MODE (memref))
2339: src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
2340: validate_change (insn, &SET_SRC (body), src, 1);
2341: }
2342: else if (GET_MODE (SET_SRC (body)) != VOIDmode
2343: && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
2344: /* This shouldn't happen because anything that didn't have
2345: one of these modes should have got converted explicitly
2346: and then referenced through a subreg.
2347: This is so because the original bit-field was
2348: handled by agg_mode and so its tree structure had
2349: the same mode that memref now has. */
2350: abort ();
2351: }
2352: else
2353: {
2354: rtx dest = SET_DEST (body);
2355:
2356: while (GET_CODE (dest) == SUBREG
1.1.1.8 root 2357: && SUBREG_WORD (dest) == 0
2358: && (GET_MODE_CLASS (GET_MODE (dest))
2359: == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest)))))
1.1 root 2360: dest = SUBREG_REG (dest);
2361:
2362: validate_change (insn, &SET_DEST (body), dest, 1);
2363:
2364: if (GET_MODE (dest) == GET_MODE (memref))
2365: validate_change (insn, &SET_SRC (body), memref, 1);
2366: else
2367: {
2368: /* Convert the mem ref to the destination mode. */
2369: rtx newreg = gen_reg_rtx (GET_MODE (dest));
2370:
2371: start_sequence ();
2372: convert_move (newreg, memref,
2373: GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
2374: seq = get_insns ();
2375: end_sequence ();
2376:
2377: validate_change (insn, &SET_SRC (body), newreg, 1);
2378: }
2379: }
2380:
2381: /* See if we can convert this extraction or insertion into
2382: a simple move insn. We might not be able to do so if this
2383: was, for example, part of a PARALLEL.
2384:
2385: If we succeed, write out any needed conversions. If we fail,
2386: it is hard to guess why we failed, so don't do anything
2387: special; just let the optimization be suppressed. */
2388:
2389: if (apply_change_group () && seq)
2390: emit_insns_before (seq, insn);
2391: }
2392: }
2393: }
2394:
2395: /* These routines are responsible for converting virtual register references
2396: to the actual hard register references once RTL generation is complete.
2397:
2398: The following four variables are used for communication between the
2399: routines. They contain the offsets of the virtual registers from their
2400: respective hard registers. */
2401:
2402: static int in_arg_offset;
2403: static int var_offset;
2404: static int dynamic_offset;
2405: static int out_arg_offset;
2406:
2407: /* In most machines, the stack pointer register is equivalent to the bottom
2408: of the stack. */
2409:
2410: #ifndef STACK_POINTER_OFFSET
2411: #define STACK_POINTER_OFFSET 0
2412: #endif
2413:
2414: /* If not defined, pick an appropriate default for the offset of dynamically
2415: allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
2416: REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE. */
2417:
2418: #ifndef STACK_DYNAMIC_OFFSET
2419:
2420: #ifdef ACCUMULATE_OUTGOING_ARGS
2421: /* The bottom of the stack points to the actual arguments. If
2422: REG_PARM_STACK_SPACE is defined, this includes the space for the register
2423: parameters. However, if OUTGOING_REG_PARM_STACK space is not defined,
2424: stack space for register parameters is not pushed by the caller, but
2425: rather part of the fixed stack areas and hence not included in
2426: `current_function_outgoing_args_size'. Nevertheless, we must allow
2427: for it when allocating stack dynamic objects. */
2428:
2429: #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
2430: #define STACK_DYNAMIC_OFFSET(FNDECL) \
2431: (current_function_outgoing_args_size \
2432: + REG_PARM_STACK_SPACE (FNDECL) + (STACK_POINTER_OFFSET))
2433:
2434: #else
2435: #define STACK_DYNAMIC_OFFSET(FNDECL) \
2436: (current_function_outgoing_args_size + (STACK_POINTER_OFFSET))
2437: #endif
2438:
2439: #else
2440: #define STACK_DYNAMIC_OFFSET(FNDECL) STACK_POINTER_OFFSET
2441: #endif
2442: #endif
2443:
2444: /* Pass through the INSNS of function FNDECL and convert virtual register
2445: references to hard register references. */
2446:
2447: void
2448: instantiate_virtual_regs (fndecl, insns)
2449: tree fndecl;
2450: rtx insns;
2451: {
2452: rtx insn;
2453:
2454: /* Compute the offsets to use for this function. */
2455: in_arg_offset = FIRST_PARM_OFFSET (fndecl);
2456: var_offset = STARTING_FRAME_OFFSET;
2457: dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
2458: out_arg_offset = STACK_POINTER_OFFSET;
2459:
2460: /* Scan all variables and parameters of this function. For each that is
2461: in memory, instantiate all virtual registers if the result is a valid
2462: address. If not, we do it later. That will handle most uses of virtual
2463: regs on many machines. */
2464: instantiate_decls (fndecl, 1);
2465:
2466: /* Initialize recognition, indicating that volatile is OK. */
2467: init_recog ();
2468:
2469: /* Scan through all the insns, instantiating every virtual register still
2470: present. */
2471: for (insn = insns; insn; insn = NEXT_INSN (insn))
2472: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
2473: || GET_CODE (insn) == CALL_INSN)
2474: {
2475: instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);
1.1.1.4 root 2476: instantiate_virtual_regs_1 (®_NOTES (insn), NULL_RTX, 0);
1.1 root 2477: }
2478:
2479: /* Now instantiate the remaining register equivalences for debugging info.
2480: These will not be valid addresses. */
2481: instantiate_decls (fndecl, 0);
2482:
2483: /* Indicate that, from now on, assign_stack_local should use
2484: frame_pointer_rtx. */
2485: virtuals_instantiated = 1;
2486: }
2487:
2488: /* Scan all decls in FNDECL (both variables and parameters) and instantiate
2489: all virtual registers in their DECL_RTL's.
2490:
2491: If VALID_ONLY, do this only if the resulting address is still valid.
2492: Otherwise, always do it. */
2493:
2494: static void
2495: instantiate_decls (fndecl, valid_only)
2496: tree fndecl;
2497: int valid_only;
2498: {
2499: tree decl;
2500:
1.1.1.8 root 2501: if (DECL_INLINE (fndecl) || DECL_DEFER_OUTPUT (fndecl))
1.1 root 2502: /* When compiling an inline function, the obstack used for
2503: rtl allocation is the maybepermanent_obstack. Calling
2504: `resume_temporary_allocation' switches us back to that
2505: obstack while we process this function's parameters. */
2506: resume_temporary_allocation ();
2507:
2508: /* Process all parameters of the function. */
2509: for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
2510: {
1.1.1.4 root 2511: instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)),
2512: valid_only);
2513: instantiate_decl (DECL_INCOMING_RTL (decl),
2514: int_size_in_bytes (TREE_TYPE (decl)), valid_only);
1.1 root 2515: }
2516:
2517: /* Now process all variables defined in the function or its subblocks. */
2518: instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);
2519:
1.1.1.8 root 2520: if (DECL_INLINE (fndecl) || DECL_DEFER_OUTPUT (fndecl))
1.1 root 2521: {
2522: /* Save all rtl allocated for this function by raising the
2523: high-water mark on the maybepermanent_obstack. */
2524: preserve_data ();
2525: /* All further rtl allocation is now done in the current_obstack. */
2526: rtl_in_current_obstack ();
2527: }
2528: }
2529:
2530: /* Subroutine of instantiate_decls: Process all decls in the given
2531: BLOCK node and all its subblocks. */
2532:
2533: static void
2534: instantiate_decls_1 (let, valid_only)
2535: tree let;
2536: int valid_only;
2537: {
2538: tree t;
2539:
2540: for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
1.1.1.4 root 2541: instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)),
2542: valid_only);
1.1 root 2543:
2544: /* Process all subblocks. */
2545: for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
2546: instantiate_decls_1 (t, valid_only);
2547: }
1.1.1.4 root 2548:
1.1.1.5 root 2549: /* Subroutine of the preceding procedures: Given RTL representing a
1.1.1.4 root 2550: decl and the size of the object, do any instantiation required.
2551:
2552: If VALID_ONLY is non-zero, it means that the RTL should only be
2553: changed if the new address is valid. */
2554:
2555: static void
2556: instantiate_decl (x, size, valid_only)
2557: rtx x;
2558: int size;
2559: int valid_only;
2560: {
2561: enum machine_mode mode;
2562: rtx addr;
2563:
2564: /* If this is not a MEM, no need to do anything. Similarly if the
2565: address is a constant or a register that is not a virtual register. */
2566:
2567: if (x == 0 || GET_CODE (x) != MEM)
2568: return;
2569:
2570: addr = XEXP (x, 0);
2571: if (CONSTANT_P (addr)
2572: || (GET_CODE (addr) == REG
2573: && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
2574: || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
2575: return;
2576:
2577: /* If we should only do this if the address is valid, copy the address.
2578: We need to do this so we can undo any changes that might make the
2579: address invalid. This copy is unfortunate, but probably can't be
2580: avoided. */
2581:
2582: if (valid_only)
2583: addr = copy_rtx (addr);
2584:
2585: instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
2586:
2587: if (! valid_only)
2588: return;
2589:
2590: /* Now verify that the resulting address is valid for every integer or
2591: floating-point mode up to and including SIZE bytes long. We do this
2592: since the object might be accessed in any mode and frame addresses
2593: are shared. */
2594:
2595: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
2596: mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
2597: mode = GET_MODE_WIDER_MODE (mode))
2598: if (! memory_address_p (mode, addr))
2599: return;
2600:
2601: for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
2602: mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
2603: mode = GET_MODE_WIDER_MODE (mode))
2604: if (! memory_address_p (mode, addr))
2605: return;
2606:
2607: /* Otherwise, put back the address, now that we have updated it and we
2608: know it is valid. */
2609:
2610: XEXP (x, 0) = addr;
2611: }
1.1 root 2612:
2613: /* Given a pointer to a piece of rtx and an optional pointer to the
2614: containing object, instantiate any virtual registers present in it.
2615:
2616: If EXTRA_INSNS, we always do the replacement and generate
2617: any extra insns before OBJECT. If it zero, we do nothing if replacement
2618: is not valid.
2619:
2620: Return 1 if we either had nothing to do or if we were able to do the
2621: needed replacement. Return 0 otherwise; we only return zero if
2622: EXTRA_INSNS is zero.
2623:
2624: We first try some simple transformations to avoid the creation of extra
2625: pseudos. */
2626:
2627: static int
2628: instantiate_virtual_regs_1 (loc, object, extra_insns)
2629: rtx *loc;
2630: rtx object;
2631: int extra_insns;
2632: {
2633: rtx x;
2634: RTX_CODE code;
2635: rtx new = 0;
2636: int offset;
2637: rtx temp;
2638: rtx seq;
2639: int i, j;
2640: char *fmt;
2641:
2642: /* Re-start here to avoid recursion in common cases. */
2643: restart:
2644:
2645: x = *loc;
2646: if (x == 0)
2647: return 1;
2648:
2649: code = GET_CODE (x);
2650:
2651: /* Check for some special cases. */
2652: switch (code)
2653: {
2654: case CONST_INT:
2655: case CONST_DOUBLE:
2656: case CONST:
2657: case SYMBOL_REF:
2658: case CODE_LABEL:
2659: case PC:
2660: case CC0:
2661: case ASM_INPUT:
2662: case ADDR_VEC:
2663: case ADDR_DIFF_VEC:
2664: case RETURN:
2665: return 1;
2666:
2667: case SET:
2668: /* We are allowed to set the virtual registers. This means that
2669: that the actual register should receive the source minus the
2670: appropriate offset. This is used, for example, in the handling
2671: of non-local gotos. */
2672: if (SET_DEST (x) == virtual_incoming_args_rtx)
2673: new = arg_pointer_rtx, offset = - in_arg_offset;
2674: else if (SET_DEST (x) == virtual_stack_vars_rtx)
2675: new = frame_pointer_rtx, offset = - var_offset;
2676: else if (SET_DEST (x) == virtual_stack_dynamic_rtx)
2677: new = stack_pointer_rtx, offset = - dynamic_offset;
2678: else if (SET_DEST (x) == virtual_outgoing_args_rtx)
2679: new = stack_pointer_rtx, offset = - out_arg_offset;
2680:
2681: if (new)
2682: {
2683: /* The only valid sources here are PLUS or REG. Just do
2684: the simplest possible thing to handle them. */
2685: if (GET_CODE (SET_SRC (x)) != REG
2686: && GET_CODE (SET_SRC (x)) != PLUS)
2687: abort ();
2688:
2689: start_sequence ();
2690: if (GET_CODE (SET_SRC (x)) != REG)
1.1.1.4 root 2691: temp = force_operand (SET_SRC (x), NULL_RTX);
1.1 root 2692: else
2693: temp = SET_SRC (x);
1.1.1.4 root 2694: temp = force_operand (plus_constant (temp, offset), NULL_RTX);
1.1 root 2695: seq = get_insns ();
2696: end_sequence ();
2697:
2698: emit_insns_before (seq, object);
2699: SET_DEST (x) = new;
2700:
2701: if (!validate_change (object, &SET_SRC (x), temp, 0)
2702: || ! extra_insns)
2703: abort ();
2704:
2705: return 1;
2706: }
2707:
2708: instantiate_virtual_regs_1 (&SET_DEST (x), object, extra_insns);
2709: loc = &SET_SRC (x);
2710: goto restart;
2711:
2712: case PLUS:
2713: /* Handle special case of virtual register plus constant. */
2714: if (CONSTANT_P (XEXP (x, 1)))
2715: {
1.1.1.8 root 2716: rtx old, new_offset;
1.1 root 2717:
2718: /* Check for (plus (plus VIRT foo) (const_int)) first. */
2719: if (GET_CODE (XEXP (x, 0)) == PLUS)
2720: {
2721: rtx inner = XEXP (XEXP (x, 0), 0);
2722:
2723: if (inner == virtual_incoming_args_rtx)
2724: new = arg_pointer_rtx, offset = in_arg_offset;
2725: else if (inner == virtual_stack_vars_rtx)
2726: new = frame_pointer_rtx, offset = var_offset;
2727: else if (inner == virtual_stack_dynamic_rtx)
2728: new = stack_pointer_rtx, offset = dynamic_offset;
2729: else if (inner == virtual_outgoing_args_rtx)
2730: new = stack_pointer_rtx, offset = out_arg_offset;
2731: else
2732: {
2733: loc = &XEXP (x, 0);
2734: goto restart;
2735: }
2736:
2737: instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
2738: extra_insns);
2739: new = gen_rtx (PLUS, Pmode, new, XEXP (XEXP (x, 0), 1));
2740: }
2741:
2742: else if (XEXP (x, 0) == virtual_incoming_args_rtx)
2743: new = arg_pointer_rtx, offset = in_arg_offset;
2744: else if (XEXP (x, 0) == virtual_stack_vars_rtx)
2745: new = frame_pointer_rtx, offset = var_offset;
2746: else if (XEXP (x, 0) == virtual_stack_dynamic_rtx)
2747: new = stack_pointer_rtx, offset = dynamic_offset;
2748: else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
2749: new = stack_pointer_rtx, offset = out_arg_offset;
2750: else
2751: {
2752: /* We know the second operand is a constant. Unless the
2753: first operand is a REG (which has been already checked),
2754: it needs to be checked. */
2755: if (GET_CODE (XEXP (x, 0)) != REG)
2756: {
2757: loc = &XEXP (x, 0);
2758: goto restart;
2759: }
2760: return 1;
2761: }
2762:
1.1.1.8 root 2763: new_offset = plus_constant (XEXP (x, 1), offset);
1.1 root 2764:
1.1.1.8 root 2765: /* If the new constant is zero, try to replace the sum with just
2766: the register. */
2767: if (new_offset == const0_rtx
2768: && validate_change (object, loc, new, 0))
1.1 root 2769: return 1;
2770:
1.1.1.8 root 2771: /* Next try to replace the register and new offset.
2772: There are two changes to validate here and we can't assume that
2773: in the case of old offset equals new just changing the register
2774: will yield a valid insn. In the interests of a little efficiency,
2775: however, we only call validate change once (we don't queue up the
2776: changes and then call apply_change_group). */
2777:
2778: old = XEXP (x, 0);
2779: if (offset == 0
2780: ? ! validate_change (object, &XEXP (x, 0), new, 0)
2781: : (XEXP (x, 0) = new,
2782: ! validate_change (object, &XEXP (x, 1), new_offset, 0)))
1.1 root 2783: {
2784: if (! extra_insns)
2785: {
2786: XEXP (x, 0) = old;
2787: return 0;
2788: }
2789:
2790: /* Otherwise copy the new constant into a register and replace
2791: constant with that register. */
2792: temp = gen_reg_rtx (Pmode);
1.1.1.8 root 2793: XEXP (x, 0) = new;
1.1 root 2794: if (validate_change (object, &XEXP (x, 1), temp, 0))
1.1.1.8 root 2795: emit_insn_before (gen_move_insn (temp, new_offset), object);
1.1 root 2796: else
2797: {
2798: /* If that didn't work, replace this expression with a
2799: register containing the sum. */
2800:
2801: XEXP (x, 0) = old;
1.1.1.8 root 2802: new = gen_rtx (PLUS, Pmode, new, new_offset);
1.1 root 2803:
2804: start_sequence ();
1.1.1.4 root 2805: temp = force_operand (new, NULL_RTX);
1.1 root 2806: seq = get_insns ();
2807: end_sequence ();
2808:
2809: emit_insns_before (seq, object);
2810: if (! validate_change (object, loc, temp, 0)
2811: && ! validate_replace_rtx (x, temp, object))
2812: abort ();
2813: }
2814: }
2815:
2816: return 1;
2817: }
2818:
2819: /* Fall through to generic two-operand expression case. */
2820: case EXPR_LIST:
2821: case CALL:
2822: case COMPARE:
2823: case MINUS:
2824: case MULT:
2825: case DIV: case UDIV:
2826: case MOD: case UMOD:
2827: case AND: case IOR: case XOR:
1.1.1.7 root 2828: case ROTATERT: case ROTATE:
2829: case ASHIFTRT: case LSHIFTRT: case ASHIFT:
1.1 root 2830: case NE: case EQ:
2831: case GE: case GT: case GEU: case GTU:
2832: case LE: case LT: case LEU: case LTU:
2833: if (XEXP (x, 1) && ! CONSTANT_P (XEXP (x, 1)))
2834: instantiate_virtual_regs_1 (&XEXP (x, 1), object, extra_insns);
2835: loc = &XEXP (x, 0);
2836: goto restart;
2837:
2838: case MEM:
2839: /* Most cases of MEM that convert to valid addresses have already been
2840: handled by our scan of regno_reg_rtx. The only special handling we
2841: need here is to make a copy of the rtx to ensure it isn't being
1.1.1.2 root 2842: shared if we have to change it to a pseudo.
1.1 root 2843:
2844: If the rtx is a simple reference to an address via a virtual register,
2845: it can potentially be shared. In such cases, first try to make it
2846: a valid address, which can also be shared. Otherwise, copy it and
2847: proceed normally.
2848:
2849: First check for common cases that need no processing. These are
2850: usually due to instantiation already being done on a previous instance
2851: of a shared rtx. */
2852:
2853: temp = XEXP (x, 0);
2854: if (CONSTANT_ADDRESS_P (temp)
2855: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
2856: || temp == arg_pointer_rtx
2857: #endif
1.1.1.6 root 2858: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
2859: || temp == hard_frame_pointer_rtx
2860: #endif
1.1 root 2861: || temp == frame_pointer_rtx)
2862: return 1;
2863:
2864: if (GET_CODE (temp) == PLUS
2865: && CONSTANT_ADDRESS_P (XEXP (temp, 1))
2866: && (XEXP (temp, 0) == frame_pointer_rtx
1.1.1.6 root 2867: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
2868: || XEXP (temp, 0) == hard_frame_pointer_rtx
2869: #endif
1.1 root 2870: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
2871: || XEXP (temp, 0) == arg_pointer_rtx
2872: #endif
2873: ))
2874: return 1;
2875:
2876: if (temp == virtual_stack_vars_rtx
2877: || temp == virtual_incoming_args_rtx
2878: || (GET_CODE (temp) == PLUS
2879: && CONSTANT_ADDRESS_P (XEXP (temp, 1))
2880: && (XEXP (temp, 0) == virtual_stack_vars_rtx
2881: || XEXP (temp, 0) == virtual_incoming_args_rtx)))
2882: {
2883: /* This MEM may be shared. If the substitution can be done without
2884: the need to generate new pseudos, we want to do it in place
2885: so all copies of the shared rtx benefit. The call below will
2886: only make substitutions if the resulting address is still
2887: valid.
2888:
2889: Note that we cannot pass X as the object in the recursive call
2890: since the insn being processed may not allow all valid
1.1.1.2 root 2891: addresses. However, if we were not passed on object, we can
2892: only modify X without copying it if X will have a valid
2893: address.
2894:
2895: ??? Also note that this can still lose if OBJECT is an insn that
2896: has less restrictions on an address that some other insn.
2897: In that case, we will modify the shared address. This case
2898: doesn't seem very likely, though. */
1.1 root 2899:
1.1.1.2 root 2900: if (instantiate_virtual_regs_1 (&XEXP (x, 0),
2901: object ? object : x, 0))
1.1 root 2902: return 1;
2903:
2904: /* Otherwise make a copy and process that copy. We copy the entire
2905: RTL expression since it might be a PLUS which could also be
2906: shared. */
2907: *loc = x = copy_rtx (x);
2908: }
2909:
2910: /* Fall through to generic unary operation case. */
2911: case USE:
2912: case CLOBBER:
2913: case SUBREG:
2914: case STRICT_LOW_PART:
2915: case NEG: case NOT:
2916: case PRE_DEC: case PRE_INC: case POST_DEC: case POST_INC:
2917: case SIGN_EXTEND: case ZERO_EXTEND:
2918: case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE:
2919: case FLOAT: case FIX:
2920: case UNSIGNED_FIX: case UNSIGNED_FLOAT:
2921: case ABS:
2922: case SQRT:
2923: case FFS:
2924: /* These case either have just one operand or we know that we need not
2925: check the rest of the operands. */
2926: loc = &XEXP (x, 0);
2927: goto restart;
2928:
2929: case REG:
2930: /* Try to replace with a PLUS. If that doesn't work, compute the sum
2931: in front of this insn and substitute the temporary. */
2932: if (x == virtual_incoming_args_rtx)
2933: new = arg_pointer_rtx, offset = in_arg_offset;
2934: else if (x == virtual_stack_vars_rtx)
2935: new = frame_pointer_rtx, offset = var_offset;
2936: else if (x == virtual_stack_dynamic_rtx)
2937: new = stack_pointer_rtx, offset = dynamic_offset;
2938: else if (x == virtual_outgoing_args_rtx)
2939: new = stack_pointer_rtx, offset = out_arg_offset;
2940:
2941: if (new)
2942: {
2943: temp = plus_constant (new, offset);
2944: if (!validate_change (object, loc, temp, 0))
2945: {
2946: if (! extra_insns)
2947: return 0;
2948:
2949: start_sequence ();
1.1.1.4 root 2950: temp = force_operand (temp, NULL_RTX);
1.1 root 2951: seq = get_insns ();
2952: end_sequence ();
2953:
2954: emit_insns_before (seq, object);
2955: if (! validate_change (object, loc, temp, 0)
2956: && ! validate_replace_rtx (x, temp, object))
2957: abort ();
2958: }
2959: }
2960:
2961: return 1;
2962: }
2963:
2964: /* Scan all subexpressions. */
2965: fmt = GET_RTX_FORMAT (code);
2966: for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
2967: if (*fmt == 'e')
2968: {
2969: if (!instantiate_virtual_regs_1 (&XEXP (x, i), object, extra_insns))
2970: return 0;
2971: }
2972: else if (*fmt == 'E')
2973: for (j = 0; j < XVECLEN (x, i); j++)
2974: if (! instantiate_virtual_regs_1 (&XVECEXP (x, i, j), object,
2975: extra_insns))
2976: return 0;
2977:
2978: return 1;
2979: }
2980:
2981: /* Optimization: assuming this function does not receive nonlocal gotos,
2982: delete the handlers for such, as well as the insns to establish
2983: and disestablish them. */
2984:
2985: static void
2986: delete_handlers ()
2987: {
2988: rtx insn;
2989: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2990: {
2991: /* Delete the handler by turning off the flag that would
2992: prevent jump_optimize from deleting it.
2993: Also permit deletion of the nonlocal labels themselves
2994: if nothing local refers to them. */
2995: if (GET_CODE (insn) == CODE_LABEL)
1.1.1.8 root 2996: {
2997: tree t, last_t;
2998:
2999: LABEL_PRESERVE_P (insn) = 0;
3000:
3001: /* Remove it from the nonlocal_label list, to avoid confusing
3002: flow. */
3003: for (t = nonlocal_labels, last_t = 0; t;
3004: last_t = t, t = TREE_CHAIN (t))
3005: if (DECL_RTL (TREE_VALUE (t)) == insn)
3006: break;
3007: if (t)
3008: {
3009: if (! last_t)
3010: nonlocal_labels = TREE_CHAIN (nonlocal_labels);
3011: else
3012: TREE_CHAIN (last_t) = TREE_CHAIN (t);
3013: }
3014: }
1.1 root 3015: if (GET_CODE (insn) == INSN
1.1.1.3 root 3016: && ((nonlocal_goto_handler_slot != 0
3017: && reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (insn)))
3018: || (nonlocal_goto_stack_level != 0
3019: && reg_mentioned_p (nonlocal_goto_stack_level,
3020: PATTERN (insn)))))
1.1 root 3021: delete_insn (insn);
3022: }
3023: }
3024:
3025: /* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
3026: of the current function. */
3027:
3028: rtx
3029: nonlocal_label_rtx_list ()
3030: {
3031: tree t;
3032: rtx x = 0;
3033:
3034: for (t = nonlocal_labels; t; t = TREE_CHAIN (t))
3035: x = gen_rtx (EXPR_LIST, VOIDmode, label_rtx (TREE_VALUE (t)), x);
3036:
3037: return x;
3038: }
3039:
3040: /* Output a USE for any register use in RTL.
3041: This is used with -noreg to mark the extent of lifespan
3042: of any registers used in a user-visible variable's DECL_RTL. */
3043:
3044: void
3045: use_variable (rtl)
3046: rtx rtl;
3047: {
3048: if (GET_CODE (rtl) == REG)
3049: /* This is a register variable. */
3050: emit_insn (gen_rtx (USE, VOIDmode, rtl));
3051: else if (GET_CODE (rtl) == MEM
3052: && GET_CODE (XEXP (rtl, 0)) == REG
3053: && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
3054: || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
3055: && XEXP (rtl, 0) != current_function_internal_arg_pointer)
3056: /* This is a variable-sized structure. */
3057: emit_insn (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)));
3058: }
3059:
3060: /* Like use_variable except that it outputs the USEs after INSN
3061: instead of at the end of the insn-chain. */
3062:
3063: void
3064: use_variable_after (rtl, insn)
3065: rtx rtl, insn;
3066: {
3067: if (GET_CODE (rtl) == REG)
3068: /* This is a register variable. */
3069: emit_insn_after (gen_rtx (USE, VOIDmode, rtl), insn);
3070: else if (GET_CODE (rtl) == MEM
3071: && GET_CODE (XEXP (rtl, 0)) == REG
3072: && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
3073: || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
3074: && XEXP (rtl, 0) != current_function_internal_arg_pointer)
3075: /* This is a variable-sized structure. */
3076: emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)), insn);
3077: }
3078:
3079: int
3080: max_parm_reg_num ()
3081: {
3082: return max_parm_reg;
3083: }
3084:
3085: /* Return the first insn following those generated by `assign_parms'. */
3086:
3087: rtx
3088: get_first_nonparm_insn ()
3089: {
3090: if (last_parm_insn)
3091: return NEXT_INSN (last_parm_insn);
3092: return get_insns ();
3093: }
3094:
1.1.1.4 root 3095: /* Return the first NOTE_INSN_BLOCK_BEG note in the function.
3096: Crash if there is none. */
3097:
3098: rtx
3099: get_first_block_beg ()
3100: {
3101: register rtx searcher;
3102: register rtx insn = get_first_nonparm_insn ();
3103:
3104: for (searcher = insn; searcher; searcher = NEXT_INSN (searcher))
3105: if (GET_CODE (searcher) == NOTE
3106: && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG)
3107: return searcher;
3108:
3109: abort (); /* Invalid call to this function. (See comments above.) */
3110: return NULL_RTX;
3111: }
3112:
1.1.1.6 root 3113: /* Return 1 if EXP is an aggregate type (or a value with aggregate type).
3114: This means a type for which function calls must pass an address to the
3115: function or get an address back from the function.
3116: EXP may be a type node or an expression (whose type is tested). */
1.1 root 3117:
3118: int
3119: aggregate_value_p (exp)
3120: tree exp;
3121: {
1.1.1.4 root 3122: int i, regno, nregs;
3123: rtx reg;
1.1.1.6 root 3124: tree type;
3125: if (TREE_CODE_CLASS (TREE_CODE (exp)) == 't')
3126: type = exp;
3127: else
3128: type = TREE_TYPE (exp);
3129:
3130: if (RETURN_IN_MEMORY (type))
1.1 root 3131: return 1;
1.1.1.7 root 3132: if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
1.1 root 3133: return 1;
1.1.1.4 root 3134: /* Make sure we have suitable call-clobbered regs to return
3135: the value in; if not, we must return it in memory. */
1.1.1.6 root 3136: reg = hard_function_value (type, 0);
1.1.1.4 root 3137: regno = REGNO (reg);
1.1.1.6 root 3138: nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
1.1.1.4 root 3139: for (i = 0; i < nregs; i++)
3140: if (! call_used_regs[regno + i])
3141: return 1;
1.1 root 3142: return 0;
3143: }
3144:
3145: /* Assign RTL expressions to the function's parameters.
3146: This may involve copying them into registers and using
3147: those registers as the RTL for them.
3148:
3149: If SECOND_TIME is non-zero it means that this function is being
3150: called a second time. This is done by integrate.c when a function's
3151: compilation is deferred. We need to come back here in case the
3152: FUNCTION_ARG macro computes items needed for the rest of the compilation
3153: (such as changing which registers are fixed or caller-saved). But suppress
3154: writing any insns or setting DECL_RTL of anything in this case. */
3155:
3156: void
3157: assign_parms (fndecl, second_time)
3158: tree fndecl;
3159: int second_time;
3160: {
3161: register tree parm;
3162: register rtx entry_parm = 0;
3163: register rtx stack_parm = 0;
3164: CUMULATIVE_ARGS args_so_far;
1.1.1.8 root 3165: enum machine_mode promoted_mode, passed_mode;
3166: enum machine_mode nominal_mode, promoted_nominal_mode;
1.1.1.4 root 3167: int unsignedp;
1.1 root 3168: /* Total space needed so far for args on the stack,
3169: given as a constant and a tree-expression. */
3170: struct args_size stack_args_size;
3171: tree fntype = TREE_TYPE (fndecl);
3172: tree fnargs = DECL_ARGUMENTS (fndecl);
3173: /* This is used for the arg pointer when referring to stack args. */
3174: rtx internal_arg_pointer;
3175: /* This is a dummy PARM_DECL that we used for the function result if
3176: the function returns a structure. */
3177: tree function_result_decl = 0;
3178: int nparmregs = list_length (fnargs) + LAST_VIRTUAL_REGISTER + 1;
3179: int varargs_setup = 0;
1.1.1.5 root 3180: rtx conversion_insns = 0;
3181: /* FUNCTION_ARG may look at this variable. Since this is not
3182: expanding a call it will always be zero in this function. */
3183: int current_call_is_indirect = 0;
1.1 root 3184:
3185: /* Nonzero if the last arg is named `__builtin_va_alist',
3186: which is used on some machines for old-fashioned non-ANSI varargs.h;
3187: this should be stuck onto the stack as if it had arrived there. */
1.1.1.7 root 3188: int hide_last_arg
3189: = (current_function_varargs
3190: && fnargs
1.1 root 3191: && (parm = tree_last (fnargs)) != 0
3192: && DECL_NAME (parm)
3193: && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)),
3194: "__builtin_va_alist")));
3195:
3196: /* Nonzero if function takes extra anonymous args.
3197: This means the last named arg must be on the stack
3198: right before the anonymous ones. */
3199: int stdarg
3200: = (TYPE_ARG_TYPES (fntype) != 0
3201: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3202: != void_type_node));
3203:
1.1.1.8 root 3204: current_function_stdarg = stdarg;
3205:
1.1 root 3206: /* If the reg that the virtual arg pointer will be translated into is
3207: not a fixed reg or is the stack pointer, make a copy of the virtual
3208: arg pointer, and address parms via the copy. The frame pointer is
3209: considered fixed even though it is not marked as such.
3210:
3211: The second time through, simply use ap to avoid generating rtx. */
3212:
3213: if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
3214: || ! (fixed_regs[ARG_POINTER_REGNUM]
3215: || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))
3216: && ! second_time)
3217: internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
3218: else
3219: internal_arg_pointer = virtual_incoming_args_rtx;
3220: current_function_internal_arg_pointer = internal_arg_pointer;
3221:
3222: stack_args_size.constant = 0;
3223: stack_args_size.var = 0;
3224:
3225: /* If struct value address is treated as the first argument, make it so. */
3226: if (aggregate_value_p (DECL_RESULT (fndecl))
3227: && ! current_function_returns_pcc_struct
3228: && struct_value_incoming_rtx == 0)
3229: {
3230: tree type = build_pointer_type (fntype);
3231:
1.1.1.4 root 3232: function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
1.1 root 3233:
3234: DECL_ARG_TYPE (function_result_decl) = type;
3235: TREE_CHAIN (function_result_decl) = fnargs;
3236: fnargs = function_result_decl;
3237: }
3238:
3239: parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx));
1.1.1.7 root 3240: bzero ((char *) parm_reg_stack_loc, nparmregs * sizeof (rtx));
1.1 root 3241:
3242: #ifdef INIT_CUMULATIVE_INCOMING_ARGS
1.1.1.5 root 3243: INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
1.1 root 3244: #else
1.1.1.5 root 3245: INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX);
1.1 root 3246: #endif
3247:
3248: /* We haven't yet found an argument that we must push and pretend the
3249: caller did. */
3250: current_function_pretend_args_size = 0;
3251:
3252: for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
3253: {
1.1.1.7 root 3254: int aggregate = AGGREGATE_TYPE_P (TREE_TYPE (parm));
1.1 root 3255: struct args_size stack_offset;
3256: struct args_size arg_size;
3257: int passed_pointer = 0;
1.1.1.8 root 3258: int did_conversion = 0;
1.1 root 3259: tree passed_type = DECL_ARG_TYPE (parm);
1.1.1.8 root 3260: tree nominal_type = TREE_TYPE (parm);
1.1 root 3261:
3262: /* Set LAST_NAMED if this is last named arg before some
3263: anonymous args. We treat it as if it were anonymous too. */
3264: int last_named = ((TREE_CHAIN (parm) == 0
3265: || DECL_NAME (TREE_CHAIN (parm)) == 0)
1.1.1.7 root 3266: && (stdarg || current_function_varargs));
1.1 root 3267:
3268: if (TREE_TYPE (parm) == error_mark_node
3269: /* This can happen after weird syntax errors
3270: or if an enum type is defined among the parms. */
3271: || TREE_CODE (parm) != PARM_DECL
3272: || passed_type == NULL)
3273: {
1.1.1.4 root 3274: DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = gen_rtx (MEM, BLKmode,
3275: const0_rtx);
1.1 root 3276: TREE_USED (parm) = 1;
3277: continue;
3278: }
3279:
3280: /* For varargs.h function, save info about regs and stack space
3281: used by the individual args, not including the va_alist arg. */
1.1.1.7 root 3282: if (hide_last_arg && last_named)
1.1 root 3283: current_function_args_info = args_so_far;
3284:
3285: /* Find mode of arg as it is passed, and mode of arg
3286: as it should be during execution of this function. */
3287: passed_mode = TYPE_MODE (passed_type);
1.1.1.8 root 3288: nominal_mode = TYPE_MODE (nominal_type);
1.1 root 3289:
1.1.1.4 root 3290: /* If the parm's mode is VOID, its value doesn't matter,
3291: and avoid the usual things like emit_move_insn that could crash. */
3292: if (nominal_mode == VOIDmode)
3293: {
3294: DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = const0_rtx;
3295: continue;
3296: }
3297:
1.1.1.7 root 3298: /* If the parm is to be passed as a transparent union, use the
3299: type of the first field for the tests below. We have already
3300: verified that the modes are the same. */
3301: if (DECL_TRANSPARENT_UNION (parm)
3302: || TYPE_TRANSPARENT_UNION (passed_type))
3303: passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
3304:
1.1.1.6 root 3305: /* See if this arg was passed by invisible reference. It is if
3306: it is an object whose size depends on the contents of the
3307: object itself or if the machine requires these objects be passed
3308: that way. */
3309:
3310: if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
3311: && contains_placeholder_p (TYPE_SIZE (passed_type)))
1.1.1.8 root 3312: || TREE_ADDRESSABLE (passed_type)
1.1 root 3313: #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
1.1.1.6 root 3314: || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
3315: passed_type, ! last_named)
3316: #endif
3317: )
1.1 root 3318: {
1.1.1.8 root 3319: passed_type = nominal_type = build_pointer_type (passed_type);
1.1 root 3320: passed_pointer = 1;
3321: passed_mode = nominal_mode = Pmode;
3322: }
3323:
1.1.1.4 root 3324: promoted_mode = passed_mode;
3325:
3326: #ifdef PROMOTE_FUNCTION_ARGS
3327: /* Compute the mode in which the arg is actually extended to. */
1.1.1.7 root 3328: promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
1.1.1.4 root 3329: #endif
3330:
1.1 root 3331: /* Let machine desc say which reg (if any) the parm arrives in.
3332: 0 means it arrives on the stack. */
3333: #ifdef FUNCTION_INCOMING_ARG
1.1.1.4 root 3334: entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
1.1 root 3335: passed_type, ! last_named);
3336: #else
1.1.1.4 root 3337: entry_parm = FUNCTION_ARG (args_so_far, promoted_mode,
1.1 root 3338: passed_type, ! last_named);
3339: #endif
3340:
1.1.1.8 root 3341: if (entry_parm == 0)
3342: promoted_mode = passed_mode;
1.1.1.4 root 3343:
1.1 root 3344: #ifdef SETUP_INCOMING_VARARGS
3345: /* If this is the last named parameter, do any required setup for
3346: varargs or stdargs. We need to know about the case of this being an
3347: addressable type, in which case we skip the registers it
3348: would have arrived in.
3349:
3350: For stdargs, LAST_NAMED will be set for two parameters, the one that
3351: is actually the last named, and the dummy parameter. We only
3352: want to do this action once.
3353:
3354: Also, indicate when RTL generation is to be suppressed. */
3355: if (last_named && !varargs_setup)
3356: {
1.1.1.8 root 3357: SETUP_INCOMING_VARARGS (args_so_far, promoted_mode, passed_type,
1.1 root 3358: current_function_pretend_args_size,
3359: second_time);
3360: varargs_setup = 1;
3361: }
3362: #endif
3363:
3364: /* Determine parm's home in the stack,
3365: in case it arrives in the stack or we should pretend it did.
3366:
3367: Compute the stack position and rtx where the argument arrives
3368: and its size.
3369:
3370: There is one complexity here: If this was a parameter that would
3371: have been passed in registers, but wasn't only because it is
3372: __builtin_va_alist, we want locate_and_pad_parm to treat it as if
3373: it came in a register so that REG_PARM_STACK_SPACE isn't skipped.
3374: In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
3375: 0 as it was the previous time. */
3376:
1.1.1.8 root 3377: locate_and_pad_parm (promoted_mode, passed_type,
1.1 root 3378: #ifdef STACK_PARMS_IN_REG_PARM_AREA
3379: 1,
3380: #else
3381: #ifdef FUNCTION_INCOMING_ARG
1.1.1.8 root 3382: FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
1.1 root 3383: passed_type,
3384: (! last_named
3385: || varargs_setup)) != 0,
3386: #else
1.1.1.8 root 3387: FUNCTION_ARG (args_so_far, promoted_mode,
1.1 root 3388: passed_type,
3389: ! last_named || varargs_setup) != 0,
3390: #endif
3391: #endif
3392: fndecl, &stack_args_size, &stack_offset, &arg_size);
3393:
3394: if (! second_time)
3395: {
3396: rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
3397:
3398: if (offset_rtx == const0_rtx)
1.1.1.8 root 3399: stack_parm = gen_rtx (MEM, promoted_mode, internal_arg_pointer);
1.1 root 3400: else
1.1.1.8 root 3401: stack_parm = gen_rtx (MEM, promoted_mode,
1.1 root 3402: gen_rtx (PLUS, Pmode,
3403: internal_arg_pointer, offset_rtx));
3404:
3405: /* If this is a memory ref that contains aggregate components,
3406: mark it as such for cse and loop optimize. */
3407: MEM_IN_STRUCT_P (stack_parm) = aggregate;
3408: }
3409:
3410: /* If this parameter was passed both in registers and in the stack,
3411: use the copy on the stack. */
1.1.1.8 root 3412: if (MUST_PASS_IN_STACK (promoted_mode, passed_type))
1.1 root 3413: entry_parm = 0;
3414:
1.1.1.5 root 3415: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1.1 root 3416: /* If this parm was passed part in regs and part in memory,
3417: pretend it arrived entirely in memory
3418: by pushing the register-part onto the stack.
3419:
3420: In the special case of a DImode or DFmode that is split,
3421: we could put it together in a pseudoreg directly,
3422: but for now that's not worth bothering with. */
3423:
3424: if (entry_parm)
3425: {
1.1.1.8 root 3426: int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
1.1.1.5 root 3427: passed_type, ! last_named);
1.1 root 3428:
3429: if (nregs > 0)
3430: {
3431: current_function_pretend_args_size
3432: = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
3433: / (PARM_BOUNDARY / BITS_PER_UNIT)
3434: * (PARM_BOUNDARY / BITS_PER_UNIT));
3435:
3436: if (! second_time)
3437: move_block_from_reg (REGNO (entry_parm),
1.1.1.6 root 3438: validize_mem (stack_parm), nregs,
3439: int_size_in_bytes (TREE_TYPE (parm)));
1.1 root 3440: entry_parm = stack_parm;
3441: }
3442: }
1.1.1.5 root 3443: #endif
1.1 root 3444:
3445: /* If we didn't decide this parm came in a register,
3446: by default it came on the stack. */
3447: if (entry_parm == 0)
3448: entry_parm = stack_parm;
3449:
3450: /* Record permanently how this parm was passed. */
3451: if (! second_time)
3452: DECL_INCOMING_RTL (parm) = entry_parm;
3453:
3454: /* If there is actually space on the stack for this parm,
3455: count it in stack_args_size; otherwise set stack_parm to 0
3456: to indicate there is no preallocated stack slot for the parm. */
3457:
3458: if (entry_parm == stack_parm
1.1.1.3 root 3459: #if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
1.1 root 3460: /* On some machines, even if a parm value arrives in a register
1.1.1.3 root 3461: there is still an (uninitialized) stack slot allocated for it.
3462:
3463: ??? When MAYBE_REG_PARM_STACK_SPACE is defined, we can't tell
3464: whether this parameter already has a stack slot allocated,
3465: because an arg block exists only if current_function_args_size
1.1.1.8 root 3466: is larger than some threshold, and we haven't calculated that
1.1.1.3 root 3467: yet. So, for now, we just assume that stack slots never exist
3468: in this case. */
1.1 root 3469: || REG_PARM_STACK_SPACE (fndecl) > 0
3470: #endif
3471: )
3472: {
3473: stack_args_size.constant += arg_size.constant;
3474: if (arg_size.var)
3475: ADD_PARM_SIZE (stack_args_size, arg_size.var);
3476: }
3477: else
3478: /* No stack slot was pushed for this parm. */
3479: stack_parm = 0;
3480:
3481: /* Update info on where next arg arrives in registers. */
3482:
1.1.1.8 root 3483: FUNCTION_ARG_ADVANCE (args_so_far, promoted_mode,
1.1 root 3484: passed_type, ! last_named);
3485:
3486: /* If this is our second time through, we are done with this parm. */
3487: if (second_time)
3488: continue;
3489:
1.1.1.3 root 3490: /* If we can't trust the parm stack slot to be aligned enough
3491: for its ultimate type, don't use that slot after entry.
3492: We'll make another stack slot, if we need one. */
3493: {
3494: int thisparm_boundary
1.1.1.8 root 3495: = FUNCTION_ARG_BOUNDARY (promoted_mode, passed_type);
1.1.1.3 root 3496:
3497: if (GET_MODE_ALIGNMENT (nominal_mode) > thisparm_boundary)
3498: stack_parm = 0;
3499: }
3500:
1.1.1.6 root 3501: /* If parm was passed in memory, and we need to convert it on entry,
3502: don't store it back in that same slot. */
3503: if (entry_parm != 0
3504: && nominal_mode != BLKmode && nominal_mode != passed_mode)
3505: stack_parm = 0;
3506:
3507: #if 0
1.1 root 3508: /* Now adjust STACK_PARM to the mode and precise location
3509: where this parameter should live during execution,
3510: if we discover that it must live in the stack during execution.
3511: To make debuggers happier on big-endian machines, we store
3512: the value in the last bytes of the space available. */
3513:
3514: if (nominal_mode != BLKmode && nominal_mode != passed_mode
3515: && stack_parm != 0)
3516: {
3517: rtx offset_rtx;
3518:
1.1.1.8 root 3519: if (BYTES_BIG_ENDIAN
3520: && GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
1.1 root 3521: stack_offset.constant += (GET_MODE_SIZE (passed_mode)
3522: - GET_MODE_SIZE (nominal_mode));
3523:
3524: offset_rtx = ARGS_SIZE_RTX (stack_offset);
3525: if (offset_rtx == const0_rtx)
3526: stack_parm = gen_rtx (MEM, nominal_mode, internal_arg_pointer);
3527: else
3528: stack_parm = gen_rtx (MEM, nominal_mode,
3529: gen_rtx (PLUS, Pmode,
3530: internal_arg_pointer, offset_rtx));
3531:
3532: /* If this is a memory ref that contains aggregate components,
3533: mark it as such for cse and loop optimize. */
3534: MEM_IN_STRUCT_P (stack_parm) = aggregate;
3535: }
1.1.1.6 root 3536: #endif /* 0 */
1.1 root 3537:
1.1.1.8 root 3538: #ifdef STACK_REGS
3539: /* We need this "use" info, because the gcc-register->stack-register
3540: converter in reg-stack.c needs to know which registers are active
3541: at the start of the function call. The actual parameter loading
3542: instructions are not always available then anymore, since they might
3543: have been optimised away. */
3544:
3545: if (GET_CODE (entry_parm) == REG && !(hide_last_arg && last_named))
3546: emit_insn (gen_rtx (USE, GET_MODE (entry_parm), entry_parm));
3547: #endif
3548:
1.1 root 3549: /* ENTRY_PARM is an RTX for the parameter as it arrives,
3550: in the mode in which it arrives.
3551: STACK_PARM is an RTX for a stack slot where the parameter can live
3552: during the function (in case we want to put it there).
3553: STACK_PARM is 0 if no stack slot was pushed for it.
3554:
3555: Now output code if necessary to convert ENTRY_PARM to
3556: the type in which this function declares it,
3557: and store that result in an appropriate place,
3558: which may be a pseudo reg, may be STACK_PARM,
3559: or may be a local stack slot if STACK_PARM is 0.
3560:
3561: Set DECL_RTL to that place. */
3562:
3563: if (nominal_mode == BLKmode)
3564: {
3565: /* If a BLKmode arrives in registers, copy it to a stack slot. */
3566: if (GET_CODE (entry_parm) == REG)
3567: {
1.1.1.8 root 3568: int size_stored
3569: = CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)),
3570: UNITS_PER_WORD);
1.1 root 3571:
3572: /* Note that we will be storing an integral number of words.
3573: So we have to be careful to ensure that we allocate an
3574: integral number of words. We do this below in the
3575: assign_stack_local if space was not allocated in the argument
3576: list. If it was, this will not work if PARM_BOUNDARY is not
3577: a multiple of BITS_PER_WORD. It isn't clear how to fix this
3578: if it becomes a problem. */
3579:
3580: if (stack_parm == 0)
1.1.1.4 root 3581: {
3582: stack_parm
1.1.1.8 root 3583: = assign_stack_local (GET_MODE (entry_parm),
3584: size_stored, 0);
3585:
3586: /* If this is a memory ref that contains aggregate
3587: components, mark it as such for cse and loop optimize. */
1.1.1.4 root 3588: MEM_IN_STRUCT_P (stack_parm) = aggregate;
3589: }
3590:
1.1 root 3591: else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
3592: abort ();
3593:
1.1.1.7 root 3594: if (TREE_READONLY (parm))
3595: RTX_UNCHANGING_P (stack_parm) = 1;
3596:
1.1 root 3597: move_block_from_reg (REGNO (entry_parm),
3598: validize_mem (stack_parm),
1.1.1.6 root 3599: size_stored / UNITS_PER_WORD,
3600: int_size_in_bytes (TREE_TYPE (parm)));
1.1 root 3601: }
3602: DECL_RTL (parm) = stack_parm;
3603: }
1.1.1.4 root 3604: else if (! ((obey_regdecls && ! DECL_REGISTER (parm)
3605: && ! DECL_INLINE (fndecl))
1.1 root 3606: /* layout_decl may set this. */
3607: || TREE_ADDRESSABLE (parm)
3608: || TREE_SIDE_EFFECTS (parm)
3609: /* If -ffloat-store specified, don't put explicit
3610: float variables into registers. */
3611: || (flag_float_store
3612: && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))
3613: /* Always assign pseudo to structure return or item passed
3614: by invisible reference. */
3615: || passed_pointer || parm == function_result_decl)
3616: {
1.1.1.4 root 3617: /* Store the parm in a pseudoregister during the function, but we
3618: may need to do it in a wider mode. */
3619:
3620: register rtx parmreg;
1.1.1.7 root 3621: int regno, regnoi, regnor;
1.1.1.4 root 3622:
3623: unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
1.1 root 3624:
1.1.1.8 root 3625: promoted_nominal_mode
3626: = promote_mode (TREE_TYPE (parm), nominal_mode, &unsignedp, 0);
3627:
3628: parmreg = gen_reg_rtx (promoted_nominal_mode);
1.1 root 3629: REG_USERVAR_P (parmreg) = 1;
3630:
3631: /* If this was an item that we received a pointer to, set DECL_RTL
3632: appropriately. */
3633: if (passed_pointer)
3634: {
1.1.1.8 root 3635: DECL_RTL (parm)
3636: = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
1.1 root 3637: MEM_IN_STRUCT_P (DECL_RTL (parm)) = aggregate;
3638: }
3639: else
3640: DECL_RTL (parm) = parmreg;
3641:
3642: /* Copy the value into the register. */
1.1.1.8 root 3643: if (nominal_mode != passed_mode
3644: || promoted_nominal_mode != promoted_mode)
1.1.1.2 root 3645: {
1.1.1.8 root 3646: /* ENTRY_PARM has been converted to PROMOTED_MODE, its
3647: mode, by the caller. We now have to convert it to
3648: NOMINAL_MODE, if different. However, PARMREG may be in
3649: a diffent mode than NOMINAL_MODE if it is being stored
3650: promoted.
3651:
3652: If ENTRY_PARM is a hard register, it might be in a register
1.1.1.2 root 3653: not valid for operating in its mode (e.g., an odd-numbered
3654: register for a DFmode). In that case, moves are the only
3655: thing valid, so we can't do a convert from there. This
3656: occurs when the calling sequence allow such misaligned
1.1.1.5 root 3657: usages.
3658:
3659: In addition, the conversion may involve a call, which could
3660: clobber parameters which haven't been copied to pseudo
3661: registers yet. Therefore, we must first copy the parm to
3662: a pseudo reg here, and save the conversion until after all
3663: parameters have been moved. */
3664:
3665: rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
3666:
3667: emit_move_insn (tempreg, validize_mem (entry_parm));
3668:
3669: push_to_sequence (conversion_insns);
1.1.1.8 root 3670: tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
3671:
3672: expand_assignment (parm,
3673: make_tree (nominal_type, tempreg), 0, 0);
1.1.1.5 root 3674: conversion_insns = get_insns ();
1.1.1.8 root 3675: did_conversion = 1;
1.1.1.5 root 3676: end_sequence ();
1.1.1.2 root 3677: }
1.1 root 3678: else
3679: emit_move_insn (parmreg, validize_mem (entry_parm));
3680:
1.1.1.4 root 3681: /* If we were passed a pointer but the actual value
3682: can safely live in a register, put it in one. */
3683: if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
3684: && ! ((obey_regdecls && ! DECL_REGISTER (parm)
3685: && ! DECL_INLINE (fndecl))
3686: /* layout_decl may set this. */
3687: || TREE_ADDRESSABLE (parm)
3688: || TREE_SIDE_EFFECTS (parm)
3689: /* If -ffloat-store specified, don't put explicit
3690: float variables into registers. */
3691: || (flag_float_store
3692: && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)))
3693: {
3694: /* We can't use nominal_mode, because it will have been set to
3695: Pmode above. We must use the actual mode of the parm. */
3696: parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
1.1.1.7 root 3697: REG_USERVAR_P (parmreg) = 1;
1.1.1.4 root 3698: emit_move_insn (parmreg, DECL_RTL (parm));
3699: DECL_RTL (parm) = parmreg;
1.1.1.6 root 3700: /* STACK_PARM is the pointer, not the parm, and PARMREG is
3701: now the parm. */
3702: stack_parm = 0;
1.1.1.4 root 3703: }
1.1.1.5 root 3704: #ifdef FUNCTION_ARG_CALLEE_COPIES
3705: /* If we are passed an arg by reference and it is our responsibility
3706: to make a copy, do it now.
3707: PASSED_TYPE and PASSED mode now refer to the pointer, not the
3708: original argument, so we must recreate them in the call to
3709: FUNCTION_ARG_CALLEE_COPIES. */
3710: /* ??? Later add code to handle the case that if the argument isn't
3711: modified, don't do the copy. */
3712:
3713: else if (passed_pointer
3714: && FUNCTION_ARG_CALLEE_COPIES (args_so_far,
3715: TYPE_MODE (DECL_ARG_TYPE (parm)),
3716: DECL_ARG_TYPE (parm),
1.1.1.8 root 3717: ! last_named)
3718: && ! TREE_ADDRESSABLE (DECL_ARG_TYPE (parm)))
1.1.1.5 root 3719: {
3720: rtx copy;
3721: tree type = DECL_ARG_TYPE (parm);
3722:
3723: /* This sequence may involve a library call perhaps clobbering
3724: registers that haven't been copied to pseudos yet. */
3725:
3726: push_to_sequence (conversion_insns);
3727:
3728: if (TYPE_SIZE (type) == 0
3729: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
1.1.1.7 root 3730: /* This is a variable sized object. */
3731: copy = gen_rtx (MEM, BLKmode,
3732: allocate_dynamic_stack_space
3733: (expr_size (parm), NULL_RTX,
3734: TYPE_ALIGN (type)));
1.1.1.5 root 3735: else
1.1.1.7 root 3736: copy = assign_stack_temp (TYPE_MODE (type),
3737: int_size_in_bytes (type), 1);
1.1.1.8 root 3738: MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
1.1.1.5 root 3739:
3740: store_expr (parm, copy, 0);
3741: emit_move_insn (parmreg, XEXP (copy, 0));
3742: conversion_insns = get_insns ();
1.1.1.8 root 3743: did_conversion = 1;
1.1.1.5 root 3744: end_sequence ();
3745: }
3746: #endif /* FUNCTION_ARG_CALLEE_COPIES */
1.1.1.4 root 3747:
1.1 root 3748: /* In any case, record the parm's desired stack location
1.1.1.6 root 3749: in case we later discover it must live in the stack.
3750:
3751: If it is a COMPLEX value, store the stack location for both
3752: halves. */
3753:
3754: if (GET_CODE (parmreg) == CONCAT)
3755: regno = MAX (REGNO (XEXP (parmreg, 0)), REGNO (XEXP (parmreg, 1)));
3756: else
3757: regno = REGNO (parmreg);
3758:
3759: if (regno >= nparmregs)
1.1 root 3760: {
3761: rtx *new;
1.1.1.6 root 3762: int old_nparmregs = nparmregs;
3763:
3764: nparmregs = regno + 5;
1.1 root 3765: new = (rtx *) oballoc (nparmregs * sizeof (rtx));
1.1.1.7 root 3766: bcopy ((char *) parm_reg_stack_loc, (char *) new,
3767: old_nparmregs * sizeof (rtx));
3768: bzero ((char *) (new + old_nparmregs),
1.1.1.6 root 3769: (nparmregs - old_nparmregs) * sizeof (rtx));
1.1 root 3770: parm_reg_stack_loc = new;
3771: }
1.1.1.6 root 3772:
3773: if (GET_CODE (parmreg) == CONCAT)
3774: {
3775: enum machine_mode submode = GET_MODE (XEXP (parmreg, 0));
3776:
1.1.1.7 root 3777: regnor = REGNO (gen_realpart (submode, parmreg));
3778: regnoi = REGNO (gen_imagpart (submode, parmreg));
3779:
1.1.1.6 root 3780: if (stack_parm != 0)
3781: {
1.1.1.7 root 3782: parm_reg_stack_loc[regnor]
3783: = gen_realpart (submode, stack_parm);
3784: parm_reg_stack_loc[regnoi]
3785: = gen_imagpart (submode, stack_parm);
1.1.1.6 root 3786: }
3787: else
3788: {
1.1.1.7 root 3789: parm_reg_stack_loc[regnor] = 0;
3790: parm_reg_stack_loc[regnoi] = 0;
1.1.1.6 root 3791: }
3792: }
3793: else
3794: parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
1.1 root 3795:
3796: /* Mark the register as eliminable if we did no conversion
3797: and it was copied from memory at a fixed offset,
3798: and the arg pointer was not copied to a pseudo-reg.
3799: If the arg pointer is a pseudo reg or the offset formed
3800: an invalid address, such memory-equivalences
3801: as we make here would screw up life analysis for it. */
3802: if (nominal_mode == passed_mode
1.1.1.8 root 3803: && ! did_conversion
1.1 root 3804: && GET_CODE (entry_parm) == MEM
1.1.1.3 root 3805: && entry_parm == stack_parm
1.1 root 3806: && stack_offset.var == 0
3807: && reg_mentioned_p (virtual_incoming_args_rtx,
3808: XEXP (entry_parm, 0)))
1.1.1.7 root 3809: {
3810: rtx linsn = get_last_insn ();
3811:
3812: /* Mark complex types separately. */
3813: if (GET_CODE (parmreg) == CONCAT)
3814: {
3815: REG_NOTES (linsn)
3816: = gen_rtx (EXPR_LIST, REG_EQUIV,
3817: parm_reg_stack_loc[regnoi], REG_NOTES (linsn));
3818:
3819: /* Now search backward for where we set the real part. */
3820: for (; linsn != 0
3821: && ! reg_referenced_p (parm_reg_stack_loc[regnor],
3822: PATTERN (linsn));
3823: linsn = prev_nonnote_insn (linsn))
3824: ;
3825:
3826: REG_NOTES (linsn)
3827: = gen_rtx (EXPR_LIST, REG_EQUIV,
3828: parm_reg_stack_loc[regnor], REG_NOTES (linsn));
3829: }
3830: else
3831: REG_NOTES (linsn)
3832: = gen_rtx (EXPR_LIST, REG_EQUIV,
3833: entry_parm, REG_NOTES (linsn));
3834: }
1.1 root 3835:
3836: /* For pointer data type, suggest pointer register. */
3837: if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
3838: mark_reg_pointer (parmreg);
3839: }
3840: else
3841: {
3842: /* Value must be stored in the stack slot STACK_PARM
3843: during function execution. */
3844:
1.1.1.8 root 3845: if (promoted_mode != nominal_mode)
1.1.1.2 root 3846: {
3847: /* Conversion is required. */
1.1.1.5 root 3848: rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
1.1.1.2 root 3849:
1.1.1.5 root 3850: emit_move_insn (tempreg, validize_mem (entry_parm));
3851:
3852: push_to_sequence (conversion_insns);
3853: entry_parm = convert_to_mode (nominal_mode, tempreg,
1.1.1.4 root 3854: TREE_UNSIGNED (TREE_TYPE (parm)));
1.1.1.5 root 3855: conversion_insns = get_insns ();
1.1.1.8 root 3856: did_conversion = 1;
1.1.1.5 root 3857: end_sequence ();
1.1.1.2 root 3858: }
1.1 root 3859:
3860: if (entry_parm != stack_parm)
3861: {
3862: if (stack_parm == 0)
1.1.1.4 root 3863: {
3864: stack_parm
3865: = assign_stack_local (GET_MODE (entry_parm),
3866: GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
3867: /* If this is a memory ref that contains aggregate components,
3868: mark it as such for cse and loop optimize. */
3869: MEM_IN_STRUCT_P (stack_parm) = aggregate;
3870: }
3871:
1.1.1.8 root 3872: if (promoted_mode != nominal_mode)
1.1.1.5 root 3873: {
3874: push_to_sequence (conversion_insns);
3875: emit_move_insn (validize_mem (stack_parm),
3876: validize_mem (entry_parm));
3877: conversion_insns = get_insns ();
3878: end_sequence ();
3879: }
3880: else
3881: emit_move_insn (validize_mem (stack_parm),
3882: validize_mem (entry_parm));
1.1 root 3883: }
3884:
3885: DECL_RTL (parm) = stack_parm;
3886: }
3887:
3888: /* If this "parameter" was the place where we are receiving the
3889: function's incoming structure pointer, set up the result. */
3890: if (parm == function_result_decl)
1.1.1.7 root 3891: {
3892: tree result = DECL_RESULT (fndecl);
3893: tree restype = TREE_TYPE (result);
3894:
3895: DECL_RTL (result)
3896: = gen_rtx (MEM, DECL_MODE (result), DECL_RTL (parm));
3897:
3898: MEM_IN_STRUCT_P (DECL_RTL (result)) = AGGREGATE_TYPE_P (restype);
3899: }
1.1 root 3900:
3901: if (TREE_THIS_VOLATILE (parm))
3902: MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
3903: if (TREE_READONLY (parm))
3904: RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
3905: }
3906:
1.1.1.5 root 3907: /* Output all parameter conversion instructions (possibly including calls)
3908: now that all parameters have been copied out of hard registers. */
3909: emit_insns (conversion_insns);
3910:
1.1 root 3911: max_parm_reg = max_reg_num ();
3912: last_parm_insn = get_last_insn ();
3913:
3914: current_function_args_size = stack_args_size.constant;
3915:
3916: /* Adjust function incoming argument size for alignment and
3917: minimum length. */
3918:
3919: #ifdef REG_PARM_STACK_SPACE
1.1.1.3 root 3920: #ifndef MAYBE_REG_PARM_STACK_SPACE
1.1 root 3921: current_function_args_size = MAX (current_function_args_size,
3922: REG_PARM_STACK_SPACE (fndecl));
3923: #endif
1.1.1.3 root 3924: #endif
1.1 root 3925:
3926: #ifdef STACK_BOUNDARY
3927: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
3928:
3929: current_function_args_size
3930: = ((current_function_args_size + STACK_BYTES - 1)
3931: / STACK_BYTES) * STACK_BYTES;
3932: #endif
3933:
3934: #ifdef ARGS_GROW_DOWNWARD
3935: current_function_arg_offset_rtx
1.1.1.4 root 3936: = (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant)
1.1 root 3937: : expand_expr (size_binop (MINUS_EXPR, stack_args_size.var,
3938: size_int (-stack_args_size.constant)),
1.1.1.4 root 3939: NULL_RTX, VOIDmode, 0));
1.1 root 3940: #else
3941: current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
3942: #endif
3943:
3944: /* See how many bytes, if any, of its args a function should try to pop
3945: on return. */
3946:
1.1.1.8 root 3947: current_function_pops_args = RETURN_POPS_ARGS (fndecl, TREE_TYPE (fndecl),
1.1 root 3948: current_function_args_size);
3949:
1.1.1.7 root 3950: /* For stdarg.h function, save info about
3951: regs and stack space used by the named args. */
1.1 root 3952:
1.1.1.7 root 3953: if (!hide_last_arg)
1.1 root 3954: current_function_args_info = args_so_far;
3955:
3956: /* Set the rtx used for the function return value. Put this in its
3957: own variable so any optimizers that need this information don't have
3958: to include tree.h. Do this here so it gets done when an inlined
3959: function gets output. */
3960:
3961: current_function_return_rtx = DECL_RTL (DECL_RESULT (fndecl));
3962: }
3963:
1.1.1.5 root 3964: /* Indicate whether REGNO is an incoming argument to the current function
3965: that was promoted to a wider mode. If so, return the RTX for the
3966: register (to get its mode). PMODE and PUNSIGNEDP are set to the mode
3967: that REGNO is promoted from and whether the promotion was signed or
3968: unsigned. */
3969:
3970: #ifdef PROMOTE_FUNCTION_ARGS
3971:
3972: rtx
3973: promoted_input_arg (regno, pmode, punsignedp)
3974: int regno;
3975: enum machine_mode *pmode;
3976: int *punsignedp;
3977: {
3978: tree arg;
3979:
3980: for (arg = DECL_ARGUMENTS (current_function_decl); arg;
3981: arg = TREE_CHAIN (arg))
3982: if (GET_CODE (DECL_INCOMING_RTL (arg)) == REG
1.1.1.8 root 3983: && REGNO (DECL_INCOMING_RTL (arg)) == regno
3984: && TYPE_MODE (DECL_ARG_TYPE (arg)) == TYPE_MODE (TREE_TYPE (arg)))
1.1.1.5 root 3985: {
3986: enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
3987: int unsignedp = TREE_UNSIGNED (TREE_TYPE (arg));
3988:
1.1.1.7 root 3989: mode = promote_mode (TREE_TYPE (arg), mode, &unsignedp, 1);
1.1.1.5 root 3990: if (mode == GET_MODE (DECL_INCOMING_RTL (arg))
3991: && mode != DECL_MODE (arg))
3992: {
3993: *pmode = DECL_MODE (arg);
3994: *punsignedp = unsignedp;
3995: return DECL_INCOMING_RTL (arg);
3996: }
3997: }
3998:
3999: return 0;
4000: }
4001:
4002: #endif
4003:
1.1 root 4004: /* Compute the size and offset from the start of the stacked arguments for a
4005: parm passed in mode PASSED_MODE and with type TYPE.
4006:
4007: INITIAL_OFFSET_PTR points to the current offset into the stacked
4008: arguments.
4009:
4010: The starting offset and size for this parm are returned in *OFFSET_PTR
4011: and *ARG_SIZE_PTR, respectively.
4012:
4013: IN_REGS is non-zero if the argument will be passed in registers. It will
4014: never be set if REG_PARM_STACK_SPACE is not defined.
4015:
4016: FNDECL is the function in which the argument was defined.
4017:
4018: There are two types of rounding that are done. The first, controlled by
4019: FUNCTION_ARG_BOUNDARY, forces the offset from the start of the argument
4020: list to be aligned to the specific boundary (in bits). This rounding
4021: affects the initial and starting offsets, but not the argument size.
4022:
4023: The second, controlled by FUNCTION_ARG_PADDING and PARM_BOUNDARY,
4024: optionally rounds the size of the parm to PARM_BOUNDARY. The
4025: initial offset is not affected by this rounding, while the size always
4026: is and the starting offset may be. */
4027:
4028: /* offset_ptr will be negative for ARGS_GROW_DOWNWARD case;
4029: initial_offset_ptr is positive because locate_and_pad_parm's
4030: callers pass in the total size of args so far as
4031: initial_offset_ptr. arg_size_ptr is always positive.*/
4032:
4033: void
4034: locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
4035: initial_offset_ptr, offset_ptr, arg_size_ptr)
4036: enum machine_mode passed_mode;
4037: tree type;
4038: int in_regs;
4039: tree fndecl;
4040: struct args_size *initial_offset_ptr;
4041: struct args_size *offset_ptr;
4042: struct args_size *arg_size_ptr;
4043: {
4044: tree sizetree
4045: = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
4046: enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
4047: int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
4048: int boundary_in_bytes = boundary / BITS_PER_UNIT;
4049: int reg_parm_stack_space = 0;
4050:
4051: #ifdef REG_PARM_STACK_SPACE
4052: /* If we have found a stack parm before we reach the end of the
4053: area reserved for registers, skip that area. */
4054: if (! in_regs)
4055: {
1.1.1.3 root 4056: #ifdef MAYBE_REG_PARM_STACK_SPACE
4057: reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
4058: #else
1.1 root 4059: reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
1.1.1.3 root 4060: #endif
1.1 root 4061: if (reg_parm_stack_space > 0)
4062: {
4063: if (initial_offset_ptr->var)
4064: {
4065: initial_offset_ptr->var
4066: = size_binop (MAX_EXPR, ARGS_SIZE_TREE (*initial_offset_ptr),
4067: size_int (reg_parm_stack_space));
4068: initial_offset_ptr->constant = 0;
4069: }
4070: else if (initial_offset_ptr->constant < reg_parm_stack_space)
4071: initial_offset_ptr->constant = reg_parm_stack_space;
4072: }
4073: }
4074: #endif /* REG_PARM_STACK_SPACE */
4075:
4076: arg_size_ptr->var = 0;
4077: arg_size_ptr->constant = 0;
4078:
4079: #ifdef ARGS_GROW_DOWNWARD
4080: if (initial_offset_ptr->var)
4081: {
4082: offset_ptr->constant = 0;
4083: offset_ptr->var = size_binop (MINUS_EXPR, integer_zero_node,
4084: initial_offset_ptr->var);
4085: }
4086: else
4087: {
4088: offset_ptr->constant = - initial_offset_ptr->constant;
4089: offset_ptr->var = 0;
4090: }
1.1.1.7 root 4091: if (where_pad != none
1.1 root 4092: && (TREE_CODE (sizetree) != INTEGER_CST
4093: || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
4094: sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
4095: SUB_PARM_SIZE (*offset_ptr, sizetree);
1.1.1.4 root 4096: if (where_pad != downward)
4097: pad_to_arg_alignment (offset_ptr, boundary);
1.1 root 4098: if (initial_offset_ptr->var)
4099: {
4100: arg_size_ptr->var = size_binop (MINUS_EXPR,
4101: size_binop (MINUS_EXPR,
4102: integer_zero_node,
4103: initial_offset_ptr->var),
4104: offset_ptr->var);
4105: }
4106: else
4107: {
4108: arg_size_ptr->constant = (- initial_offset_ptr->constant -
4109: offset_ptr->constant);
4110: }
4111: #else /* !ARGS_GROW_DOWNWARD */
4112: pad_to_arg_alignment (initial_offset_ptr, boundary);
4113: *offset_ptr = *initial_offset_ptr;
4114:
4115: #ifdef PUSH_ROUNDING
4116: if (passed_mode != BLKmode)
4117: sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
4118: #endif
4119:
1.1.1.8 root 4120: /* Pad_below needs the pre-rounded size to know how much to pad below
4121: so this must be done before rounding up. */
4122: if (where_pad == downward
4123: /* However, BLKmode args passed in regs have their padding done elsewhere.
4124: The stack slot must be able to hold the entire register. */
4125: && !(in_regs && passed_mode == BLKmode))
4126: pad_below (offset_ptr, passed_mode, sizetree);
4127:
1.1 root 4128: if (where_pad != none
4129: && (TREE_CODE (sizetree) != INTEGER_CST
4130: || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
4131: sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
4132:
4133: ADD_PARM_SIZE (*arg_size_ptr, sizetree);
4134: #endif /* ARGS_GROW_DOWNWARD */
4135: }
4136:
1.1.1.3 root 4137: /* Round the stack offset in *OFFSET_PTR up to a multiple of BOUNDARY.
4138: BOUNDARY is measured in bits, but must be a multiple of a storage unit. */
4139:
1.1 root 4140: static void
4141: pad_to_arg_alignment (offset_ptr, boundary)
4142: struct args_size *offset_ptr;
4143: int boundary;
4144: {
4145: int boundary_in_bytes = boundary / BITS_PER_UNIT;
4146:
4147: if (boundary > BITS_PER_UNIT)
4148: {
4149: if (offset_ptr->var)
4150: {
4151: offset_ptr->var =
4152: #ifdef ARGS_GROW_DOWNWARD
4153: round_down
4154: #else
4155: round_up
4156: #endif
4157: (ARGS_SIZE_TREE (*offset_ptr),
4158: boundary / BITS_PER_UNIT);
4159: offset_ptr->constant = 0; /*?*/
4160: }
4161: else
4162: offset_ptr->constant =
4163: #ifdef ARGS_GROW_DOWNWARD
4164: FLOOR_ROUND (offset_ptr->constant, boundary_in_bytes);
4165: #else
4166: CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
4167: #endif
4168: }
4169: }
4170:
4171: static void
4172: pad_below (offset_ptr, passed_mode, sizetree)
4173: struct args_size *offset_ptr;
4174: enum machine_mode passed_mode;
4175: tree sizetree;
4176: {
4177: if (passed_mode != BLKmode)
4178: {
4179: if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
4180: offset_ptr->constant
4181: += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
4182: / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
4183: - GET_MODE_SIZE (passed_mode));
4184: }
4185: else
4186: {
4187: if (TREE_CODE (sizetree) != INTEGER_CST
4188: || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
4189: {
4190: /* Round the size up to multiple of PARM_BOUNDARY bits. */
4191: tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
4192: /* Add it in. */
4193: ADD_PARM_SIZE (*offset_ptr, s2);
4194: SUB_PARM_SIZE (*offset_ptr, sizetree);
4195: }
4196: }
4197: }
4198:
4199: static tree
4200: round_down (value, divisor)
4201: tree value;
4202: int divisor;
4203: {
4204: return size_binop (MULT_EXPR,
4205: size_binop (FLOOR_DIV_EXPR, value, size_int (divisor)),
4206: size_int (divisor));
4207: }
4208:
4209: /* Walk the tree of blocks describing the binding levels within a function
4210: and warn about uninitialized variables.
4211: This is done after calling flow_analysis and before global_alloc
4212: clobbers the pseudo-regs to hard regs. */
4213:
4214: void
4215: uninitialized_vars_warning (block)
4216: tree block;
4217: {
4218: register tree decl, sub;
4219: for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
4220: {
4221: if (TREE_CODE (decl) == VAR_DECL
4222: /* These warnings are unreliable for and aggregates
4223: because assigning the fields one by one can fail to convince
4224: flow.c that the entire aggregate was initialized.
4225: Unions are troublesome because members may be shorter. */
1.1.1.7 root 4226: && ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
1.1 root 4227: && DECL_RTL (decl) != 0
4228: && GET_CODE (DECL_RTL (decl)) == REG
4229: && regno_uninitialized (REGNO (DECL_RTL (decl))))
4230: warning_with_decl (decl,
1.1.1.7 root 4231: "`%s' might be used uninitialized in this function");
1.1 root 4232: if (TREE_CODE (decl) == VAR_DECL
4233: && DECL_RTL (decl) != 0
4234: && GET_CODE (DECL_RTL (decl)) == REG
4235: && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
4236: warning_with_decl (decl,
1.1.1.7 root 4237: "variable `%s' might be clobbered by `longjmp' or `vfork'");
1.1 root 4238: }
4239: for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
4240: uninitialized_vars_warning (sub);
4241: }
4242:
4243: /* Do the appropriate part of uninitialized_vars_warning
4244: but for arguments instead of local variables. */
4245:
4246: void
1.1.1.8 root 4247: setjmp_args_warning ()
1.1 root 4248: {
4249: register tree decl;
4250: for (decl = DECL_ARGUMENTS (current_function_decl);
4251: decl; decl = TREE_CHAIN (decl))
4252: if (DECL_RTL (decl) != 0
4253: && GET_CODE (DECL_RTL (decl)) == REG
4254: && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
1.1.1.7 root 4255: warning_with_decl (decl, "argument `%s' might be clobbered by `longjmp' or `vfork'");
1.1 root 4256: }
4257:
4258: /* If this function call setjmp, put all vars into the stack
4259: unless they were declared `register'. */
4260:
4261: void
4262: setjmp_protect (block)
4263: tree block;
4264: {
4265: register tree decl, sub;
4266: for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
4267: if ((TREE_CODE (decl) == VAR_DECL
4268: || TREE_CODE (decl) == PARM_DECL)
4269: && DECL_RTL (decl) != 0
4270: && GET_CODE (DECL_RTL (decl)) == REG
1.1.1.2 root 4271: /* If this variable came from an inline function, it must be
4272: that it's life doesn't overlap the setjmp. If there was a
4273: setjmp in the function, it would already be in memory. We
4274: must exclude such variable because their DECL_RTL might be
4275: set to strange things such as virtual_stack_vars_rtx. */
4276: && ! DECL_FROM_INLINE (decl)
1.1 root 4277: && (
4278: #ifdef NON_SAVING_SETJMP
4279: /* If longjmp doesn't restore the registers,
4280: don't put anything in them. */
4281: NON_SAVING_SETJMP
4282: ||
4283: #endif
1.1.1.4 root 4284: ! DECL_REGISTER (decl)))
1.1 root 4285: put_var_into_stack (decl);
4286: for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
4287: setjmp_protect (sub);
4288: }
4289:
4290: /* Like the previous function, but for args instead of local variables. */
4291:
4292: void
4293: setjmp_protect_args ()
4294: {
4295: register tree decl, sub;
4296: for (decl = DECL_ARGUMENTS (current_function_decl);
4297: decl; decl = TREE_CHAIN (decl))
4298: if ((TREE_CODE (decl) == VAR_DECL
4299: || TREE_CODE (decl) == PARM_DECL)
4300: && DECL_RTL (decl) != 0
4301: && GET_CODE (DECL_RTL (decl)) == REG
4302: && (
4303: /* If longjmp doesn't restore the registers,
4304: don't put anything in them. */
4305: #ifdef NON_SAVING_SETJMP
4306: NON_SAVING_SETJMP
4307: ||
4308: #endif
1.1.1.4 root 4309: ! DECL_REGISTER (decl)))
1.1 root 4310: put_var_into_stack (decl);
4311: }
4312:
4313: /* Return the context-pointer register corresponding to DECL,
4314: or 0 if it does not need one. */
4315:
4316: rtx
4317: lookup_static_chain (decl)
4318: tree decl;
4319: {
4320: tree context = decl_function_context (decl);
4321: tree link;
4322:
4323: if (context == 0)
4324: return 0;
4325:
4326: /* We treat inline_function_decl as an alias for the current function
4327: because that is the inline function whose vars, types, etc.
4328: are being merged into the current function.
4329: See expand_inline_function. */
4330: if (context == current_function_decl || context == inline_function_decl)
4331: return virtual_stack_vars_rtx;
4332:
4333: for (link = context_display; link; link = TREE_CHAIN (link))
4334: if (TREE_PURPOSE (link) == context)
4335: return RTL_EXPR_RTL (TREE_VALUE (link));
4336:
4337: abort ();
4338: }
4339:
4340: /* Convert a stack slot address ADDR for variable VAR
4341: (from a containing function)
4342: into an address valid in this function (using a static chain). */
4343:
4344: rtx
4345: fix_lexical_addr (addr, var)
4346: rtx addr;
4347: tree var;
4348: {
4349: rtx basereg;
4350: int displacement;
4351: tree context = decl_function_context (var);
4352: struct function *fp;
4353: rtx base = 0;
4354:
4355: /* If this is the present function, we need not do anything. */
4356: if (context == current_function_decl || context == inline_function_decl)
4357: return addr;
4358:
4359: for (fp = outer_function_chain; fp; fp = fp->next)
4360: if (fp->decl == context)
4361: break;
4362:
4363: if (fp == 0)
4364: abort ();
4365:
4366: /* Decode given address as base reg plus displacement. */
4367: if (GET_CODE (addr) == REG)
4368: basereg = addr, displacement = 0;
4369: else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
4370: basereg = XEXP (addr, 0), displacement = INTVAL (XEXP (addr, 1));
4371: else
4372: abort ();
4373:
4374: /* We accept vars reached via the containing function's
4375: incoming arg pointer and via its stack variables pointer. */
4376: if (basereg == fp->internal_arg_pointer)
4377: {
4378: /* If reached via arg pointer, get the arg pointer value
4379: out of that function's stack frame.
4380:
4381: There are two cases: If a separate ap is needed, allocate a
4382: slot in the outer function for it and dereference it that way.
4383: This is correct even if the real ap is actually a pseudo.
4384: Otherwise, just adjust the offset from the frame pointer to
4385: compensate. */
4386:
4387: #ifdef NEED_SEPARATE_AP
4388: rtx addr;
4389:
4390: if (fp->arg_pointer_save_area == 0)
4391: fp->arg_pointer_save_area
4392: = assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
4393:
4394: addr = fix_lexical_addr (XEXP (fp->arg_pointer_save_area, 0), var);
4395: addr = memory_address (Pmode, addr);
4396:
4397: base = copy_to_reg (gen_rtx (MEM, Pmode, addr));
4398: #else
4399: displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
1.1.1.2 root 4400: base = lookup_static_chain (var);
1.1 root 4401: #endif
4402: }
4403:
4404: else if (basereg == virtual_stack_vars_rtx)
4405: {
4406: /* This is the same code as lookup_static_chain, duplicated here to
4407: avoid an extra call to decl_function_context. */
4408: tree link;
4409:
4410: for (link = context_display; link; link = TREE_CHAIN (link))
4411: if (TREE_PURPOSE (link) == context)
4412: {
4413: base = RTL_EXPR_RTL (TREE_VALUE (link));
4414: break;
4415: }
4416: }
4417:
4418: if (base == 0)
4419: abort ();
4420:
4421: /* Use same offset, relative to appropriate static chain or argument
4422: pointer. */
4423: return plus_constant (base, displacement);
4424: }
4425:
4426: /* Return the address of the trampoline for entering nested fn FUNCTION.
4427: If necessary, allocate a trampoline (in the stack frame)
4428: and emit rtl to initialize its contents (at entry to this function). */
4429:
4430: rtx
4431: trampoline_address (function)
4432: tree function;
4433: {
4434: tree link;
4435: tree rtlexp;
4436: rtx tramp;
4437: struct function *fp;
4438: tree fn_context;
4439:
4440: /* Find an existing trampoline and return it. */
4441: for (link = trampoline_list; link; link = TREE_CHAIN (link))
4442: if (TREE_PURPOSE (link) == function)
1.1.1.7 root 4443: return
4444: round_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0));
4445:
1.1 root 4446: for (fp = outer_function_chain; fp; fp = fp->next)
4447: for (link = fp->trampoline_list; link; link = TREE_CHAIN (link))
4448: if (TREE_PURPOSE (link) == function)
4449: {
4450: tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0),
4451: function);
4452: return round_trampoline_addr (tramp);
4453: }
4454:
4455: /* None exists; we must make one. */
4456:
4457: /* Find the `struct function' for the function containing FUNCTION. */
4458: fp = 0;
4459: fn_context = decl_function_context (function);
4460: if (fn_context != current_function_decl)
4461: for (fp = outer_function_chain; fp; fp = fp->next)
4462: if (fp->decl == fn_context)
4463: break;
4464:
4465: /* Allocate run-time space for this trampoline
4466: (usually in the defining function's stack frame). */
4467: #ifdef ALLOCATE_TRAMPOLINE
4468: tramp = ALLOCATE_TRAMPOLINE (fp);
4469: #else
4470: /* If rounding needed, allocate extra space
4471: to ensure we have TRAMPOLINE_SIZE bytes left after rounding up. */
4472: #ifdef TRAMPOLINE_ALIGNMENT
4473: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE + TRAMPOLINE_ALIGNMENT - 1)
4474: #else
4475: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
4476: #endif
4477: if (fp != 0)
4478: tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp);
4479: else
4480: tramp = assign_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0);
4481: #endif
4482:
4483: /* Record the trampoline for reuse and note it for later initialization
4484: by expand_function_end. */
4485: if (fp != 0)
4486: {
1.1.1.6 root 4487: push_obstacks (fp->function_maybepermanent_obstack,
4488: fp->function_maybepermanent_obstack);
1.1 root 4489: rtlexp = make_node (RTL_EXPR);
4490: RTL_EXPR_RTL (rtlexp) = tramp;
4491: fp->trampoline_list = tree_cons (function, rtlexp, fp->trampoline_list);
4492: pop_obstacks ();
4493: }
4494: else
4495: {
4496: /* Make the RTL_EXPR node temporary, not momentary, so that the
4497: trampoline_list doesn't become garbage. */
4498: int momentary = suspend_momentary ();
4499: rtlexp = make_node (RTL_EXPR);
4500: resume_momentary (momentary);
4501:
4502: RTL_EXPR_RTL (rtlexp) = tramp;
4503: trampoline_list = tree_cons (function, rtlexp, trampoline_list);
4504: }
4505:
4506: tramp = fix_lexical_addr (XEXP (tramp, 0), function);
4507: return round_trampoline_addr (tramp);
4508: }
4509:
4510: /* Given a trampoline address,
4511: round it to multiple of TRAMPOLINE_ALIGNMENT. */
4512:
4513: static rtx
4514: round_trampoline_addr (tramp)
4515: rtx tramp;
4516: {
4517: #ifdef TRAMPOLINE_ALIGNMENT
4518: /* Round address up to desired boundary. */
4519: rtx temp = gen_reg_rtx (Pmode);
4520: temp = expand_binop (Pmode, add_optab, tramp,
1.1.1.4 root 4521: GEN_INT (TRAMPOLINE_ALIGNMENT - 1),
1.1 root 4522: temp, 0, OPTAB_LIB_WIDEN);
4523: tramp = expand_binop (Pmode, and_optab, temp,
1.1.1.4 root 4524: GEN_INT (- TRAMPOLINE_ALIGNMENT),
1.1 root 4525: temp, 0, OPTAB_LIB_WIDEN);
4526: #endif
4527: return tramp;
4528: }
4529:
1.1.1.4 root 4530: /* The functions identify_blocks and reorder_blocks provide a way to
4531: reorder the tree of BLOCK nodes, for optimizers that reshuffle or
4532: duplicate portions of the RTL code. Call identify_blocks before
4533: changing the RTL, and call reorder_blocks after. */
4534:
4535: /* Put all this function's BLOCK nodes into a vector, and return it.
4536: Also store in each NOTE for the beginning or end of a block
4537: the index of that block in the vector.
4538: The arguments are TOP_BLOCK, the top-level block of the function,
4539: and INSNS, the insn chain of the function. */
4540:
4541: tree *
4542: identify_blocks (top_block, insns)
4543: tree top_block;
4544: rtx insns;
4545: {
4546: int n_blocks;
4547: tree *block_vector;
4548: int *block_stack;
4549: int depth = 0;
4550: int next_block_number = 0;
4551: int current_block_number = 0;
4552: rtx insn;
4553:
4554: if (top_block == 0)
4555: return 0;
4556:
4557: n_blocks = all_blocks (top_block, 0);
4558: block_vector = (tree *) xmalloc (n_blocks * sizeof (tree));
4559: block_stack = (int *) alloca (n_blocks * sizeof (int));
4560:
4561: all_blocks (top_block, block_vector);
4562:
4563: for (insn = insns; insn; insn = NEXT_INSN (insn))
4564: if (GET_CODE (insn) == NOTE)
4565: {
4566: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
4567: {
4568: block_stack[depth++] = current_block_number;
4569: current_block_number = next_block_number;
4570: NOTE_BLOCK_NUMBER (insn) = next_block_number++;
4571: }
4572: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
4573: {
4574: current_block_number = block_stack[--depth];
4575: NOTE_BLOCK_NUMBER (insn) = current_block_number;
4576: }
4577: }
4578:
4579: return block_vector;
4580: }
4581:
4582: /* Given BLOCK_VECTOR which was returned by identify_blocks,
4583: and a revised instruction chain, rebuild the tree structure
4584: of BLOCK nodes to correspond to the new order of RTL.
4585: The new block tree is inserted below TOP_BLOCK.
4586: Returns the current top-level block. */
4587:
4588: tree
4589: reorder_blocks (block_vector, top_block, insns)
4590: tree *block_vector;
4591: tree top_block;
4592: rtx insns;
4593: {
4594: tree current_block = top_block;
4595: rtx insn;
4596:
4597: if (block_vector == 0)
4598: return top_block;
4599:
4600: /* Prune the old tree away, so that it doesn't get in the way. */
4601: BLOCK_SUBBLOCKS (current_block) = 0;
4602:
4603: for (insn = insns; insn; insn = NEXT_INSN (insn))
4604: if (GET_CODE (insn) == NOTE)
4605: {
4606: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
4607: {
4608: tree block = block_vector[NOTE_BLOCK_NUMBER (insn)];
4609: /* If we have seen this block before, copy it. */
4610: if (TREE_ASM_WRITTEN (block))
4611: block = copy_node (block);
4612: BLOCK_SUBBLOCKS (block) = 0;
4613: TREE_ASM_WRITTEN (block) = 1;
4614: BLOCK_SUPERCONTEXT (block) = current_block;
4615: BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
4616: BLOCK_SUBBLOCKS (current_block) = block;
4617: current_block = block;
4618: NOTE_SOURCE_FILE (insn) = 0;
4619: }
4620: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
4621: {
4622: BLOCK_SUBBLOCKS (current_block)
4623: = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
4624: current_block = BLOCK_SUPERCONTEXT (current_block);
4625: NOTE_SOURCE_FILE (insn) = 0;
4626: }
4627: }
4628:
4629: return current_block;
4630: }
4631:
4632: /* Reverse the order of elements in the chain T of blocks,
4633: and return the new head of the chain (old last element). */
4634:
4635: static tree
4636: blocks_nreverse (t)
4637: tree t;
4638: {
4639: register tree prev = 0, decl, next;
4640: for (decl = t; decl; decl = next)
4641: {
4642: next = BLOCK_CHAIN (decl);
4643: BLOCK_CHAIN (decl) = prev;
4644: prev = decl;
4645: }
4646: return prev;
4647: }
4648:
4649: /* Count the subblocks of BLOCK, and list them all into the vector VECTOR.
4650: Also clear TREE_ASM_WRITTEN in all blocks. */
4651:
4652: static int
4653: all_blocks (block, vector)
4654: tree block;
4655: tree *vector;
4656: {
4657: int n_blocks = 1;
4658: tree subblocks;
4659:
4660: TREE_ASM_WRITTEN (block) = 0;
4661: /* Record this block. */
4662: if (vector)
4663: vector[0] = block;
4664:
4665: /* Record the subblocks, and their subblocks. */
4666: for (subblocks = BLOCK_SUBBLOCKS (block);
4667: subblocks; subblocks = BLOCK_CHAIN (subblocks))
4668: n_blocks += all_blocks (subblocks, vector ? vector + n_blocks : 0);
4669:
4670: return n_blocks;
4671: }
4672:
1.1.1.6 root 4673: /* Build bytecode call descriptor for function SUBR. */
1.1.1.7 root 4674:
1.1.1.6 root 4675: rtx
4676: bc_build_calldesc (subr)
4677: tree subr;
4678: {
4679: tree calldesc = 0, arg;
4680: int nargs = 0;
4681:
4682: /* Build the argument description vector in reverse order. */
4683: DECL_ARGUMENTS (subr) = nreverse (DECL_ARGUMENTS (subr));
4684: nargs = 0;
4685:
4686: for (arg = DECL_ARGUMENTS (subr); arg; arg = TREE_CHAIN (arg))
4687: {
4688: ++nargs;
4689:
4690: calldesc = tree_cons ((tree) 0, size_in_bytes (TREE_TYPE (arg)), calldesc);
4691: calldesc = tree_cons ((tree) 0, bc_runtime_type_code (TREE_TYPE (arg)), calldesc);
4692: }
4693:
4694: DECL_ARGUMENTS (subr) = nreverse (DECL_ARGUMENTS (subr));
4695:
4696: /* Prepend the function's return type. */
4697: calldesc = tree_cons ((tree) 0,
4698: size_in_bytes (TREE_TYPE (TREE_TYPE (subr))),
4699: calldesc);
4700:
4701: calldesc = tree_cons ((tree) 0,
4702: bc_runtime_type_code (TREE_TYPE (TREE_TYPE (subr))),
4703: calldesc);
4704:
4705: /* Prepend the arg count. */
4706: calldesc = tree_cons ((tree) 0, build_int_2 (nargs, 0), calldesc);
4707:
4708: /* Output the call description vector and get its address. */
4709: calldesc = build_nt (CONSTRUCTOR, (tree) 0, calldesc);
4710: TREE_TYPE (calldesc) = build_array_type (integer_type_node,
4711: build_index_type (build_int_2 (nargs * 2, 0)));
4712:
4713: return output_constant_def (calldesc);
4714: }
4715:
4716:
1.1 root 4717: /* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node)
4718: and initialize static variables for generating RTL for the statements
4719: of the function. */
4720:
4721: void
4722: init_function_start (subr, filename, line)
4723: tree subr;
4724: char *filename;
4725: int line;
4726: {
4727: char *junk;
4728:
1.1.1.6 root 4729: if (output_bytecode)
4730: {
4731: this_function_decl = subr;
4732: this_function_calldesc = bc_build_calldesc (subr);
4733: local_vars_size = 0;
4734: stack_depth = 0;
4735: max_stack_depth = 0;
4736: stmt_expr_depth = 0;
4737: return;
4738: }
4739:
1.1 root 4740: init_stmt_for_function ();
4741:
4742: cse_not_expected = ! optimize;
4743:
4744: /* Caller save not needed yet. */
4745: caller_save_needed = 0;
4746:
4747: /* No stack slots have been made yet. */
4748: stack_slot_list = 0;
4749:
4750: /* There is no stack slot for handling nonlocal gotos. */
4751: nonlocal_goto_handler_slot = 0;
4752: nonlocal_goto_stack_level = 0;
4753:
4754: /* No labels have been declared for nonlocal use. */
4755: nonlocal_labels = 0;
4756:
4757: /* No function calls so far in this function. */
4758: function_call_count = 0;
4759:
4760: /* No parm regs have been allocated.
4761: (This is important for output_inline_function.) */
4762: max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
4763:
4764: /* Initialize the RTL mechanism. */
4765: init_emit ();
4766:
4767: /* Initialize the queue of pending postincrement and postdecrements,
4768: and some other info in expr.c. */
4769: init_expr ();
4770:
4771: /* We haven't done register allocation yet. */
4772: reg_renumber = 0;
4773:
4774: init_const_rtx_hash_table ();
4775:
4776: current_function_name = (*decl_printable_name) (subr, &junk);
4777:
4778: /* Nonzero if this is a nested function that uses a static chain. */
4779:
4780: current_function_needs_context
4781: = (decl_function_context (current_function_decl) != 0);
4782:
4783: /* Set if a call to setjmp is seen. */
4784: current_function_calls_setjmp = 0;
4785:
4786: /* Set if a call to longjmp is seen. */
4787: current_function_calls_longjmp = 0;
4788:
4789: current_function_calls_alloca = 0;
4790: current_function_has_nonlocal_label = 0;
1.1.1.6 root 4791: current_function_has_nonlocal_goto = 0;
1.1 root 4792: current_function_contains_functions = 0;
4793:
4794: current_function_returns_pcc_struct = 0;
4795: current_function_returns_struct = 0;
4796: current_function_epilogue_delay_list = 0;
4797: current_function_uses_const_pool = 0;
4798: current_function_uses_pic_offset_table = 0;
4799:
4800: /* We have not yet needed to make a label to jump to for tail-recursion. */
4801: tail_recursion_label = 0;
4802:
4803: /* We haven't had a need to make a save area for ap yet. */
4804:
4805: arg_pointer_save_area = 0;
4806:
4807: /* No stack slots allocated yet. */
4808: frame_offset = 0;
4809:
4810: /* No SAVE_EXPRs in this function yet. */
4811: save_expr_regs = 0;
4812:
4813: /* No RTL_EXPRs in this function yet. */
4814: rtl_expr_chain = 0;
4815:
4816: /* We have not allocated any temporaries yet. */
4817: temp_slots = 0;
4818: temp_slot_level = 0;
1.1.1.7 root 4819: target_temp_slot_level = 0;
1.1 root 4820:
4821: /* Within function body, compute a type's size as soon it is laid out. */
4822: immediate_size_expand++;
4823:
1.1.1.6 root 4824: /* We haven't made any trampolines for this function yet. */
4825: trampoline_list = 0;
4826:
1.1 root 4827: init_pending_stack_adjust ();
4828: inhibit_defer_pop = 0;
4829:
4830: current_function_outgoing_args_size = 0;
4831:
4832: /* Prevent ever trying to delete the first instruction of a function.
4833: Also tell final how to output a linenum before the function prologue. */
4834: emit_line_note (filename, line);
4835:
4836: /* Make sure first insn is a note even if we don't want linenums.
4837: This makes sure the first insn will never be deleted.
4838: Also, final expects a note to appear there. */
1.1.1.4 root 4839: emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1 root 4840:
4841: /* Set flags used by final.c. */
4842: if (aggregate_value_p (DECL_RESULT (subr)))
4843: {
4844: #ifdef PCC_STATIC_STRUCT_RETURN
1.1.1.5 root 4845: current_function_returns_pcc_struct = 1;
1.1 root 4846: #endif
1.1.1.5 root 4847: current_function_returns_struct = 1;
1.1 root 4848: }
4849:
4850: /* Warn if this value is an aggregate type,
4851: regardless of which calling convention we are using for it. */
4852: if (warn_aggregate_return
1.1.1.7 root 4853: && AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr))))
1.1 root 4854: warning ("function returns an aggregate");
4855:
4856: current_function_returns_pointer
1.1.1.8 root 4857: = POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
1.1 root 4858:
4859: /* Indicate that we need to distinguish between the return value of the
4860: present function and the return value of a function being called. */
4861: rtx_equal_function_value_matters = 1;
4862:
4863: /* Indicate that we have not instantiated virtual registers yet. */
4864: virtuals_instantiated = 0;
4865:
4866: /* Indicate we have no need of a frame pointer yet. */
4867: frame_pointer_needed = 0;
4868:
1.1.1.8 root 4869: /* By default assume not varargs or stdarg. */
1.1 root 4870: current_function_varargs = 0;
1.1.1.8 root 4871: current_function_stdarg = 0;
1.1 root 4872: }
4873:
4874: /* Indicate that the current function uses extra args
4875: not explicitly mentioned in the argument list in any fashion. */
4876:
4877: void
4878: mark_varargs ()
4879: {
4880: current_function_varargs = 1;
4881: }
4882:
4883: /* Expand a call to __main at the beginning of a possible main function. */
4884:
1.1.1.7 root 4885: #if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
4886: #undef HAS_INIT_SECTION
4887: #define HAS_INIT_SECTION
4888: #endif
4889:
1.1 root 4890: void
4891: expand_main_function ()
4892: {
1.1.1.6 root 4893: if (!output_bytecode)
4894: {
4895: /* The zero below avoids a possible parse error */
4896: 0;
1.1.1.7 root 4897: #if !defined (HAS_INIT_SECTION)
1.1.1.6 root 4898: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0,
4899: VOIDmode, 0);
1.1.1.7 root 4900: #endif /* not HAS_INIT_SECTION */
1.1.1.6 root 4901: }
1.1 root 4902: }
4903:
1.1.1.6 root 4904: extern struct obstack permanent_obstack;
4905:
4906: /* Expand start of bytecode function. See comment at
4907: expand_function_start below for details. */
4908:
4909: void
4910: bc_expand_function_start (subr, parms_have_cleanups)
4911: tree subr;
4912: int parms_have_cleanups;
4913: {
4914: char label[20], *name;
4915: static int nlab;
4916: tree thisarg;
4917: int argsz;
4918:
4919: if (TREE_PUBLIC (subr))
4920: bc_globalize_label (IDENTIFIER_POINTER (DECL_NAME (subr)));
4921:
4922: #ifdef DEBUG_PRINT_CODE
4923: fprintf (stderr, "\n<func %s>\n", IDENTIFIER_POINTER (DECL_NAME (subr)));
4924: #endif
4925:
4926: for (argsz = 0, thisarg = DECL_ARGUMENTS (subr); thisarg; thisarg = TREE_CHAIN (thisarg))
4927: {
4928: if (DECL_RTL (thisarg))
4929: abort (); /* Should be NULL here I think. */
4930: else if (TREE_CONSTANT (DECL_SIZE (thisarg)))
4931: {
4932: DECL_RTL (thisarg) = bc_gen_rtx ((char *) 0, argsz, (struct bc_label *) 0);
4933: argsz += TREE_INT_CST_LOW (DECL_SIZE (thisarg));
4934: }
4935: else
4936: {
4937: /* Variable-sized objects are pointers to their storage. */
4938: DECL_RTL (thisarg) = bc_gen_rtx ((char *) 0, argsz, (struct bc_label *) 0);
4939: argsz += POINTER_SIZE;
4940: }
4941: }
4942:
4943: bc_begin_function (bc_xstrdup (IDENTIFIER_POINTER (DECL_NAME (subr))));
4944:
4945: ASM_GENERATE_INTERNAL_LABEL (label, "LX", nlab);
4946:
4947: ++nlab;
4948: name = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
4949: this_function_callinfo = bc_gen_rtx (name, 0, (struct bc_label *) 0);
4950: this_function_bytecode =
4951: bc_emit_trampoline (BYTECODE_LABEL (this_function_callinfo));
4952: }
4953:
4954:
4955: /* Expand end of bytecode function. See details the comment of
4956: expand_function_end(), below. */
4957:
4958: void
4959: bc_expand_function_end ()
4960: {
4961: char *ptrconsts;
4962:
4963: expand_null_return ();
4964:
4965: /* Emit any fixup code. This must be done before the call to
4966: to BC_END_FUNCTION (), since that will cause the bytecode
4967: segment to be finished off and closed. */
4968:
1.1.1.7 root 4969: expand_fixups (NULL_RTX);
1.1.1.6 root 4970:
4971: ptrconsts = bc_end_function ();
4972:
4973: bc_align_const (2 /* INT_ALIGN */);
4974:
4975: /* If this changes also make sure to change bc-interp.h! */
4976:
4977: bc_emit_const_labeldef (BYTECODE_LABEL (this_function_callinfo));
4978: bc_emit_const ((char *) &max_stack_depth, sizeof max_stack_depth);
4979: bc_emit_const ((char *) &local_vars_size, sizeof local_vars_size);
4980: bc_emit_const_labelref (this_function_bytecode, 0);
4981: bc_emit_const_labelref (ptrconsts, 0);
4982: bc_emit_const_labelref (BYTECODE_LABEL (this_function_calldesc), 0);
4983: }
4984:
4985:
1.1 root 4986: /* Start the RTL for a new function, and set variables used for
4987: emitting RTL.
4988: SUBR is the FUNCTION_DECL node.
4989: PARMS_HAVE_CLEANUPS is nonzero if there are cleanups associated with
4990: the function's parameters, which must be run at any return statement. */
4991:
4992: void
4993: expand_function_start (subr, parms_have_cleanups)
4994: tree subr;
4995: int parms_have_cleanups;
4996: {
4997: register int i;
4998: tree tem;
4999: rtx last_ptr;
5000:
1.1.1.6 root 5001: if (output_bytecode)
5002: {
5003: bc_expand_function_start (subr, parms_have_cleanups);
5004: return;
5005: }
5006:
1.1 root 5007: /* Make sure volatile mem refs aren't considered
5008: valid operands of arithmetic insns. */
5009: init_recog_no_volatile ();
5010:
5011: /* If function gets a static chain arg, store it in the stack frame.
5012: Do this first, so it gets the first stack slot offset. */
5013: if (current_function_needs_context)
1.1.1.4 root 5014: {
5015: last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
1.1.1.7 root 5016:
5017: #ifdef SMALL_REGISTER_CLASSES
5018: /* Delay copying static chain if it is not a register to avoid
5019: conflicts with regs used for parameters. */
5020: if (GET_CODE (static_chain_incoming_rtx) == REG)
5021: #endif
5022: emit_move_insn (last_ptr, static_chain_incoming_rtx);
1.1.1.4 root 5023: }
1.1 root 5024:
5025: /* If the parameters of this function need cleaning up, get a label
5026: for the beginning of the code which executes those cleanups. This must
5027: be done before doing anything with return_label. */
5028: if (parms_have_cleanups)
5029: cleanup_label = gen_label_rtx ();
5030: else
5031: cleanup_label = 0;
5032:
5033: /* Make the label for return statements to jump to, if this machine
5034: does not have a one-instruction return and uses an epilogue,
5035: or if it returns a structure, or if it has parm cleanups. */
5036: #ifdef HAVE_return
5037: if (cleanup_label == 0 && HAVE_return
5038: && ! current_function_returns_pcc_struct
5039: && ! (current_function_returns_struct && ! optimize))
5040: return_label = 0;
5041: else
5042: return_label = gen_label_rtx ();
5043: #else
5044: return_label = gen_label_rtx ();
5045: #endif
5046:
5047: /* Initialize rtx used to return the value. */
5048: /* Do this before assign_parms so that we copy the struct value address
5049: before any library calls that assign parms might generate. */
5050:
5051: /* Decide whether to return the value in memory or in a register. */
5052: if (aggregate_value_p (DECL_RESULT (subr)))
5053: {
5054: /* Returning something that won't go in a register. */
1.1.1.7 root 5055: register rtx value_address = 0;
1.1 root 5056:
5057: #ifdef PCC_STATIC_STRUCT_RETURN
5058: if (current_function_returns_pcc_struct)
5059: {
5060: int size = int_size_in_bytes (TREE_TYPE (DECL_RESULT (subr)));
5061: value_address = assemble_static_space (size);
5062: }
5063: else
5064: #endif
5065: {
5066: /* Expect to be passed the address of a place to store the value.
5067: If it is passed as an argument, assign_parms will take care of
5068: it. */
5069: if (struct_value_incoming_rtx)
5070: {
5071: value_address = gen_reg_rtx (Pmode);
5072: emit_move_insn (value_address, struct_value_incoming_rtx);
5073: }
5074: }
5075: if (value_address)
1.1.1.7 root 5076: {
5077: DECL_RTL (DECL_RESULT (subr))
5078: = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)), value_address);
5079: MEM_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)))
5080: = AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
5081: }
1.1 root 5082: }
5083: else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
5084: /* If return mode is void, this decl rtl should not be used. */
5085: DECL_RTL (DECL_RESULT (subr)) = 0;
5086: else if (parms_have_cleanups)
1.1.1.4 root 5087: {
5088: /* If function will end with cleanup code for parms,
5089: compute the return values into a pseudo reg,
5090: which we will copy into the true return register
5091: after the cleanups are done. */
5092:
5093: enum machine_mode mode = DECL_MODE (DECL_RESULT (subr));
1.1.1.7 root 5094:
1.1.1.4 root 5095: #ifdef PROMOTE_FUNCTION_RETURN
5096: tree type = TREE_TYPE (DECL_RESULT (subr));
5097: int unsignedp = TREE_UNSIGNED (type);
5098:
1.1.1.7 root 5099: mode = promote_mode (type, mode, &unsignedp, 1);
1.1.1.4 root 5100: #endif
5101:
5102: DECL_RTL (DECL_RESULT (subr)) = gen_reg_rtx (mode);
5103: }
1.1 root 5104: else
5105: /* Scalar, returned in a register. */
5106: {
5107: #ifdef FUNCTION_OUTGOING_VALUE
5108: DECL_RTL (DECL_RESULT (subr))
5109: = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
5110: #else
5111: DECL_RTL (DECL_RESULT (subr))
5112: = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
5113: #endif
5114:
5115: /* Mark this reg as the function's return value. */
5116: if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
5117: {
5118: REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
5119: /* Needed because we may need to move this to memory
5120: in case it's a named return value whose address is taken. */
1.1.1.4 root 5121: DECL_REGISTER (DECL_RESULT (subr)) = 1;
1.1 root 5122: }
5123: }
5124:
5125: /* Initialize rtx for parameters and local variables.
5126: In some cases this requires emitting insns. */
5127:
5128: assign_parms (subr, 0);
5129:
1.1.1.7 root 5130: #ifdef SMALL_REGISTER_CLASSES
5131: /* Copy the static chain now if it wasn't a register. The delay is to
5132: avoid conflicts with the parameter passing registers. */
5133:
5134: if (current_function_needs_context)
5135: if (GET_CODE (static_chain_incoming_rtx) != REG)
5136: emit_move_insn (last_ptr, static_chain_incoming_rtx);
5137: #endif
5138:
1.1 root 5139: /* The following was moved from init_function_start.
5140: The move is supposed to make sdb output more accurate. */
5141: /* Indicate the beginning of the function body,
5142: as opposed to parm setup. */
1.1.1.4 root 5143: emit_note (NULL_PTR, NOTE_INSN_FUNCTION_BEG);
1.1 root 5144:
5145: /* If doing stupid allocation, mark parms as born here. */
5146:
5147: if (GET_CODE (get_last_insn ()) != NOTE)
1.1.1.4 root 5148: emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1 root 5149: parm_birth_insn = get_last_insn ();
5150:
5151: if (obey_regdecls)
5152: {
5153: for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
5154: use_variable (regno_reg_rtx[i]);
5155:
5156: if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
5157: use_variable (current_function_internal_arg_pointer);
5158: }
5159:
5160: /* Fetch static chain values for containing functions. */
5161: tem = decl_function_context (current_function_decl);
1.1.1.7 root 5162: /* If not doing stupid register allocation copy the static chain
1.1.1.8 root 5163: pointer into a pseudo. If we have small register classes, copy the
1.1.1.7 root 5164: value from memory if static_chain_incoming_rtx is a REG. If we do
5165: stupid register allocation, we use the stack address generated above. */
1.1.1.4 root 5166: if (tem && ! obey_regdecls)
1.1.1.7 root 5167: {
5168: #ifdef SMALL_REGISTER_CLASSES
5169: /* If the static chain originally came in a register, put it back
5170: there, then move it out in the next insn. The reason for
5171: this peculiar code is to satisfy function integration. */
5172: if (GET_CODE (static_chain_incoming_rtx) == REG)
5173: emit_move_insn (static_chain_incoming_rtx, last_ptr);
5174: #endif
5175:
5176: last_ptr = copy_to_reg (static_chain_incoming_rtx);
5177: }
5178:
1.1 root 5179: context_display = 0;
5180: while (tem)
5181: {
5182: tree rtlexp = make_node (RTL_EXPR);
5183:
5184: RTL_EXPR_RTL (rtlexp) = last_ptr;
5185: context_display = tree_cons (tem, rtlexp, context_display);
5186: tem = decl_function_context (tem);
5187: if (tem == 0)
5188: break;
5189: /* Chain thru stack frames, assuming pointer to next lexical frame
5190: is found at the place we always store it. */
5191: #ifdef FRAME_GROWS_DOWNWARD
5192: last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
5193: #endif
5194: last_ptr = copy_to_reg (gen_rtx (MEM, Pmode,
5195: memory_address (Pmode, last_ptr)));
1.1.1.6 root 5196:
5197: /* If we are not optimizing, ensure that we know that this
5198: piece of context is live over the entire function. */
5199: if (! optimize)
5200: save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, last_ptr,
5201: save_expr_regs);
1.1 root 5202: }
5203:
5204: /* After the display initializations is where the tail-recursion label
5205: should go, if we end up needing one. Ensure we have a NOTE here
5206: since some things (like trampolines) get placed before this. */
1.1.1.4 root 5207: tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1 root 5208:
5209: /* Evaluate now the sizes of any types declared among the arguments. */
5210: for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
1.1.1.5 root 5211: expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
1.1 root 5212:
5213: /* Make sure there is a line number after the function entry setup code. */
5214: force_next_line_note ();
5215: }
5216:
5217: /* Generate RTL for the end of the current function.
1.1.1.6 root 5218: FILENAME and LINE are the current position in the source file.
1.1 root 5219:
1.1.1.6 root 5220: It is up to language-specific callers to do cleanups for parameters--
5221: or else, supply 1 for END_BINDINGS and we will call expand_end_bindings. */
1.1 root 5222:
5223: void
1.1.1.6 root 5224: expand_function_end (filename, line, end_bindings)
1.1 root 5225: char *filename;
5226: int line;
1.1.1.6 root 5227: int end_bindings;
1.1 root 5228: {
5229: register int i;
5230: tree link;
5231:
1.1.1.9 ! root 5232: #ifdef TRAMPOLINE_TEMPLATE
1.1 root 5233: static rtx initial_trampoline;
1.1.1.9 ! root 5234: #endif
1.1 root 5235:
1.1.1.6 root 5236: if (output_bytecode)
5237: {
5238: bc_expand_function_end ();
5239: return;
5240: }
5241:
1.1 root 5242: #ifdef NON_SAVING_SETJMP
5243: /* Don't put any variables in registers if we call setjmp
5244: on a machine that fails to restore the registers. */
5245: if (NON_SAVING_SETJMP && current_function_calls_setjmp)
5246: {
1.1.1.7 root 5247: if (DECL_INITIAL (current_function_decl) != error_mark_node)
5248: setjmp_protect (DECL_INITIAL (current_function_decl));
5249:
1.1 root 5250: setjmp_protect_args ();
5251: }
5252: #endif
5253:
5254: /* Save the argument pointer if a save area was made for it. */
5255: if (arg_pointer_save_area)
5256: {
5257: rtx x = gen_move_insn (arg_pointer_save_area, virtual_incoming_args_rtx);
5258: emit_insn_before (x, tail_recursion_reentry);
5259: }
5260:
5261: /* Initialize any trampolines required by this function. */
5262: for (link = trampoline_list; link; link = TREE_CHAIN (link))
5263: {
5264: tree function = TREE_PURPOSE (link);
5265: rtx context = lookup_static_chain (function);
5266: rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link));
1.1.1.9 ! root 5267: rtx blktramp;
1.1 root 5268: rtx seq;
5269:
1.1.1.9 ! root 5270: #ifdef TRAMPOLINE_TEMPLATE
1.1 root 5271: /* First make sure this compilation has a template for
5272: initializing trampolines. */
5273: if (initial_trampoline == 0)
1.1.1.2 root 5274: {
5275: end_temporary_allocation ();
5276: initial_trampoline
5277: = gen_rtx (MEM, BLKmode, assemble_trampoline_template ());
5278: resume_temporary_allocation ();
5279: }
1.1.1.9 ! root 5280: #endif
1.1 root 5281:
5282: /* Generate insns to initialize the trampoline. */
5283: start_sequence ();
1.1.1.9 ! root 5284: tramp = round_trampoline_addr (XEXP (tramp, 0));
! 5285: #ifdef TRAMPOLINE_TEMPLATE
! 5286: blktramp = change_address (initial_trampoline, BLKmode, tramp);
! 5287: emit_block_move (blktramp, initial_trampoline,
! 5288: GEN_INT (TRAMPOLINE_SIZE),
1.1 root 5289: FUNCTION_BOUNDARY / BITS_PER_UNIT);
1.1.1.9 ! root 5290: #endif
! 5291: INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
1.1 root 5292: seq = get_insns ();
5293: end_sequence ();
5294:
5295: /* Put those insns at entry to the containing function (this one). */
5296: emit_insns_before (seq, tail_recursion_reentry);
5297: }
5298:
1.1.1.8 root 5299: /* Warn about unused parms if extra warnings were specified. */
5300: if (warn_unused && extra_warnings)
1.1 root 5301: {
1.1.1.8 root 5302: tree decl;
1.1 root 5303:
5304: for (decl = DECL_ARGUMENTS (current_function_decl);
5305: decl; decl = TREE_CHAIN (decl))
1.1.1.8 root 5306: if (! TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
5307: && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
1.1 root 5308: warning_with_decl (decl, "unused parameter `%s'");
5309: }
5310:
5311: /* Delete handlers for nonlocal gotos if nothing uses them. */
5312: if (nonlocal_goto_handler_slot != 0 && !current_function_has_nonlocal_label)
5313: delete_handlers ();
5314:
5315: /* End any sequences that failed to be closed due to syntax errors. */
5316: while (in_sequence_p ())
1.1.1.4 root 5317: end_sequence ();
1.1 root 5318:
5319: /* Outside function body, can't compute type's actual size
5320: until next function's body starts. */
5321: immediate_size_expand--;
5322:
5323: /* If doing stupid register allocation,
5324: mark register parms as dying here. */
5325:
5326: if (obey_regdecls)
5327: {
5328: rtx tem;
5329: for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
5330: use_variable (regno_reg_rtx[i]);
5331:
5332: /* Likewise for the regs of all the SAVE_EXPRs in the function. */
5333:
5334: for (tem = save_expr_regs; tem; tem = XEXP (tem, 1))
5335: {
5336: use_variable (XEXP (tem, 0));
5337: use_variable_after (XEXP (tem, 0), parm_birth_insn);
5338: }
5339:
5340: if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
5341: use_variable (current_function_internal_arg_pointer);
5342: }
5343:
5344: clear_pending_stack_adjust ();
5345: do_pending_stack_adjust ();
5346:
5347: /* Mark the end of the function body.
5348: If control reaches this insn, the function can drop through
5349: without returning a value. */
1.1.1.4 root 5350: emit_note (NULL_PTR, NOTE_INSN_FUNCTION_END);
1.1 root 5351:
5352: /* Output a linenumber for the end of the function.
5353: SDB depends on this. */
5354: emit_line_note_force (filename, line);
5355:
5356: /* Output the label for the actual return from the function,
5357: if one is expected. This happens either because a function epilogue
5358: is used instead of a return instruction, or because a return was done
5359: with a goto in order to run local cleanups, or because of pcc-style
5360: structure returning. */
5361:
5362: if (return_label)
5363: emit_label (return_label);
5364:
1.1.1.6 root 5365: /* C++ uses this. */
5366: if (end_bindings)
5367: expand_end_bindings (0, 0, 0);
5368:
1.1 root 5369: /* If we had calls to alloca, and this machine needs
5370: an accurate stack pointer to exit the function,
5371: insert some code to save and restore the stack pointer. */
5372: #ifdef EXIT_IGNORE_STACK
5373: if (! EXIT_IGNORE_STACK)
5374: #endif
5375: if (current_function_calls_alloca)
5376: {
1.1.1.3 root 5377: rtx tem = 0;
5378:
5379: emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
1.1.1.4 root 5380: emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
1.1 root 5381: }
5382:
5383: /* If scalar return value was computed in a pseudo-reg,
5384: copy that to the hard return register. */
5385: if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0
5386: && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG
5387: && (REGNO (DECL_RTL (DECL_RESULT (current_function_decl)))
5388: >= FIRST_PSEUDO_REGISTER))
5389: {
5390: rtx real_decl_result;
5391:
5392: #ifdef FUNCTION_OUTGOING_VALUE
5393: real_decl_result
5394: = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
5395: current_function_decl);
5396: #else
5397: real_decl_result
5398: = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
5399: current_function_decl);
5400: #endif
5401: REG_FUNCTION_VALUE_P (real_decl_result) = 1;
5402: emit_move_insn (real_decl_result,
5403: DECL_RTL (DECL_RESULT (current_function_decl)));
5404: emit_insn (gen_rtx (USE, VOIDmode, real_decl_result));
5405: }
5406:
5407: /* If returning a structure, arrange to return the address of the value
5408: in a place where debuggers expect to find it.
5409:
5410: If returning a structure PCC style,
5411: the caller also depends on this value.
5412: And current_function_returns_pcc_struct is not necessarily set. */
5413: if (current_function_returns_struct
5414: || current_function_returns_pcc_struct)
5415: {
5416: rtx value_address = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5417: tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
5418: #ifdef FUNCTION_OUTGOING_VALUE
5419: rtx outgoing
5420: = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
5421: current_function_decl);
5422: #else
5423: rtx outgoing
5424: = FUNCTION_VALUE (build_pointer_type (type),
5425: current_function_decl);
5426: #endif
5427:
5428: /* Mark this as a function return value so integrate will delete the
5429: assignment and USE below when inlining this function. */
5430: REG_FUNCTION_VALUE_P (outgoing) = 1;
5431:
5432: emit_move_insn (outgoing, value_address);
5433: use_variable (outgoing);
5434: }
5435:
5436: /* Output a return insn if we are using one.
5437: Otherwise, let the rtl chain end here, to drop through
5438: into the epilogue. */
5439:
5440: #ifdef HAVE_return
5441: if (HAVE_return)
5442: {
5443: emit_jump_insn (gen_return ());
5444: emit_barrier ();
5445: }
5446: #endif
5447:
5448: /* Fix up any gotos that jumped out to the outermost
5449: binding level of the function.
5450: Must follow emitting RETURN_LABEL. */
5451:
5452: /* If you have any cleanups to do at this point,
5453: and they need to create temporary variables,
5454: then you will lose. */
1.1.1.7 root 5455: expand_fixups (get_insns ());
1.1.1.4 root 5456: }
5457:
5458: /* These arrays record the INSN_UIDs of the prologue and epilogue insns. */
5459:
5460: static int *prologue;
5461: static int *epilogue;
5462:
5463: /* Create an array that records the INSN_UIDs of INSNS (either a sequence
5464: or a single insn). */
5465:
5466: static int *
5467: record_insns (insns)
5468: rtx insns;
5469: {
5470: int *vec;
5471:
5472: if (GET_CODE (insns) == SEQUENCE)
5473: {
5474: int len = XVECLEN (insns, 0);
5475: vec = (int *) oballoc ((len + 1) * sizeof (int));
5476: vec[len] = 0;
5477: while (--len >= 0)
5478: vec[len] = INSN_UID (XVECEXP (insns, 0, len));
5479: }
5480: else
5481: {
5482: vec = (int *) oballoc (2 * sizeof (int));
5483: vec[0] = INSN_UID (insns);
5484: vec[1] = 0;
5485: }
5486: return vec;
5487: }
5488:
5489: /* Determine how many INSN_UIDs in VEC are part of INSN. */
5490:
5491: static int
5492: contains (insn, vec)
5493: rtx insn;
5494: int *vec;
5495: {
5496: register int i, j;
5497:
5498: if (GET_CODE (insn) == INSN
5499: && GET_CODE (PATTERN (insn)) == SEQUENCE)
5500: {
5501: int count = 0;
5502: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
5503: for (j = 0; vec[j]; j++)
5504: if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j])
5505: count++;
5506: return count;
5507: }
5508: else
5509: {
5510: for (j = 0; vec[j]; j++)
5511: if (INSN_UID (insn) == vec[j])
5512: return 1;
5513: }
5514: return 0;
5515: }
5516:
1.1.1.8 root 5517: /* Generate the prologue and epilogue RTL if the machine supports it. Thread
1.1.1.4 root 5518: this into place with notes indicating where the prologue ends and where
5519: the epilogue begins. Update the basic block information when possible. */
5520:
5521: void
5522: thread_prologue_and_epilogue_insns (f)
5523: rtx f;
5524: {
5525: #ifdef HAVE_prologue
5526: if (HAVE_prologue)
5527: {
5528: rtx head, seq, insn;
5529:
5530: /* The first insn (a NOTE_INSN_DELETED) is followed by zero or more
5531: prologue insns and a NOTE_INSN_PROLOGUE_END. */
5532: emit_note_after (NOTE_INSN_PROLOGUE_END, f);
5533: seq = gen_prologue ();
5534: head = emit_insn_after (seq, f);
5535:
5536: /* Include the new prologue insns in the first block. Ignore them
5537: if they form a basic block unto themselves. */
5538: if (basic_block_head && n_basic_blocks
5539: && GET_CODE (basic_block_head[0]) != CODE_LABEL)
5540: basic_block_head[0] = NEXT_INSN (f);
5541:
5542: /* Retain a map of the prologue insns. */
5543: prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head);
5544: }
5545: else
5546: #endif
5547: prologue = 0;
5548:
5549: #ifdef HAVE_epilogue
5550: if (HAVE_epilogue)
5551: {
5552: rtx insn = get_last_insn ();
5553: rtx prev = prev_nonnote_insn (insn);
5554:
5555: /* If we end with a BARRIER, we don't need an epilogue. */
5556: if (! (prev && GET_CODE (prev) == BARRIER))
5557: {
1.1.1.6 root 5558: rtx tail, seq, tem;
5559: rtx first_use = 0;
5560: rtx last_use = 0;
5561:
5562: /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
5563: epilogue insns, the USE insns at the end of a function,
5564: the jump insn that returns, and then a BARRIER. */
1.1.1.4 root 5565:
1.1.1.6 root 5566: /* Move the USE insns at the end of a function onto a list. */
1.1.1.4 root 5567: while (prev
5568: && GET_CODE (prev) == INSN
5569: && GET_CODE (PATTERN (prev)) == USE)
5570: {
1.1.1.6 root 5571: tem = prev;
1.1.1.4 root 5572: prev = prev_nonnote_insn (prev);
1.1.1.6 root 5573:
5574: NEXT_INSN (PREV_INSN (tem)) = NEXT_INSN (tem);
5575: PREV_INSN (NEXT_INSN (tem)) = PREV_INSN (tem);
5576: if (first_use)
5577: {
5578: NEXT_INSN (tem) = first_use;
5579: PREV_INSN (first_use) = tem;
5580: }
5581: first_use = tem;
5582: if (!last_use)
5583: last_use = tem;
1.1.1.4 root 5584: }
5585:
1.1.1.6 root 5586: emit_barrier_after (insn);
5587:
1.1.1.4 root 5588: seq = gen_epilogue ();
5589: tail = emit_jump_insn_after (seq, insn);
1.1.1.6 root 5590:
5591: /* Insert the USE insns immediately before the return insn, which
5592: must be the first instruction before the final barrier. */
5593: if (first_use)
5594: {
5595: tem = prev_nonnote_insn (get_last_insn ());
5596: NEXT_INSN (PREV_INSN (tem)) = first_use;
5597: PREV_INSN (first_use) = PREV_INSN (tem);
5598: PREV_INSN (tem) = last_use;
5599: NEXT_INSN (last_use) = tem;
5600: }
5601:
1.1.1.4 root 5602: emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn);
5603:
5604: /* Include the new epilogue insns in the last block. Ignore
5605: them if they form a basic block unto themselves. */
5606: if (basic_block_end && n_basic_blocks
5607: && GET_CODE (basic_block_end[n_basic_blocks - 1]) != JUMP_INSN)
5608: basic_block_end[n_basic_blocks - 1] = tail;
5609:
5610: /* Retain a map of the epilogue insns. */
5611: epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
5612: return;
5613: }
5614: }
5615: #endif
5616: epilogue = 0;
5617: }
5618:
5619: /* Reposition the prologue-end and epilogue-begin notes after instruction
5620: scheduling and delayed branch scheduling. */
5621:
5622: void
5623: reposition_prologue_and_epilogue_notes (f)
5624: rtx f;
5625: {
5626: #if defined (HAVE_prologue) || defined (HAVE_epilogue)
5627: /* Reposition the prologue and epilogue notes. */
5628: if (n_basic_blocks)
5629: {
5630: rtx next, prev;
5631: int len;
5632:
5633: if (prologue)
5634: {
5635: register rtx insn, note = 0;
5636:
5637: /* Scan from the beginning until we reach the last prologue insn.
5638: We apparently can't depend on basic_block_{head,end} after
5639: reorg has run. */
5640: for (len = 0; prologue[len]; len++)
5641: ;
1.1.1.5 root 5642: for (insn = f; len && insn; insn = NEXT_INSN (insn))
5643: {
5644: if (GET_CODE (insn) == NOTE)
5645: {
5646: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
5647: note = insn;
5648: }
5649: else if ((len -= contains (insn, prologue)) == 0)
5650: {
5651: /* Find the prologue-end note if we haven't already, and
5652: move it to just after the last prologue insn. */
5653: if (note == 0)
5654: {
5655: for (note = insn; note = NEXT_INSN (note);)
5656: if (GET_CODE (note) == NOTE
5657: && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
5658: break;
5659: }
5660: next = NEXT_INSN (note);
5661: prev = PREV_INSN (note);
5662: if (prev)
5663: NEXT_INSN (prev) = next;
5664: if (next)
5665: PREV_INSN (next) = prev;
5666: add_insn_after (note, insn);
5667: }
5668: }
1.1.1.4 root 5669: }
5670:
5671: if (epilogue)
5672: {
5673: register rtx insn, note = 0;
5674:
5675: /* Scan from the end until we reach the first epilogue insn.
5676: We apparently can't depend on basic_block_{head,end} after
5677: reorg has run. */
5678: for (len = 0; epilogue[len]; len++)
5679: ;
1.1.1.5 root 5680: for (insn = get_last_insn (); len && insn; insn = PREV_INSN (insn))
5681: {
5682: if (GET_CODE (insn) == NOTE)
5683: {
5684: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
5685: note = insn;
5686: }
5687: else if ((len -= contains (insn, epilogue)) == 0)
5688: {
5689: /* Find the epilogue-begin note if we haven't already, and
5690: move it to just before the first epilogue insn. */
5691: if (note == 0)
5692: {
5693: for (note = insn; note = PREV_INSN (note);)
5694: if (GET_CODE (note) == NOTE
5695: && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
5696: break;
5697: }
5698: next = NEXT_INSN (note);
5699: prev = PREV_INSN (note);
5700: if (prev)
5701: NEXT_INSN (prev) = next;
5702: if (next)
5703: PREV_INSN (next) = prev;
5704: add_insn_after (note, PREV_INSN (insn));
5705: }
5706: }
1.1.1.4 root 5707: }
5708: }
5709: #endif /* HAVE_prologue or HAVE_epilogue */
1.1 root 5710: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.