|
|
1.1 root 1: /* Procedure integration for GNU CC.
2: Copyright (C) 1988, 1991 Free Software Foundation, Inc.
3: Contributed by Michael Tiemann ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
22: #include <stdio.h>
23:
24: #include "config.h"
25: #include "rtl.h"
26: #include "tree.h"
27: #include "flags.h"
28: #include "insn-config.h"
29: #include "insn-flags.h"
30: #include "expr.h"
31: #include "output.h"
32: #include "integrate.h"
33: #include "real.h"
34: #include "function.h"
35:
36: #include "obstack.h"
37: #define obstack_chunk_alloc xmalloc
38: #define obstack_chunk_free free
39: extern int xmalloc ();
40: extern void free ();
41:
42: extern struct obstack *function_maybepermanent_obstack;
43:
44: extern tree pushdecl ();
45: extern tree poplevel ();
46:
47: /* Similar, but round to the next highest integer that meets the
48: alignment. */
49: #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
50:
51: /* Default max number of insns a function can have and still be inline.
52: This is overridden on RISC machines. */
53: #ifndef INTEGRATE_THRESHOLD
54: #define INTEGRATE_THRESHOLD(DECL) \
55: (8 * (8 + list_length (DECL_ARGUMENTS (DECL))))
56: #endif
57:
58: /* Save any constant pool constants in an insn. */
59: static void save_constants ();
60:
61: /* Note when parameter registers are the destination of a SET. */
62: static void note_modified_parmregs ();
63:
64: /* Copy an rtx for save_for_inline_copying. */
65: static rtx copy_for_inline ();
66:
67: /* Make copies of MEMs in DECL_RTLs. */
68: static void copy_decl_rtls ();
69:
70: static tree copy_decl_tree ();
71:
72: /* Return the constant equivalent of a given rtx, or 0 if none. */
73: static rtx const_equiv ();
74:
75: static void integrate_parm_decls ();
76: static void integrate_decl_tree ();
77:
78: static void subst_constants ();
79: static rtx fold_out_const_cc0 ();
80:
81: /* Zero if the current function (whose FUNCTION_DECL is FNDECL)
82: is safe and reasonable to integrate into other functions.
83: Nonzero means value is a warning message with a single %s
84: for the function's name. */
85:
86: char *
87: function_cannot_inline_p (fndecl)
88: register tree fndecl;
89: {
90: register rtx insn;
91: tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
92: int max_insns = INTEGRATE_THRESHOLD (fndecl);
93: register int ninsns = 0;
94: register tree parms;
95:
96: /* No inlines with varargs. `grokdeclarator' gives a warning
97: message about that if `inline' is specified. This code
98: it put in to catch the volunteers. */
99: if ((last && TREE_VALUE (last) != void_type_node)
100: || (DECL_ARGUMENTS (fndecl) && DECL_NAME (DECL_ARGUMENTS (fndecl))
101: && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (DECL_ARGUMENTS (fndecl))),
102: "__builtin_va_alist")))
103: return "varargs function cannot be inline";
104:
105: if (current_function_calls_alloca)
106: return "function using alloca cannot be inline";
107:
108: if (current_function_contains_functions)
109: return "function with nested functions cannot be inline";
110:
111: /* This restriction may be eliminated sometime soon. But for now, don't
112: worry about remapping the static chain. */
113: if (current_function_needs_context)
114: return "nested function cannot be inline";
115:
116: /* If its not even close, don't even look. */
117: if (!TREE_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
118: return "function too large to be inline";
119:
120: #if 0
121: /* Large stacks are OK now that inlined functions can share them. */
122: /* Don't inline functions with large stack usage,
123: since they can make other recursive functions burn up stack. */
124: if (!TREE_INLINE (fndecl) && get_frame_size () > 100)
125: return "function stack frame for inlining";
126: #endif
127:
128: #if 0
129: /* Don't inline functions which do not specify a function prototype and
130: have BLKmode argument or take the address of a parameter. */
131: for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
132: {
133: if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
134: TREE_ADDRESSABLE (parms) = 1;
135: if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
136: return "no prototype, and parameter address used; cannot be inline";
137: }
138: #endif
139:
140: /* We can't inline functions that return structures
141: the old-fashioned PCC way, copying into a static block. */
142: if (current_function_returns_pcc_struct)
143: return "inline functions not supported for this return value type";
144:
145: /* We can't inline functions that return structures of varying size. */
146: if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
147: return "function with varying-size return value cannot be inline";
148:
149: /* Cannot inline a function with a varying size argument. */
150: for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
151: if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
152: return "function with varying-size parameter cannot be inline";
153:
154: if (!TREE_INLINE (fndecl) && get_max_uid () > max_insns)
155: {
156: for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns;
157: insn = NEXT_INSN (insn))
158: {
159: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
160: ninsns++;
161: }
162:
163: if (ninsns >= max_insns)
164: return "function too large to be inline";
165: }
166:
167: return 0;
168: }
169:
170: /* Variables used within save_for_inline. */
171:
172: /* Mapping from old pseudo-register to new pseudo-registers.
173: The first element of this map is reg_map[FIRST_PSEUDO_REGISTER].
174: It is allocated in `save_for_inline' and `expand_inline_function',
175: and deallocated on exit from each of those routines. */
176: static rtx *reg_map;
177:
178: /* Mapping from old code-labels to new code-labels.
179: The first element of this map is label_map[min_labelno].
180: It is allocated in `save_for_inline' and `expand_inline_function',
181: and deallocated on exit from each of those routines. */
182: static rtx *label_map;
183:
184: /* Mapping from old insn uid's to copied insns.
185: It is allocated in `save_for_inline' and `expand_inline_function',
186: and deallocated on exit from each of those routines. */
187: static rtx *insn_map;
188:
189: /* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
190: Zero for a reg that isn't a parm's home.
191: Only reg numbers less than max_parm_reg are mapped here. */
192: static tree *parmdecl_map;
193:
194: /* Keep track of first pseudo-register beyond those that are parms. */
195: static int max_parm_reg;
196:
197: /* When an insn is being copied by copy_for_inline,
198: this is nonzero if we have copied an ASM_OPERANDS.
199: In that case, it is the original input-operand vector. */
200: static rtvec orig_asm_operands_vector;
201:
202: /* When an insn is being copied by copy_for_inline,
203: this is nonzero if we have copied an ASM_OPERANDS.
204: In that case, it is the copied input-operand vector. */
205: static rtvec copy_asm_operands_vector;
206:
207: /* Likewise, this is the copied constraints vector. */
208: static rtvec copy_asm_constraints_vector;
209:
210: /* In save_for_inline, nonzero if past the parm-initialization insns. */
211: static int in_nonparm_insns;
212:
213: /* Subroutine for `save_for_inline{copying,nocopy}'. Performs initialization
214: needed to save FNDECL's insns and info for future inline expansion. */
215:
216: static rtx
217: initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
218: tree fndecl;
219: int min_labelno;
220: int max_labelno;
221: int max_reg;
222: int copy;
223: {
224: int function_flags, i;
225: rtvec arg_vector;
226: tree parms;
227:
228: /* Compute the values of any flags we must restore when inlining this. */
229:
230: function_flags
231: = (current_function_calls_alloca * FUNCTION_FLAGS_CALLS_ALLOCA
232: + current_function_calls_setjmp * FUNCTION_FLAGS_CALLS_SETJMP
233: + current_function_calls_longjmp * FUNCTION_FLAGS_CALLS_LONGJMP
234: + current_function_returns_struct * FUNCTION_FLAGS_RETURNS_STRUCT
235: + current_function_returns_pcc_struct * FUNCTION_FLAGS_RETURNS_PCC_STRUCT
236: + current_function_needs_context * FUNCTION_FLAGS_NEEDS_CONTEXT
237: + current_function_has_nonlocal_label * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL
238: + current_function_returns_pointer * FUNCTION_FLAGS_RETURNS_POINTER
239: + current_function_uses_const_pool * FUNCTION_FLAGS_USES_CONST_POOL
240: + current_function_uses_pic_offset_table * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE);
241:
242: /* Clear out PARMDECL_MAP. It was allocated in the caller's frame. */
243: bzero (parmdecl_map, max_parm_reg * sizeof (tree));
244: arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
245:
246: for (parms = DECL_ARGUMENTS (fndecl), i = 0;
247: parms;
248: parms = TREE_CHAIN (parms), i++)
249: {
250: rtx p = DECL_RTL (parms);
251:
252: if (GET_CODE (p) == MEM && copy)
253: /* Copy the rtl so that modifications of the address
254: later in compilation won't affect this arg_vector.
255: Virtual register instantiation can screw the address
256: of the rtl. */
257: DECL_RTL (parms) = copy_rtx (p);
258:
259: RTVEC_ELT (arg_vector, i) = p;
260:
261: if (GET_CODE (p) == REG)
262: parmdecl_map[REGNO (p)] = parms;
263: TREE_READONLY (parms) = 1;
264: }
265:
266: /* Assume we start out in the insns that set up the parameters. */
267: in_nonparm_insns = 0;
268:
269: /* The list of DECL_SAVED_INSNS, starts off with a header which
270: contains the following information:
271:
272: the first insn of the function (not including the insns that copy
273: parameters into registers).
274: the first parameter insn of the function,
275: the first label used by that function,
276: the last label used by that function,
277: the highest register number used for parameters,
278: the total number of registers used,
279: the size of the incoming stack area for parameters,
280: the number of bytes popped on return,
281: the stack slot list,
282: some flags that are used to restore compiler globals,
283: the value of current_function_outgoing_args_size,
284: the original argument vector,
285: and the original DECL_INITIAL. */
286:
287: return gen_inline_header_rtx (NULL, NULL, min_labelno, max_labelno,
288: max_parm_reg, max_reg,
289: current_function_args_size,
290: current_function_pops_args,
291: stack_slot_list, function_flags,
292: current_function_outgoing_args_size,
293: arg_vector, (rtx) DECL_INITIAL (fndecl));
294: }
295:
296: /* Subroutine for `save_for_inline{copying,nocopy}'. Finishes up the
297: things that must be done to make FNDECL expandable as an inline function.
298: HEAD contains the chain of insns to which FNDECL will expand. */
299:
300: static void
301: finish_inline (fndecl, head)
302: tree fndecl;
303: rtx head;
304: {
305: NEXT_INSN (head) = get_first_nonparm_insn ();
306: FIRST_PARM_INSN (head) = get_insns ();
307: DECL_SAVED_INSNS (fndecl) = head;
308: DECL_FRAME_SIZE (fndecl) = get_frame_size ();
309: TREE_INLINE (fndecl) = 1;
310: }
311:
312: /* Make the insns and PARM_DECLs of the current function permanent
313: and record other information in DECL_SAVED_INSNS to allow inlining
314: of this function in subsequent calls.
315:
316: This function is called when we are going to immediately compile
317: the insns for FNDECL. The insns in maybepermanent_obstack cannot be
318: modified by the compilation process, so we copy all of them to
319: new storage and consider the new insns to be the insn chain to be
320: compiled. */
321:
322: void
323: save_for_inline_copying (fndecl)
324: tree fndecl;
325: {
326: rtx first_insn, last_insn, insn;
327: rtx head, copy;
328: int max_labelno, min_labelno, i, len;
329: int max_reg;
330: int max_uid;
331: rtx first_nonparm_insn;
332:
333: /* Make and emit a return-label if we have not already done so.
334: Do this before recording the bounds on label numbers. */
335:
336: if (return_label == 0)
337: {
338: return_label = gen_label_rtx ();
339: emit_label (return_label);
340: }
341:
342: /* Get some bounds on the labels and registers used. */
343:
344: max_labelno = max_label_num ();
345: min_labelno = get_first_label_num ();
346: max_reg = max_reg_num ();
347:
348: /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
349: Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
350: Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
351: for the parms, prior to elimination of virtual registers.
352: These values are needed for substituting parms properly. */
353:
354: max_parm_reg = max_parm_reg_num ();
355: parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
356:
357: head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);
358:
359: if (current_function_uses_const_pool)
360: {
361: /* Replace any constant pool references with the actual constant. We
362: will put the constants back in the copy made below. */
363: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
364: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
365: {
366: save_constants (&PATTERN (insn));
367: if (REG_NOTES (insn))
368: save_constants (®_NOTES (insn));
369: }
370:
371: /* Clear out the constant pool so that we can recreate it with the
372: copied constants below. */
373: init_const_rtx_hash_table ();
374: clear_const_double_mem ();
375: }
376:
377: max_uid = INSN_UID (head);
378:
379: /* We have now allocated all that needs to be allocated permanently
380: on the rtx obstack. Set our high-water mark, so that we
381: can free the rest of this when the time comes. */
382:
383: preserve_data ();
384:
385: /* Copy the chain insns of this function.
386: Install the copied chain as the insns of this function,
387: for continued compilation;
388: the original chain is recorded as the DECL_SAVED_INSNS
389: for inlining future calls. */
390:
391: /* If there are insns that copy parms from the stack into pseudo registers,
392: those insns are not copied. `expand_inline_function' must
393: emit the correct code to handle such things. */
394:
395: insn = get_insns ();
396: if (GET_CODE (insn) != NOTE)
397: abort ();
398: first_insn = rtx_alloc (NOTE);
399: NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);
400: NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);
401: INSN_UID (first_insn) = INSN_UID (insn);
402: PREV_INSN (first_insn) = NULL;
403: NEXT_INSN (first_insn) = NULL;
404: last_insn = first_insn;
405:
406: /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.
407: Make these new rtx's now, and install them in regno_reg_rtx, so they
408: will be the official pseudo-reg rtx's for the rest of compilation. */
409:
410: reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));
411:
412: len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
413: for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)
414: reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,
415: regno_reg_rtx[i], len);
416:
417: bcopy (reg_map + LAST_VIRTUAL_REGISTER + 1,
418: regno_reg_rtx + LAST_VIRTUAL_REGISTER + 1,
419: (max_reg - (LAST_VIRTUAL_REGISTER + 1)) * sizeof (rtx));
420:
421: /* Likewise each label rtx must have a unique rtx as its copy. */
422:
423: label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
424: label_map -= min_labelno;
425:
426: for (i = min_labelno; i < max_labelno; i++)
427: label_map[i] = gen_label_rtx ();
428:
429: /* Record the mapping of old insns to copied insns. */
430:
431: insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
432: bzero (insn_map, max_uid * sizeof (rtx));
433:
434: /* Get the insn which signals the end of parameter setup code. */
435: first_nonparm_insn = get_first_nonparm_insn ();
436:
437: /* Copy any entries in regno_reg_rtx or DECL_RTLs that reference MEM
438: (the former occurs when a variable has its address taken)
439: since these may be shared and can be changed by virtual
440: register instantiation. DECL_RTL values for our arguments
441: have already been copied by initialize_for_inline. */
442: for (i = LAST_VIRTUAL_REGISTER + 1; i < max_reg; i++)
443: if (GET_CODE (regno_reg_rtx[i]) == MEM)
444: XEXP (regno_reg_rtx[i], 0)
445: = copy_for_inline (XEXP (regno_reg_rtx[i], 0));
446:
447: /* Copy the tree of subblocks of the function, and the decls in them.
448: We will use the copy for compiling this function, then restore the original
449: subblocks and decls for use when inlining this function.
450:
451: Several parts of the compiler modify BLOCK trees. In particular,
452: instantiate_virtual_regs will instantiate any virtual regs
453: mentioned in the DECL_RTLs of the decls, and loop
454: unrolling will replicate any BLOCK trees inside an unrolled loop.
455:
456: The modified subblocks or DECL_RTLs would be incorrect for the original rtl
457: which we will use for inlining. The rtl might even contain pseudoregs
458: whose space has been freed. */
459:
460: DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl));
461:
462: /* Now copy each DECL_RTL which is a MEM,
463: so it is safe to modify their addresses. */
464: copy_decl_rtls (DECL_INITIAL (fndecl));
465:
466: /* Now copy the chain of insns. Do this twice. The first copy the insn
467: itself and its body. The second time copy of REG_NOTES. This is because
468: a REG_NOTE may have a forward pointer to another insn. */
469:
470: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
471: {
472: orig_asm_operands_vector = 0;
473:
474: if (insn == first_nonparm_insn)
475: in_nonparm_insns = 1;
476:
477: switch (GET_CODE (insn))
478: {
479: case NOTE:
480: /* No need to keep these. */
481: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
482: continue;
483:
484: copy = rtx_alloc (NOTE);
485: NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
486: NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);
487: break;
488:
489: case INSN:
490: case CALL_INSN:
491: case JUMP_INSN:
492: copy = rtx_alloc (GET_CODE (insn));
493: PATTERN (copy) = copy_for_inline (PATTERN (insn));
494: INSN_CODE (copy) = -1;
495: LOG_LINKS (copy) = NULL;
496: RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
497: break;
498:
499: case CODE_LABEL:
500: copy = label_map[CODE_LABEL_NUMBER (insn)];
501: break;
502:
503: case BARRIER:
504: copy = rtx_alloc (BARRIER);
505: break;
506:
507: default:
508: abort ();
509: }
510: INSN_UID (copy) = INSN_UID (insn);
511: insn_map[INSN_UID (insn)] = copy;
512: NEXT_INSN (last_insn) = copy;
513: PREV_INSN (copy) = last_insn;
514: last_insn = copy;
515: }
516:
517: /* Now copy the REG_NOTES. */
518: for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn))
519: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
520: && insn_map[INSN_UID(insn)])
521: REG_NOTES (insn_map[INSN_UID (insn)])
522: = copy_for_inline (REG_NOTES (insn));
523:
524: NEXT_INSN (last_insn) = NULL;
525:
526: finish_inline (fndecl, head);
527:
528: set_new_first_and_last_insn (first_insn, last_insn);
529: }
530:
531: /* Make a copy of the entire tree of blocks BLOCK, and return it. */
532:
533: static tree
534: copy_decl_tree (block)
535: tree block;
536: {
537: tree t, vars, subblocks;
538:
539: vars = copy_list (BLOCK_VARS (block));
540: subblocks = 0;
541:
542: /* Process all subblocks. */
543: for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
544: {
545: tree copy = copy_decl_tree (t);
546: TREE_CHAIN (copy) = subblocks;
547: subblocks = copy;
548: }
549:
550: t = copy_node (block);
551: BLOCK_VARS (t) = vars;
552: BLOCK_SUBBLOCKS (t) = nreverse (subblocks);
553: return t;
554: }
555:
556: /* Copy DECL_RTLs in all decls in the given BLOCK node. */
557:
558: static void
559: copy_decl_rtls (block)
560: tree block;
561: {
562: tree t;
563:
564: for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
565: if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
566: DECL_RTL (t) = copy_for_inline (DECL_RTL (t));
567:
568: /* Process all subblocks. */
569: for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
570: copy_decl_rtls (t);
571: }
572:
573: /* Make the insns and PARM_DECLs of the current function permanent
574: and record other information in DECL_SAVED_INSNS to allow inlining
575: of this function in subsequent calls.
576:
577: This routine need not copy any insns because we are not going
578: to immediately compile the insns in the insn chain. There
579: are two cases when we would compile the insns for FNDECL:
580: (1) when FNDECL is expanded inline, and (2) when FNDECL needs to
581: be output at the end of other compilation, because somebody took
582: its address. In the first case, the insns of FNDECL are copied
583: as it is expanded inline, so FNDECL's saved insns are not
584: modified. In the second case, FNDECL is used for the last time,
585: so modifying the rtl is not a problem.
586:
587: ??? Actually, we do not verify that FNDECL is not inline expanded
588: by other functions which must also be written down at the end
589: of compilation. We could set flag_no_inline to nonzero when
590: the time comes to write down such functions. */
591:
592: void
593: save_for_inline_nocopy (fndecl)
594: tree fndecl;
595: {
596: rtx insn;
597: rtx head, copy;
598: tree parms;
599: int max_labelno, min_labelno, i, len;
600: int max_reg;
601: int max_uid;
602: rtx first_nonparm_insn;
603: int function_flags;
604:
605: /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
606: Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
607: Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
608: for the parms, prior to elimination of virtual registers.
609: These values are needed for substituting parms properly. */
610:
611: max_parm_reg = max_parm_reg_num ();
612: parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
613:
614: /* Make and emit a return-label if we have not already done so. */
615:
616: if (return_label == 0)
617: {
618: return_label = gen_label_rtx ();
619: emit_label (return_label);
620: }
621:
622: head = initialize_for_inline (fndecl, get_first_label_num (),
623: max_label_num (), max_reg_num (), 0);
624:
625: /* If there are insns that copy parms from the stack into pseudo registers,
626: those insns are not copied. `expand_inline_function' must
627: emit the correct code to handle such things. */
628:
629: insn = get_insns ();
630: if (GET_CODE (insn) != NOTE)
631: abort ();
632:
633: /* Get the insn which signals the end of parameter setup code. */
634: first_nonparm_insn = get_first_nonparm_insn ();
635:
636: /* Now just scan the chain of insns to see what happens to our
637: PARM_DECLs. If a PARM_DECL is used but never modified, we
638: can substitute its rtl directly when expanding inline (and
639: perform constant folding when its incoming value is constant).
640: Otherwise, we have to copy its value into a new register and track
641: the new register's life. */
642:
643: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
644: {
645: if (insn == first_nonparm_insn)
646: in_nonparm_insns = 1;
647:
648: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
649: {
650: if (current_function_uses_const_pool)
651: {
652: /* Replace any constant pool references with the actual constant.
653: We will put the constant back if we need to write the
654: function out after all. */
655: save_constants (&PATTERN (insn));
656: if (REG_NOTES (insn))
657: save_constants (®_NOTES (insn));
658: }
659:
660: /* Record what interesting things happen to our parameters. */
661: note_stores (PATTERN (insn), note_modified_parmregs);
662: }
663: }
664:
665: /* We have now allocated all that needs to be allocated permanently
666: on the rtx obstack. Set our high-water mark, so that we
667: can free the rest of this when the time comes. */
668:
669: preserve_data ();
670:
671: finish_inline (fndecl, head);
672: }
673:
674: /* Given PX, a pointer into an insn, search for references to the constant
675: pool. Replace each with a CONST that has the mode of the original
676: constant, contains the constant, and has RTX_INTEGRATED_P set.
677: Similarly, constant pool addresses not enclosed in a MEM are replaced
678: with an ADDRESS rtx which also gives the constant, mode, and has
679: RTX_INTEGRATED_P set. */
680:
681: static void
682: save_constants (px)
683: rtx *px;
684: {
685: rtx x;
686: int i, j;
687:
688: again:
689: x = *px;
690:
691: /* If this is a CONST_DOUBLE, don't try to fix things up in
692: CONST_DOUBLE_MEM, because this is an infinite recursion. */
693: if (GET_CODE (x) == CONST_DOUBLE)
694: return;
695: else if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
696: && CONSTANT_POOL_ADDRESS_P (XEXP (x,0)))
697: {
698: enum machine_mode const_mode = get_pool_mode (XEXP (x, 0));
699: rtx new = gen_rtx (CONST, const_mode, get_pool_constant (XEXP (x, 0)));
700: RTX_INTEGRATED_P (new) = 1;
701:
702: /* If the MEM was in a different mode than the constant (perhaps we
703: were only looking at the low-order part), surround it with a
704: SUBREG so we can save both modes. */
705:
706: if (GET_MODE (x) != const_mode)
707: {
708: new = gen_rtx (SUBREG, GET_MODE (x), new, 0);
709: RTX_INTEGRATED_P (new) = 1;
710: }
711:
712: *px = new;
713: save_constants (&XEXP (*px, 0));
714: }
715: else if (GET_CODE (x) == SYMBOL_REF
716: && CONSTANT_POOL_ADDRESS_P (x))
717: {
718: *px = gen_rtx (ADDRESS, get_pool_mode (x), get_pool_constant (x));
719: save_constants (&XEXP (*px, 0));
720: RTX_INTEGRATED_P (*px) = 1;
721: }
722:
723: else
724: {
725: char *fmt = GET_RTX_FORMAT (GET_CODE (x));
726: int len = GET_RTX_LENGTH (GET_CODE (x));
727:
728: for (i = len-1; i >= 0; i--)
729: {
730: switch (fmt[i])
731: {
732: case 'E':
733: for (j = 0; j < XVECLEN (x, i); j++)
734: save_constants (&XVECEXP (x, i, j));
735: break;
736:
737: case 'e':
738: if (XEXP (x, i) == 0)
739: continue;
740: if (i == 0)
741: {
742: /* Hack tail-recursion here. */
743: px = &XEXP (x, 0);
744: goto again;
745: }
746: save_constants (&XEXP (x, i));
747: break;
748: }
749: }
750: }
751: }
752:
753: /* Note whether a parameter is modified or not. */
754:
755: static void
756: note_modified_parmregs (reg, x)
757: rtx reg;
758: rtx x;
759: {
760: if (GET_CODE (reg) == REG && in_nonparm_insns
761: && REGNO (reg) < max_parm_reg
762: && REGNO (reg) >= FIRST_PSEUDO_REGISTER
763: && parmdecl_map[REGNO (reg)] != 0)
764: TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
765: }
766:
767: /* Copy the rtx ORIG recursively, replacing pseudo-regs and labels
768: according to `reg_map' and `label_map'. The original rtl insns
769: will be saved for inlining; this is used to make a copy
770: which is used to finish compiling the inline function itself.
771:
772: If we find a "saved" constant pool entry, one which was replaced with
773: the value of the constant, convert it back to a constant pool entry.
774: Since the pool wasn't touched, this should simply restore the old
775: address.
776:
777: All other kinds of rtx are copied except those that can never be
778: changed during compilation. */
779:
780: static rtx
781: copy_for_inline (orig)
782: rtx orig;
783: {
784: register rtx x = orig;
785: register int i;
786: register enum rtx_code code;
787: register char *format_ptr;
788:
789: if (x == 0)
790: return x;
791:
792: code = GET_CODE (x);
793:
794: /* These types may be freely shared. */
795:
796: switch (code)
797: {
798: case QUEUED:
799: case CONST_INT:
800: case SYMBOL_REF:
801: case PC:
802: case CC0:
803: return x;
804:
805: case CONST_DOUBLE:
806: /* We have to make a new CONST_DOUBLE to ensure that we account for
807: it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
808: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
809: {
810: REAL_VALUE_TYPE d;
811:
812: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
813: return immed_real_const_1 (d, GET_MODE (x));
814: }
815: else
816: return immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
817: VOIDmode);
818:
819: case CONST:
820: /* Get constant pool entry for constant in the pool. */
821: if (RTX_INTEGRATED_P (x))
822: return validize_mem (force_const_mem (GET_MODE (x),
823: copy_for_inline (XEXP (x, 0))));
824: break;
825:
826: case SUBREG:
827: /* Get constant pool entry, but access in different mode. */
828: if (RTX_INTEGRATED_P (x))
829: {
830: rtx new
831: = force_const_mem (GET_MODE (SUBREG_REG (x)),
832: copy_for_inline (XEXP (SUBREG_REG (x), 0)));
833:
834: PUT_MODE (new, GET_MODE (x));
835: return validize_mem (new);
836: }
837: break;
838:
839: case ADDRESS:
840: /* If not special for constant pool error. Else get constant pool
841: address. */
842: if (! RTX_INTEGRATED_P (x))
843: abort ();
844:
845: return XEXP (force_const_mem (GET_MODE (x),
846: copy_for_inline (XEXP (x, 0))), 0);
847:
848: case ASM_OPERANDS:
849: /* If a single asm insn contains multiple output operands
850: then it contains multiple ASM_OPERANDS rtx's that share operand 3.
851: We must make sure that the copied insn continues to share it. */
852: if (orig_asm_operands_vector == XVEC (orig, 3))
853: {
854: x = rtx_alloc (ASM_OPERANDS);
855: XSTR (x, 0) = XSTR (orig, 0);
856: XSTR (x, 1) = XSTR (orig, 1);
857: XINT (x, 2) = XINT (orig, 2);
858: XVEC (x, 3) = copy_asm_operands_vector;
859: XVEC (x, 4) = copy_asm_constraints_vector;
860: XSTR (x, 5) = XSTR (orig, 5);
861: XINT (x, 6) = XINT (orig, 6);
862: return x;
863: }
864: break;
865:
866: case MEM:
867: /* A MEM is usually allowed to be shared if its address is constant
868: or is a constant plus one of the special registers.
869:
870: We do not allow sharing of addresses that are either a special
871: register or the sum of a constant and a special register because
872: it is possible for unshare_all_rtl to copy the address, into memory
873: that won't be saved. Although the MEM can safely be shared, and
874: won't be copied there, the address itself cannot be shared, and may
875: need to be copied.
876:
877: There are also two exceptions with constants: The first is if the
878: constant is a LABEL_REF or the sum of the LABEL_REF
879: and an integer. This case can happen if we have an inline
880: function that supplies a constant operand to the call of another
881: inline function that uses it in a switch statement. In this case,
882: we will be replacing the LABEL_REF, so we have to replace this MEM
883: as well.
884:
885: The second case is if we have a (const (plus (address ..) ...)).
886: In that case we need to put back the address of the constant pool
887: entry. */
888:
889: if (CONSTANT_ADDRESS_P (XEXP (x, 0))
890: && GET_CODE (XEXP (x, 0)) != LABEL_REF
891: && ! (GET_CODE (XEXP (x, 0)) == CONST
892: && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
893: && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
894: == LABEL_REF)
895: || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
896: == ADDRESS)))))
897: return x;
898: break;
899:
900: case LABEL_REF:
901: {
902: /* Must point to the new insn. */
903: return gen_rtx (LABEL_REF, GET_MODE (orig),
904: label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
905: }
906:
907: case REG:
908: if (REGNO (x) > LAST_VIRTUAL_REGISTER)
909: return reg_map [REGNO (x)];
910: else
911: return x;
912:
913: case SET:
914: /* If a parm that gets modified lives in a pseudo-reg,
915: clear its TREE_READONLY to prevent certain optimizations. */
916: {
917: rtx dest = SET_DEST (x);
918:
919: while (GET_CODE (dest) == STRICT_LOW_PART
920: || GET_CODE (dest) == ZERO_EXTRACT
921: || GET_CODE (dest) == SUBREG)
922: dest = XEXP (dest, 0);
923:
924: if (GET_CODE (dest) == REG
925: && REGNO (dest) < max_parm_reg
926: && REGNO (dest) >= FIRST_PSEUDO_REGISTER
927: && parmdecl_map[REGNO (dest)] != 0
928: /* The insn to load an arg pseudo from a stack slot
929: does not count as modifying it. */
930: && in_nonparm_insns)
931: TREE_READONLY (parmdecl_map[REGNO (dest)]) = 0;
932: }
933: break;
934:
935: #if 0 /* This is a good idea, but here is the wrong place for it. */
936: /* Arrange that CONST_INTs always appear as the second operand
937: if they appear, and that `frame_pointer_rtx' or `arg_pointer_rtx'
938: always appear as the first. */
939: case PLUS:
940: if (GET_CODE (XEXP (x, 0)) == CONST_INT
941: || (XEXP (x, 1) == frame_pointer_rtx
942: || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
943: && XEXP (x, 1) == arg_pointer_rtx)))
944: {
945: rtx t = XEXP (x, 0);
946: XEXP (x, 0) = XEXP (x, 1);
947: XEXP (x, 1) = t;
948: }
949: break;
950: #endif
951: }
952:
953: /* Replace this rtx with a copy of itself. */
954:
955: x = rtx_alloc (code);
956: bcopy (orig, x, (sizeof (*x) - sizeof (x->fld)
957: + sizeof (x->fld[0]) * GET_RTX_LENGTH (code)));
958:
959: /* Now scan the subexpressions recursively.
960: We can store any replaced subexpressions directly into X
961: since we know X is not shared! Any vectors in X
962: must be copied if X was copied. */
963:
964: format_ptr = GET_RTX_FORMAT (code);
965:
966: for (i = 0; i < GET_RTX_LENGTH (code); i++)
967: {
968: switch (*format_ptr++)
969: {
970: case 'e':
971: XEXP (x, i) = copy_for_inline (XEXP (x, i));
972: break;
973:
974: case 'u':
975: /* Change any references to old-insns to point to the
976: corresponding copied insns. */
977: XEXP (x, i) = insn_map[INSN_UID (XEXP (x, i))];
978: break;
979:
980: case 'E':
981: if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
982: {
983: register int j;
984:
985: XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
986: for (j = 0; j < XVECLEN (x, i); j++)
987: XVECEXP (x, i, j)
988: = copy_for_inline (XVECEXP (x, i, j));
989: }
990: break;
991: }
992: }
993:
994: if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
995: {
996: orig_asm_operands_vector = XVEC (orig, 3);
997: copy_asm_operands_vector = XVEC (x, 3);
998: copy_asm_constraints_vector = XVEC (x, 4);
999: }
1000:
1001: return x;
1002: }
1003:
1004: /* Unfortunately, we need a global copy of const_equiv map for communication
1005: with a function called from note_stores. Be *very* careful that this
1006: is used properly in the presence of recursion. */
1007:
1008: rtx *global_const_equiv_map;
1009:
1010: #define FIXED_BASE_PLUS_P(X) \
1011: (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
1012: && GET_CODE (XEXP (X, 0)) == REG \
1013: && REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
1014: && REGNO (XEXP (X, 0)) < LAST_VIRTUAL_REGISTER)
1015:
1016: /* Integrate the procedure defined by FNDECL. Note that this function
1017: may wind up calling itself. Since the static variables are not
1018: reentrant, we do not assign them until after the possibility
1019: or recursion is eliminated.
1020:
1021: If IGNORE is nonzero, do not produce a value.
1022: Otherwise store the value in TARGET if it is nonzero and that is convenient.
1023:
1024: Value is:
1025: (rtx)-1 if we could not substitute the function
1026: 0 if we substituted it and it does not produce a value
1027: else an rtx for where the value is stored. */
1028:
1029: rtx
1030: expand_inline_function (fndecl, parms, target, ignore, type, structure_value_addr)
1031: tree fndecl, parms;
1032: rtx target;
1033: int ignore;
1034: tree type;
1035: rtx structure_value_addr;
1036: {
1037: tree formal, actual;
1038: rtx header = DECL_SAVED_INSNS (fndecl);
1039: rtx insns = FIRST_FUNCTION_INSN (header);
1040: rtx parm_insns = FIRST_PARM_INSN (header);
1041: tree *arg_trees;
1042: rtx *arg_vals;
1043: rtx insn;
1044: int max_regno;
1045: register int i;
1046: int min_labelno = FIRST_LABELNO (header);
1047: int max_labelno = LAST_LABELNO (header);
1048: int nargs;
1049: rtx local_return_label = 0;
1050: rtx loc;
1051: rtx temp;
1052: struct inline_remap *map;
1053: rtx cc0_insn = 0;
1054: rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
1055:
1056: /* Allow for equivalences of the pseudos we make for virtual fp and ap. */
1057: max_regno = MAX_REGNUM (header) + 3;
1058: if (max_regno < FIRST_PSEUDO_REGISTER)
1059: abort ();
1060:
1061: nargs = list_length (DECL_ARGUMENTS (fndecl));
1062:
1063: /* We expect PARMS to have the right length; don't crash if not. */
1064: if (list_length (parms) != nargs)
1065: return (rtx)-1;
1066: /* Also check that the parms type match. Since the appropriate
1067: conversions or default promotions have already been applied,
1068: the machine modes should match exactly. */
1069: for (formal = DECL_ARGUMENTS (fndecl),
1070: actual = parms;
1071: formal;
1072: formal = TREE_CHAIN (formal),
1073: actual = TREE_CHAIN (actual))
1074: {
1075: tree arg = TREE_VALUE (actual);
1076: enum machine_mode mode = TYPE_MODE (DECL_ARG_TYPE (formal));
1077: if (mode != TYPE_MODE (TREE_TYPE (arg)))
1078: return (rtx)-1;
1079: /* If they are block mode, the types should match exactly.
1080: They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,
1081: which could happen if the parameter has incomplete type. */
1082: if (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal))
1083: return (rtx)-1;
1084: }
1085:
1086: /* Make a binding contour to keep inline cleanups called at
1087: outer function-scope level from looking like they are shadowing
1088: parameter declarations. */
1089: pushlevel (0);
1090:
1091: /* Make a fresh binding contour that we can easily remove. */
1092: pushlevel (0);
1093: expand_start_bindings (0);
1094: if (GET_CODE (parm_insns) == NOTE
1095: && NOTE_LINE_NUMBER (parm_insns) > 0)
1096: emit_note (NOTE_SOURCE_FILE (parm_insns), NOTE_LINE_NUMBER (parm_insns));
1097:
1098: /* Expand the function arguments. Do this first so that any
1099: new registers get created before we allocate the maps. */
1100:
1101: arg_vals = (rtx *) alloca (nargs * sizeof (rtx));
1102: arg_trees = (tree *) alloca (nargs * sizeof (tree));
1103:
1104: for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;
1105: formal;
1106: formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)
1107: {
1108: /* Actual parameter, converted to the type of the argument within the
1109: function. */
1110: tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
1111: /* Mode of the variable used within the function. */
1112: enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
1113: /* Where parameter is located in the function. */
1114: rtx copy;
1115:
1116: emit_note (DECL_SOURCE_FILE (formal), DECL_SOURCE_LINE (formal));
1117:
1118: arg_trees[i] = arg;
1119: loc = RTVEC_ELT (arg_vector, i);
1120:
1121: /* If this is an object passed by invisible reference, we copy the
1122: object into a stack slot and save its address. If this will go
1123: into memory, we do nothing now. Otherwise, we just expand the
1124: argument. */
1125: if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
1126: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
1127: {
1128: enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
1129: rtx stack_slot = assign_stack_temp (mode, int_size_in_bytes (TREE_TYPE (arg)), 1);
1130:
1131: store_expr (arg, stack_slot, 0);
1132:
1133: arg_vals[i] = XEXP (stack_slot, 0);
1134: }
1135: else if (GET_CODE (loc) != MEM)
1136: arg_vals[i] = expand_expr (arg, 0, mode, EXPAND_SUM);
1137: else
1138: arg_vals[i] = 0;
1139:
1140: if (arg_vals[i] != 0
1141: && (! TREE_READONLY (formal)
1142: /* If the parameter is not read-only, copy our argument through
1143: a register. Also, we cannot use ARG_VALS[I] if it overlaps
1144: TARGET in any way. In the inline function, they will likely
1145: be two different pseudos, and `safe_from_p' will make all
1146: sorts of smart assumptions about their not conflicting.
1147: But if ARG_VALS[I] overlaps TARGET, these assumptions are
1148: wrong, so put ARG_VALS[I] into a fresh register. */
1149: || (target != 0
1150: && (GET_CODE (arg_vals[i]) == REG
1151: || GET_CODE (arg_vals[i]) == SUBREG
1152: || GET_CODE (arg_vals[i]) == MEM)
1153: && reg_overlap_mentioned_p (arg_vals[i], target))))
1154: arg_vals[i] = copy_to_mode_reg (mode, arg_vals[i]);
1155: }
1156:
1157: /* Allocate the structures we use to remap things. */
1158:
1159: map = (struct inline_remap *) alloca (sizeof (struct inline_remap));
1160: map->fndecl = fndecl;
1161:
1162: map->reg_map = (rtx *) alloca (max_regno * sizeof (rtx));
1163: bzero (map->reg_map, max_regno * sizeof (rtx));
1164:
1165: map->label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
1166: map->label_map -= min_labelno;
1167:
1168: map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
1169: bzero (map->insn_map, INSN_UID (header) * sizeof (rtx));
1170: map->min_insnno = 0;
1171: map->max_insnno = INSN_UID (header);
1172:
1173: /* const_equiv_map maps pseudos in our routine to constants, so it needs to
1174: be large enough for all our pseudos. This is the number we are currently
1175: using plus the number in the called routine, plus 15 for each arg,
1176: five to compute the virtual frame pointer, and five for the return value.
1177: This should be enough for most cases. We do not reference entries
1178: outside the range of the map.
1179:
1180: ??? These numbers are quite arbitrary and were obtained by
1181: experimentation. At some point, we should try to allocate the
1182: table after all the parameters are set up so we an more accurately
1183: estimate the number of pseudos we will need. */
1184:
1185: map->const_equiv_map_size
1186: = max_reg_num () + (max_regno - FIRST_PSEUDO_REGISTER) + 15 * nargs + 10;
1187:
1188: map->const_equiv_map
1189: = (rtx *)alloca (map->const_equiv_map_size * sizeof (rtx));
1190: bzero (map->const_equiv_map, map->const_equiv_map_size * sizeof (rtx));
1191:
1192: map->const_age_map
1193: = (unsigned *)alloca (map->const_equiv_map_size * sizeof (unsigned));
1194: bzero (map->const_age_map, map->const_equiv_map_size * sizeof (unsigned));
1195: map->const_age = 0;
1196:
1197: /* Record the current insn in case we have to set up pointers to frame
1198: and argument memory blocks. */
1199: map->insns_at_start = get_last_insn ();
1200:
1201: /* Update the outgoing argument size to allow for those in the inlined
1202: function. */
1203: if (OUTGOING_ARGS_SIZE (header) > current_function_outgoing_args_size)
1204: current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (header);
1205:
1206: /* If the inline function needs to make PIC references, that means
1207: that this function's PIC offset table must be used. */
1208: if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
1209: current_function_uses_pic_offset_table = 1;
1210:
1211: /* Process each argument. For each, set up things so that the function's
1212: reference to the argument will refer to the argument being passed.
1213: We only replace REG with REG here. Any simplifications are done
1214: via const_equiv_map.
1215:
1216: We make two passes: In the first, we deal with parameters that will
1217: be placed into registers, since we need to ensure that the allocated
1218: register number fits in const_equiv_map. Then we store all non-register
1219: parameters into their memory location. */
1220:
1221: for (i = 0; i < nargs; i++)
1222: {
1223: rtx copy = arg_vals[i];
1224:
1225: loc = RTVEC_ELT (arg_vector, i);
1226:
1227: /* There are three cases, each handled separately. */
1228: if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
1229: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
1230: {
1231: /* This must be an object passed by invisible reference (it could
1232: also be a variable-sized object, but we forbid inlining functions
1233: with variable-sized arguments). COPY is the address of the
1234: actual value (this computation will cause it to be copied). We
1235: map that address for the register, noting the actual address as
1236: an equivalent in case it can be substituted into the insns. */
1237:
1238: if (GET_CODE (copy) != REG)
1239: {
1240: temp = copy_addr_to_reg (copy);
1241: if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
1242: {
1243: map->const_equiv_map[REGNO (temp)] = copy;
1244: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1245: }
1246: copy = temp;
1247: }
1248: map->reg_map[REGNO (XEXP (loc, 0))] = copy;
1249: }
1250: else if (GET_CODE (loc) == MEM)
1251: {
1252: /* This is the case of a parameter that lives in memory.
1253: It will live in the block we allocate in the called routine's
1254: frame that simulates the incoming argument area. Do nothing
1255: now; we will call store_expr later. */
1256: ;
1257: }
1258: else if (GET_CODE (loc) == REG)
1259: {
1260: /* This is the good case where the parameter is in a register.
1261: If it is read-only and our argument is a constant, set up the
1262: constant equivalence. */
1263: if (GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
1264: {
1265: temp = copy_to_mode_reg (GET_MODE (loc), copy);
1266: if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
1267: {
1268: map->const_equiv_map[REGNO (temp)] = copy;
1269: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1270: }
1271: copy = temp;
1272: }
1273: map->reg_map[REGNO (loc)] = copy;
1274: }
1275: else
1276: abort ();
1277:
1278: /* Free any temporaries we made setting up this parameter. */
1279: free_temp_slots ();
1280: }
1281:
1282: /* Now do the parameters that will be placed in memory. */
1283:
1284: for (formal = DECL_ARGUMENTS (fndecl), i = 0;
1285: formal; formal = TREE_CHAIN (formal), i++)
1286: {
1287: rtx copy = arg_vals[i];
1288:
1289: loc = RTVEC_ELT (arg_vector, i);
1290:
1291: if (GET_CODE (loc) == MEM
1292: /* Exclude case handled above. */
1293: && ! (GET_CODE (XEXP (loc, 0)) == REG
1294: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
1295: {
1296: emit_note (DECL_SOURCE_FILE (formal), DECL_SOURCE_LINE (formal));
1297:
1298: /* Compute the address in the area we reserved and store the
1299: value there. */
1300: temp = copy_rtx_and_substitute (loc, map);
1301: subst_constants (&temp, 0, map);
1302: apply_change_group ();
1303: if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
1304: temp = change_address (temp, VOIDmode, XEXP (temp, 0));
1305: store_expr (arg_trees[i], temp, 0);
1306:
1307: /* Free any temporaries we made setting up this parameter. */
1308: free_temp_slots ();
1309: }
1310: }
1311:
1312: /* Deal with the places that the function puts its result.
1313: We are driven by what is placed into DECL_RESULT.
1314:
1315: Initially, we assume that we don't have anything special handling for
1316: REG_FUNCTION_RETURN_VALUE_P. */
1317:
1318: map->inline_target = 0;
1319: loc = DECL_RTL (DECL_RESULT (fndecl));
1320: if (TYPE_MODE (type) == VOIDmode)
1321: /* There is no return value to worry about. */
1322: ;
1323: else if (GET_CODE (loc) == MEM)
1324: {
1325: if (! structure_value_addr || ! aggregate_value_p (DECL_RESULT (fndecl)))
1326: abort ();
1327:
1328: /* Pass the function the address in which to return a structure value.
1329: Note that a constructor can cause someone to call us with
1330: STRUCTURE_VALUE_ADDR, but the initialization takes place
1331: via the first parameter, rather than the struct return address.
1332:
1333: We have two cases: If the address is a simple register indirect,
1334: use the mapping mechanism to point that register to our structure
1335: return address. Otherwise, store the structure return value into
1336: the place that it will be referenced from. */
1337:
1338: if (GET_CODE (XEXP (loc, 0)) == REG)
1339: {
1340: temp = force_reg (Pmode, structure_value_addr);
1341: map->reg_map[REGNO (XEXP (loc, 0))] = temp;
1342: if (CONSTANT_P (structure_value_addr)
1343: || (GET_CODE (structure_value_addr) == PLUS
1344: && XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx
1345: && GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))
1346: {
1347: map->const_equiv_map[REGNO (temp)] = structure_value_addr;
1348: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1349: }
1350: }
1351: else
1352: {
1353: temp = copy_rtx_and_substitute (loc, map);
1354: subst_constants (&temp, 0, map);
1355: apply_change_group ();
1356: emit_move_insn (temp, structure_value_addr);
1357: }
1358: }
1359: else if (ignore)
1360: /* We will ignore the result value, so don't look at its structure.
1361: Note that preparations for an aggregate return value
1362: do need to be made (above) even if it will be ignored. */
1363: ;
1364: else if (GET_CODE (loc) == REG)
1365: {
1366: /* The function returns an object in a register and we use the return
1367: value. Set up our target for remapping. */
1368:
1369: /* Machine mode function was declared to return. */
1370: enum machine_mode departing_mode = TYPE_MODE (type);
1371: /* (Possibly wider) machine mode it actually computes
1372: (for the sake of callers that fail to declare it right). */
1373: enum machine_mode arriving_mode
1374: = TYPE_MODE (TREE_TYPE (DECL_RESULT (fndecl)));
1375: rtx reg_to_map;
1376:
1377: /* Don't use MEMs as direct targets because on some machines
1378: substituting a MEM for a REG makes invalid insns.
1379: Let the combiner substitute the MEM if that is valid. */
1380: if (target == 0 || GET_CODE (target) != REG
1381: || GET_MODE (target) != departing_mode)
1382: target = gen_reg_rtx (departing_mode);
1383:
1384: /* If function's value was promoted before return,
1385: avoid machine mode mismatch when we substitute INLINE_TARGET.
1386: But TARGET is what we will return to the caller. */
1387: if (arriving_mode != departing_mode)
1388: reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
1389: else
1390: reg_to_map = target;
1391:
1392: /* Usually, the result value is the machine's return register.
1393: Sometimes it may be a pseudo. Handle both cases. */
1394: if (REG_FUNCTION_VALUE_P (loc))
1395: map->inline_target = reg_to_map;
1396: else
1397: map->reg_map[REGNO (loc)] = reg_to_map;
1398: }
1399:
1400: /* Make new label equivalences for the labels in the called function. */
1401: for (i = min_labelno; i < max_labelno; i++)
1402: map->label_map[i] = gen_label_rtx ();
1403:
1404: /* Perform postincrements before actually calling the function. */
1405: emit_queue ();
1406:
1407: /* Clean up stack so that variables might have smaller offsets. */
1408: do_pending_stack_adjust ();
1409:
1410: /* Save a copy of the location of const_equiv_map for mark_stores, called
1411: via note_stores. */
1412: global_const_equiv_map = map->const_equiv_map;
1413:
1414: /* Now copy the insns one by one. Do this in two passes, first the insns and
1415: then their REG_NOTES, just like save_for_inline. */
1416:
1417: /* This loop is very similar to the loop in copy_loop_body in unroll.c. */
1418:
1419: for (insn = insns; insn; insn = NEXT_INSN (insn))
1420: {
1421: rtx copy, pattern;
1422:
1423: map->orig_asm_operands_vector = 0;
1424:
1425: switch (GET_CODE (insn))
1426: {
1427: case INSN:
1428: pattern = PATTERN (insn);
1429: copy = 0;
1430: if (GET_CODE (pattern) == USE
1431: && GET_CODE (XEXP (pattern, 0)) == REG
1432: && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
1433: /* The (USE (REG n)) at return from the function should
1434: be ignored since we are changing (REG n) into
1435: inline_target. */
1436: break;
1437:
1438: /* Ignore setting a function value that we don't want to use. */
1439: if (map->inline_target == 0
1440: && GET_CODE (pattern) == SET
1441: && GET_CODE (SET_DEST (pattern)) == REG
1442: && REG_FUNCTION_VALUE_P (SET_DEST (pattern)))
1443: break;
1444:
1445: copy = emit_insn (copy_rtx_and_substitute (pattern, map));
1446: /* REG_NOTES will be copied later. */
1447:
1448: #ifdef HAVE_cc0
1449: /* If this insn is setting CC0, it may need to look at
1450: the insn that uses CC0 to see what type of insn it is.
1451: In that case, the call to recog via validate_change will
1452: fail. So don't substitute constants here. Instead,
1453: do it when we emit the following insn.
1454:
1455: For example, see the pyr.md file. That machine has signed and
1456: unsigned compares. The compare patterns must check the
1457: following branch insn to see which what kind of compare to
1458: emit.
1459:
1460: If the previous insn set CC0, substitute constants on it as
1461: well. */
1462: if (sets_cc0_p (PATTERN (copy)) != 0)
1463: cc0_insn = copy;
1464: else
1465: {
1466: if (cc0_insn)
1467: try_constants (cc0_insn, map);
1468: cc0_insn = 0;
1469: try_constants (copy, map);
1470: }
1471: #else
1472: try_constants (copy, map);
1473: #endif
1474: break;
1475:
1476: case JUMP_INSN:
1477: if (GET_CODE (PATTERN (insn)) == RETURN)
1478: {
1479: if (local_return_label == 0)
1480: local_return_label = gen_label_rtx ();
1481: pattern = gen_jump (local_return_label);
1482: }
1483: else
1484: pattern = copy_rtx_and_substitute (PATTERN (insn), map);
1485:
1486: copy = emit_jump_insn (pattern);
1487:
1488: #ifdef HAVE_cc0
1489: if (cc0_insn)
1490: try_constants (cc0_insn, map);
1491: cc0_insn = 0;
1492: #endif
1493: try_constants (copy, map);
1494:
1495: /* If this used to be a conditional jump insn but whose branch
1496: direction is now know, we must do something special. */
1497: if (condjump_p (insn) && ! simplejump_p (insn) && map->last_pc_value)
1498: {
1499: #ifdef HAVE_cc0
1500: /* The previous insn set cc0 for us. So delete it. */
1501: delete_insn (PREV_INSN (copy));
1502: #endif
1503:
1504: /* If this is now a no-op, delete it. */
1505: if (map->last_pc_value == pc_rtx)
1506: {
1507: delete_insn (copy);
1508: copy = 0;
1509: }
1510: else
1511: /* Otherwise, this is unconditional jump so we must put a
1512: BARRIER after it. We could do some dead code elimination
1513: here, but jump.c will do it just as well. */
1514: emit_barrier ();
1515: }
1516: break;
1517:
1518: case CALL_INSN:
1519: pattern = copy_rtx_and_substitute (PATTERN (insn), map);
1520: copy = emit_call_insn (pattern);
1521:
1522: #ifdef HAVE_cc0
1523: if (cc0_insn)
1524: try_constants (cc0_insn, map);
1525: cc0_insn = 0;
1526: #endif
1527: try_constants (copy, map);
1528:
1529: /* Be lazy and assume CALL_INSNs clobber all hard registers. */
1530: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1531: map->const_equiv_map[i] = 0;
1532: break;
1533:
1534: case CODE_LABEL:
1535: copy = emit_label (map->label_map[CODE_LABEL_NUMBER (insn)]);
1536: map->const_age++;
1537: break;
1538:
1539: case BARRIER:
1540: copy = emit_barrier ();
1541: break;
1542:
1543: case NOTE:
1544: /* It is important to discard function-end and function-beg notes,
1545: so we have only one of each in the current function.
1546: Also, NOTE_INSN_DELETED notes aren't useful (save_for_inline
1547: deleted these in the copy used for continuing compilation,
1548: not the copy used for inlining). */
1549: if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
1550: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
1551: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
1552: copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
1553: else
1554: copy = 0;
1555: break;
1556:
1557: default:
1558: abort ();
1559: break;
1560: }
1561:
1562: if (copy)
1563: RTX_INTEGRATED_P (copy) = 1;
1564:
1565: map->insn_map[INSN_UID (insn)] = copy;
1566: }
1567:
1568: /* Now copy the REG_NOTES. */
1569: for (insn = insns; insn; insn = NEXT_INSN (insn))
1570: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
1571: && map->insn_map[INSN_UID (insn)])
1572: REG_NOTES (map->insn_map[INSN_UID (insn)])
1573: = copy_rtx_and_substitute (REG_NOTES (insn), map);
1574:
1575: if (local_return_label)
1576: emit_label (local_return_label);
1577:
1578: /* Make copies of the decls of the symbols in the inline function, so that
1579: the copies of the variables get declared in the current function. Set
1580: up things so that lookup_static_chain knows that to interpret registers
1581: in SAVE_EXPRs for TYPE_SIZEs as local. */
1582:
1583: inline_function_decl = fndecl;
1584: integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map, 0);
1585: integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
1586: inline_function_decl = 0;
1587:
1588: /* End the scope containing the copied formal parameter variables. */
1589:
1590: expand_end_bindings (getdecls (), 1, 1);
1591: poplevel (1, 1, 0);
1592: poplevel (0, 0, 0);
1593: emit_line_note (input_filename, lineno);
1594:
1595: if (structure_value_addr)
1596: return gen_rtx (MEM, TYPE_MODE (type),
1597: memory_address (TYPE_MODE (type), structure_value_addr));
1598: return target;
1599: }
1600:
1601: /* Given a chain of PARM_DECLs, ARGS, copy each decl into a VAR_DECL,
1602: push all of those decls and give each one the corresponding home. */
1603:
1604: static void
1605: integrate_parm_decls (args, map, arg_vector)
1606: tree args;
1607: struct inline_remap *map;
1608: rtvec arg_vector;
1609: {
1610: register tree tail;
1611: register int i;
1612:
1613: for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
1614: {
1615: register tree decl = build_decl (VAR_DECL, DECL_NAME (tail),
1616: TREE_TYPE (tail));
1617: rtx new_decl_rtl
1618: = copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map);
1619:
1620: /* These args would always appear unused, if not for this. */
1621: TREE_USED (decl) = 1;
1622: /* Prevent warning for shadowing with these. */
1623: DECL_FROM_INLINE (decl) = 1;
1624: pushdecl (decl);
1625: /* Fully instantiate the address with the equivalent form so that the
1626: debugging information contains the actual register, instead of the
1627: virtual register. Do this by not passing an insn to
1628: subst_constants. */
1629: subst_constants (&new_decl_rtl, 0, map);
1630: apply_change_group ();
1631: DECL_RTL (decl) = new_decl_rtl;
1632: }
1633: }
1634:
1635: /* Given a BLOCK node LET, push decls and levels so as to construct in the
1636: current function a tree of contexts isomorphic to the one that is given.
1637:
1638: LEVEL indicates how far down into the BLOCK tree is the node we are
1639: currently traversing. It is always zero for the initial call.
1640:
1641: MAP, if nonzero, is a pointer to a inline_remap map which indicates how
1642: registers used in the DECL_RTL field should be remapped. If it is zero,
1643: no mapping is necessary.
1644:
1645: FUNCTIONBODY indicates whether the top level block tree corresponds to
1646: a function body. This is identical in meaning to the functionbody
1647: argument of poplevel. */
1648:
1649: static void
1650: integrate_decl_tree (let, level, map, functionbody)
1651: tree let;
1652: int level;
1653: struct inline_remap *map;
1654: int functionbody;
1655: {
1656: tree t, node;
1657:
1658: pushlevel (0);
1659:
1660: for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
1661: {
1662: tree d = build_decl (TREE_CODE (t), DECL_NAME (t), TREE_TYPE (t));
1663: DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t);
1664: DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t);
1665: if (! functionbody && DECL_RTL (t) != 0)
1666: {
1667: DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map);
1668: /* Fully instantiate the address with the equivalent form so that the
1669: debugging information contains the actual register, instead of the
1670: virtual register. Do this by not passing an insn to
1671: subst_constants. */
1672: subst_constants (&DECL_RTL (d), 0, map);
1673: apply_change_group ();
1674: }
1675: else if (DECL_RTL (t))
1676: DECL_RTL (d) = copy_rtx (DECL_RTL (t));
1677: TREE_EXTERNAL (d) = TREE_EXTERNAL (t);
1678: TREE_STATIC (d) = TREE_STATIC (t);
1679: TREE_PUBLIC (d) = TREE_PUBLIC (t);
1680: TREE_CONSTANT (d) = TREE_CONSTANT (t);
1681: TREE_ADDRESSABLE (d) = TREE_ADDRESSABLE (t);
1682: TREE_READONLY (d) = TREE_READONLY (t);
1683: TREE_SIDE_EFFECTS (d) = TREE_SIDE_EFFECTS (t);
1684: /* These args would always appear unused, if not for this. */
1685: TREE_USED (d) = 1;
1686: /* Prevent warning for shadowing with these. */
1687: DECL_FROM_INLINE (d) = 1;
1688: pushdecl (d);
1689: }
1690:
1691: for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
1692: integrate_decl_tree (t, level + 1, map, functionbody);
1693:
1694: node = poplevel (level > 0, 0, level == 0 && functionbody);
1695: if (node)
1696: TREE_USED (node) = TREE_USED (let);
1697: }
1698:
1699: /* Create a new copy of an rtx.
1700: Recursively copies the operands of the rtx,
1701: except for those few rtx codes that are sharable.
1702:
1703: We always return an rtx that is similar to that incoming rtx, with the
1704: exception of possibly changing a REG to a SUBREG or vice versa. No
1705: rtl is ever emitted.
1706:
1707: Handle constants that need to be placed in the constant pool by
1708: calling `force_const_mem'. */
1709:
1710: rtx
1711: copy_rtx_and_substitute (orig, map)
1712: register rtx orig;
1713: struct inline_remap *map;
1714: {
1715: register rtx copy, temp;
1716: register int i, j;
1717: register RTX_CODE code;
1718: register enum machine_mode mode;
1719: register char *format_ptr;
1720: int regno;
1721:
1722: if (orig == 0)
1723: return 0;
1724:
1725: code = GET_CODE (orig);
1726: mode = GET_MODE (orig);
1727:
1728: switch (code)
1729: {
1730: case REG:
1731: /* If the stack pointer register shows up, it must be part of
1732: stack-adjustments (*not* because we eliminated the frame pointer!).
1733: Small hard registers are returned as-is. Pseudo-registers
1734: go through their `reg_map'. */
1735: regno = REGNO (orig);
1736: if (regno <= LAST_VIRTUAL_REGISTER)
1737: {
1738: /* Some hard registers are also mapped,
1739: but others are not translated. */
1740: if (map->reg_map[regno] != 0)
1741: return map->reg_map[regno];
1742:
1743: /* If this is the virtual frame pointer, make space in current
1744: function's stack frame for the stack frame of the inline function.
1745:
1746: Copy the address of this area into a pseudo. Map
1747: virtual_stack_vars_rtx to this pseudo and set up a constant
1748: equivalence for it to be the address. This will substitute the
1749: address into insns where it can be substituted and use the new
1750: pseudo where it can't. */
1751: if (regno == VIRTUAL_STACK_VARS_REGNUM)
1752: {
1753: rtx loc, seq;
1754: int size = DECL_FRAME_SIZE (map->fndecl);
1755: int rounded;
1756:
1757: start_sequence ();
1758: loc = assign_stack_temp (BLKmode, size, 1);
1759: loc = XEXP (loc, 0);
1760: #ifdef FRAME_GROWS_DOWNWARD
1761: /* In this case, virtual_stack_vars_rtx points to one byte
1762: higher than the top of the frame area. So compute the offset
1763: to one byte higher than our substitute frame.
1764: Keep the fake frame pointer aligned like a real one. */
1765: rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
1766: loc = plus_constant (loc, rounded);
1767: #endif
1768: map->reg_map[regno] = force_operand (loc, 0);
1769: map->const_equiv_map[regno] = loc;
1770: map->const_age_map[regno] = CONST_AGE_PARM;
1771:
1772: seq = gen_sequence ();
1773: end_sequence ();
1774: emit_insn_after (seq, map->insns_at_start);
1775: return map->reg_map[regno];
1776: }
1777: else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
1778: {
1779: /* Do the same for a block to contain any arguments referenced
1780: in memory. */
1781: rtx loc, seq;
1782: int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));
1783:
1784: start_sequence ();
1785: loc = assign_stack_temp (BLKmode, size, 1);
1786: loc = XEXP (loc, 0);
1787: map->reg_map[regno] = force_operand (loc, 0);
1788: map->const_equiv_map[regno] = loc;
1789: map->const_age_map[regno] = CONST_AGE_PARM;
1790:
1791: seq = gen_sequence ();
1792: end_sequence ();
1793: emit_insn_after (seq, map->insns_at_start);
1794: return map->reg_map[regno];
1795: }
1796: else if (REG_FUNCTION_VALUE_P (orig))
1797: {
1798: /* This is a reference to the function return value. If
1799: the function doesn't have a return value, error. If the
1800: mode doesn't agree, make a SUBREG. */
1801: if (map->inline_target == 0)
1802: /* Must be unrolling loops or replicating code if we
1803: reach here, so return the register unchanged. */
1804: return orig;
1805: else if (mode != GET_MODE (map->inline_target))
1806: return gen_rtx (SUBREG, mode, map->inline_target, 0);
1807: else
1808: return map->inline_target;
1809: }
1810: return orig;
1811: }
1812: if (map->reg_map[regno] == NULL)
1813: {
1814: map->reg_map[regno] = gen_reg_rtx (mode);
1815: REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
1816: REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
1817: RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
1818: /* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
1819: }
1820: return map->reg_map[regno];
1821:
1822: case SUBREG:
1823: copy = copy_rtx_and_substitute (SUBREG_REG (orig), map);
1824: /* SUBREG is ordinary, but don't make nested SUBREGs. */
1825: if (GET_CODE (copy) == SUBREG)
1826: return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy),
1827: SUBREG_WORD (orig) + SUBREG_WORD (copy));
1828: else
1829: return gen_rtx (SUBREG, GET_MODE (orig), copy,
1830: SUBREG_WORD (orig));
1831:
1832: case USE:
1833: case CLOBBER:
1834: /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
1835: to (use foo). */
1836: copy = copy_rtx_and_substitute (XEXP (orig, 0), map);
1837: if (GET_CODE (copy) == SUBREG)
1838: copy = SUBREG_REG (copy);
1839: return gen_rtx (code, VOIDmode, copy);
1840:
1841: case CODE_LABEL:
1842: LABEL_PRESERVE_P (map->label_map[CODE_LABEL_NUMBER (orig)])
1843: = LABEL_PRESERVE_P (orig);
1844: return map->label_map[CODE_LABEL_NUMBER (orig)];
1845:
1846: case LABEL_REF:
1847: copy = rtx_alloc (LABEL_REF);
1848: PUT_MODE (copy, mode);
1849: XEXP (copy, 0) = map->label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))];
1850: LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
1851: return copy;
1852:
1853: case PC:
1854: case CC0:
1855: case CONST_INT:
1856: case SYMBOL_REF:
1857: return orig;
1858:
1859: case CONST_DOUBLE:
1860: /* We have to make a new copy of this CONST_DOUBLE because don't want
1861: to use the old value of CONST_DOUBLE_MEM. Also, this may be a
1862: duplicate of a CONST_DOUBLE we have already seen. */
1863: if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
1864: {
1865: REAL_VALUE_TYPE d;
1866:
1867: REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
1868: return immed_real_const_1 (d, GET_MODE (orig));
1869: }
1870: else
1871: return immed_double_const (CONST_DOUBLE_LOW (orig),
1872: CONST_DOUBLE_HIGH (orig), VOIDmode);
1873:
1874: case CONST:
1875: /* Make new constant pool entry for a constant
1876: that was in the pool of the inline function. */
1877: if (RTX_INTEGRATED_P (orig))
1878: {
1879: /* If this was an address of a constant pool entry that itself
1880: had to be placed in the constant pool, it might not be a
1881: valid address. So the recursive call below might turn it
1882: into a register. In that case, it isn't a constant any
1883: more, so return it. This has the potential of changing a
1884: MEM into a REG, but we'll assume that it safe. */
1885: temp = copy_rtx_and_substitute (XEXP (orig, 0), map);
1886: if (! CONSTANT_P (temp))
1887: return temp;
1888: return validize_mem (force_const_mem (GET_MODE (orig), temp));
1889: }
1890: break;
1891:
1892: case ADDRESS:
1893: /* If from constant pool address, make new constant pool entry and
1894: return its address. */
1895: if (! RTX_INTEGRATED_P (orig))
1896: abort ();
1897:
1898: temp = force_const_mem (GET_MODE (orig),
1899: copy_rtx_and_substitute (XEXP (orig, 0), map));
1900:
1901: #if 0
1902: /* Legitimizing the address here is incorrect.
1903:
1904: The only ADDRESS rtx's that can reach here are ones created by
1905: save_constants. Hence the operand of the ADDRESS is always legal
1906: in this position of the instruction, since the original rtx without
1907: the ADDRESS was legal.
1908:
1909: The reason we don't legitimize the address here is that on the
1910: Sparc, the caller may have a (high ...) surrounding this ADDRESS.
1911: This code forces the operand of the address to a register, which
1912: fails because we can not take the HIGH part of a register.
1913:
1914: Also, change_address may create new registers. These registers
1915: will not have valid reg_map entries. This can cause try_constants()
1916: to fail because assumes that all registers in the rtx have valid
1917: reg_map entries, and it may end up replacing one of these new
1918: registers with junk. */
1919:
1920: if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
1921: temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
1922: #endif
1923:
1924: return XEXP (temp, 0);
1925:
1926: case ASM_OPERANDS:
1927: /* If a single asm insn contains multiple output operands
1928: then it contains multiple ASM_OPERANDS rtx's that share operand 3.
1929: We must make sure that the copied insn continues to share it. */
1930: if (map->orig_asm_operands_vector == XVEC (orig, 3))
1931: {
1932: copy = rtx_alloc (ASM_OPERANDS);
1933: XSTR (copy, 0) = XSTR (orig, 0);
1934: XSTR (copy, 1) = XSTR (orig, 1);
1935: XINT (copy, 2) = XINT (orig, 2);
1936: XVEC (copy, 3) = map->copy_asm_operands_vector;
1937: XVEC (copy, 4) = map->copy_asm_constraints_vector;
1938: XSTR (copy, 5) = XSTR (orig, 5);
1939: XINT (copy, 6) = XINT (orig, 6);
1940: return copy;
1941: }
1942: break;
1943:
1944: case CALL:
1945: /* This is given special treatment because the first
1946: operand of a CALL is a (MEM ...) which may get
1947: forced into a register for cse. This is undesirable
1948: if function-address cse isn't wanted or if we won't do cse. */
1949: #ifndef NO_FUNCTION_CSE
1950: if (! (optimize && ! flag_no_function_cse))
1951: #endif
1952: return gen_rtx (CALL, GET_MODE (orig),
1953: gen_rtx (MEM, GET_MODE (XEXP (orig, 0)),
1954: copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0), map)),
1955: copy_rtx_and_substitute (XEXP (orig, 1), map));
1956: break;
1957:
1958: #if 0
1959: /* Must be ifdefed out for loop unrolling to work. */
1960: case RETURN:
1961: abort ();
1962: #endif
1963:
1964: case SET:
1965: /* If this is setting fp or ap, it means that we have a nonlocal goto.
1966: Don't alter that.
1967: If the nonlocal goto is into the current function,
1968: this will result in unnecessarily bad code, but should work. */
1969: if (SET_DEST (orig) == virtual_stack_vars_rtx
1970: || SET_DEST (orig) == virtual_incoming_args_rtx)
1971: return gen_rtx (SET, VOIDmode, SET_DEST (orig),
1972: copy_rtx_and_substitute (SET_SRC (orig), map));
1973: break;
1974:
1975: case MEM:
1976: copy = rtx_alloc (MEM);
1977: PUT_MODE (copy, mode);
1978: XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
1979: MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
1980: MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
1981: RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
1982: return copy;
1983: }
1984:
1985: copy = rtx_alloc (code);
1986: PUT_MODE (copy, mode);
1987: copy->in_struct = orig->in_struct;
1988: copy->volatil = orig->volatil;
1989: copy->unchanging = orig->unchanging;
1990:
1991: format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
1992:
1993: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
1994: {
1995: switch (*format_ptr++)
1996: {
1997: case '0':
1998: break;
1999:
2000: case 'e':
2001: XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i), map);
2002: break;
2003:
2004: case 'u':
2005: /* Change any references to old-insns to point to the
2006: corresponding copied insns. */
2007: XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
2008: break;
2009:
2010: case 'E':
2011: XVEC (copy, i) = XVEC (orig, i);
2012: if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
2013: {
2014: XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
2015: for (j = 0; j < XVECLEN (copy, i); j++)
2016: XVECEXP (copy, i, j)
2017: = copy_rtx_and_substitute (XVECEXP (orig, i, j), map);
2018: }
2019: break;
2020:
2021: case 'i':
2022: XINT (copy, i) = XINT (orig, i);
2023: break;
2024:
2025: case 's':
2026: XSTR (copy, i) = XSTR (orig, i);
2027: break;
2028:
2029: default:
2030: abort ();
2031: }
2032: }
2033:
2034: if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
2035: {
2036: map->orig_asm_operands_vector = XVEC (orig, 3);
2037: map->copy_asm_operands_vector = XVEC (copy, 3);
2038: map->copy_asm_constraints_vector = XVEC (copy, 4);
2039: }
2040:
2041: return copy;
2042: }
2043:
2044: /* Substitute known constant values into INSN, if that is valid. */
2045:
2046: void
2047: try_constants (insn, map)
2048: rtx insn;
2049: struct inline_remap *map;
2050: {
2051: int i;
2052:
2053: map->num_sets = 0;
2054: subst_constants (&PATTERN (insn), insn, map);
2055:
2056: /* Apply the changes if they are valid; otherwise discard them. */
2057: apply_change_group ();
2058:
2059: /* Show we don't know the value of anything stored or clobbered. */
2060: note_stores (PATTERN (insn), mark_stores);
2061: map->last_pc_value = 0;
2062: #ifdef HAVE_cc0
2063: map->last_cc0_value = 0;
2064: #endif
2065:
2066: /* Set up any constant equivalences made in this insn. */
2067: for (i = 0; i < map->num_sets; i++)
2068: {
2069: if (GET_CODE (map->equiv_sets[i].dest) == REG)
2070: {
2071: int regno = REGNO (map->equiv_sets[i].dest);
2072:
2073: if (map->const_equiv_map[regno] == 0
2074: /* Following clause is a hack to make case work where GNU C++
2075: reassigns a variable to make cse work right. */
2076: || ! rtx_equal_p (map->const_equiv_map[regno],
2077: map->equiv_sets[i].equiv))
2078: {
2079: map->const_equiv_map[regno] = map->equiv_sets[i].equiv;
2080: map->const_age_map[regno] = map->const_age;
2081: }
2082: }
2083: else if (map->equiv_sets[i].dest == pc_rtx)
2084: map->last_pc_value = map->equiv_sets[i].equiv;
2085: #ifdef HAVE_cc0
2086: else if (map->equiv_sets[i].dest == cc0_rtx)
2087: map->last_cc0_value = map->equiv_sets[i].equiv;
2088: #endif
2089: }
2090: }
2091:
2092: /* Substitute known constants for pseudo regs in the contents of LOC,
2093: which are part of INSN.
2094: If INSN is zero, the substition should always be done (this is used to
2095: update DECL_RTL).
2096: These changes are taken out by try_constants if the result is not valid.
2097:
2098: Note that we are more concerned with determining when the result of a SET
2099: is a constant, for further propagation, than actually inserting constants
2100: into insns; cse will do the latter task better.
2101:
2102: This function is also used to adjust address of items previously addressed
2103: via the virtual stack variable or virtual incoming arguments registers. */
2104:
2105: static void
2106: subst_constants (loc, insn, map)
2107: rtx *loc;
2108: rtx insn;
2109: struct inline_remap *map;
2110: {
2111: rtx x = *loc;
2112: register int i;
2113: register enum rtx_code code;
2114: register char *format_ptr;
2115: int num_changes = num_validated_changes ();
2116: rtx new = 0;
2117: enum machine_mode op0_mode;
2118:
2119: code = GET_CODE (x);
2120:
2121: switch (code)
2122: {
2123: case PC:
2124: case CONST_INT:
2125: case CONST_DOUBLE:
2126: case SYMBOL_REF:
2127: case CONST:
2128: case LABEL_REF:
2129: case ADDRESS:
2130: return;
2131:
2132: #ifdef HAVE_cc0
2133: case CC0:
2134: validate_change (insn, loc, map->last_cc0_value, 1);
2135: return;
2136: #endif
2137:
2138: case USE:
2139: case CLOBBER:
2140: /* The only thing we can do with a USE or CLOBBER is possibly do
2141: some substitutions in a MEM within it. */
2142: if (GET_CODE (XEXP (x, 0)) == MEM)
2143: subst_constants (&XEXP (XEXP (x, 0), 0), insn, map);
2144: return;
2145:
2146: case REG:
2147: /* Substitute for parms and known constants. Don't replace
2148: hard regs used as user variables with constants. */
2149: {
2150: int regno = REGNO (x);
2151:
2152: if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
2153: && regno < map->const_equiv_map_size
2154: && map->const_equiv_map[regno] != 0
2155: && map->const_age_map[regno] >= map->const_age)
2156: validate_change (insn, loc, map->const_equiv_map[regno], 1);
2157: return;
2158: }
2159:
2160: case SUBREG:
2161: /* SUBREG is ordinary, but don't make nested SUBREGs and try to simplify
2162: constants. */
2163: {
2164: rtx inner = SUBREG_REG (x);
2165: rtx new = 0;
2166:
2167: /* We can't call subst_constants on &SUBREG_REG (x) because any
2168: constant or SUBREG wouldn't be valid inside our SUBEG. Instead,
2169: see what is inside, try to form the new SUBREG and see if that is
2170: valid. We handle two cases: extracting a full word in an
2171: integral mode and extracting the low part. */
2172: subst_constants (&inner, 0, map);
2173:
2174: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
2175: && GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
2176: && GET_MODE (SUBREG_REG (x)) != VOIDmode)
2177: new = operand_subword (inner, SUBREG_WORD (x), 0,
2178: GET_MODE (SUBREG_REG (x)));
2179:
2180: if (new == 0 && subreg_lowpart_p (x))
2181: new = gen_lowpart_common (GET_MODE (x), inner);
2182:
2183: if (new)
2184: validate_change (insn, loc, new, 1);
2185:
2186: return;
2187: }
2188:
2189: case MEM:
2190: subst_constants (&XEXP (x, 0), insn, map);
2191:
2192: /* If a memory address got spoiled, change it back. */
2193: if (insn != 0 && num_validated_changes () != num_changes
2194: && !memory_address_p (GET_MODE (x), XEXP (x, 0)))
2195: cancel_changes (num_changes);
2196: return;
2197:
2198: case SET:
2199: {
2200: /* Substitute constants in our source, and in any arguments to a
2201: complex (e..g, ZERO_EXTRACT) destination, but not in the destination
2202: itself. */
2203: rtx *dest_loc = &SET_DEST (x);
2204: rtx dest = *dest_loc;
2205: rtx src, tem;
2206:
2207: subst_constants (&SET_SRC (x), insn, map);
2208: src = SET_SRC (x);
2209:
2210: while (GET_CODE (*dest_loc) == ZERO_EXTRACT
2211: || GET_CODE (*dest_loc) == SIGN_EXTRACT
2212: || GET_CODE (*dest_loc) == SUBREG
2213: || GET_CODE (*dest_loc) == STRICT_LOW_PART)
2214: {
2215: if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
2216: {
2217: subst_constants (&XEXP (*dest_loc, 1), insn, map);
2218: subst_constants (&XEXP (*dest_loc, 2), insn, map);
2219: }
2220: dest_loc = &XEXP (*dest_loc, 0);
2221: }
2222:
2223: /* Check for the case of DEST a SUBREG, both it and the underlying
2224: register are less than one word, and the SUBREG has the wider mode.
2225: In the case, we are really setting the underlying register to the
2226: source converted to the mode of DEST. So indicate that. */
2227: if (GET_CODE (dest) == SUBREG
2228: && GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
2229: && GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
2230: && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
2231: <= GET_MODE_SIZE (GET_MODE (dest)))
2232: && (tem = gen_lowpart_if_possible (GET_MODE (dest), src)))
2233: src = tem, dest = SUBREG_REG (dest);
2234:
2235: /* If storing a recognizable value save it for later recording. */
2236: if ((map->num_sets < MAX_RECOG_OPERANDS)
2237: && (CONSTANT_P (src)
2238: || (GET_CODE (src) == PLUS
2239: && GET_CODE (XEXP (src, 0)) == REG
2240: && REGNO (XEXP (src, 0)) >= FIRST_VIRTUAL_REGISTER
2241: && REGNO (XEXP (src, 0)) <= LAST_VIRTUAL_REGISTER
2242: && CONSTANT_P (XEXP (src, 1)))
2243: || GET_CODE (src) == COMPARE
2244: #ifdef HAVE_cc0
2245: || dest == cc0_rtx
2246: #endif
2247: || (dest == pc_rtx
2248: && (src == pc_rtx || GET_CODE (src) == RETURN
2249: || GET_CODE (src) == LABEL_REF))))
2250: {
2251: /* Normally, this copy won't do anything. But, if SRC is a COMPARE
2252: it will cause us to save the COMPARE with any constants
2253: substituted, which is what we want for later. */
2254: map->equiv_sets[map->num_sets].equiv = copy_rtx (src);
2255: map->equiv_sets[map->num_sets++].dest = dest;
2256: }
2257:
2258: return;
2259: }
2260: }
2261:
2262: format_ptr = GET_RTX_FORMAT (code);
2263:
2264: /* If the first operand is an expression, save its mode for later. */
2265: if (*format_ptr == 'e')
2266: op0_mode = GET_MODE (XEXP (x, 0));
2267:
2268: for (i = 0; i < GET_RTX_LENGTH (code); i++)
2269: {
2270: switch (*format_ptr++)
2271: {
2272: case '0':
2273: break;
2274:
2275: case 'e':
2276: if (XEXP (x, i))
2277: subst_constants (&XEXP (x, i), insn, map);
2278: break;
2279:
2280: case 'u':
2281: case 'i':
2282: case 's':
2283: break;
2284:
2285: case 'E':
2286: if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
2287: {
2288: int j;
2289: for (j = 0; j < XVECLEN (x, i); j++)
2290: subst_constants (&XVECEXP (x, i, j), insn, map);
2291: }
2292: break;
2293:
2294: default:
2295: abort ();
2296: }
2297: }
2298:
2299: /* If this is a commutative operation, move a constant to the second
2300: operand unless the second operand is already a CONST_INT. */
2301: if ((GET_RTX_CLASS (code) == 'c' || code == NE || code == EQ)
2302: && CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
2303: {
2304: rtx tem = XEXP (x, 0);
2305: validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
2306: validate_change (insn, &XEXP (x, 1), tem, 1);
2307: }
2308:
2309: /* Simplify the expression in case we put in some constants. */
2310: switch (GET_RTX_CLASS (code))
2311: {
2312: case '1':
2313: new = simplify_unary_operation (code, GET_MODE (x),
2314: XEXP (x, 0), op0_mode);
2315: break;
2316:
2317: case '<':
2318: {
2319: enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
2320: if (op_mode == VOIDmode)
2321: op_mode = GET_MODE (XEXP (x, 1));
2322: new = simplify_relational_operation (code, op_mode,
2323: XEXP (x, 0), XEXP (x, 1));
2324: break;
2325: }
2326:
2327: case '2':
2328: case 'c':
2329: new = simplify_binary_operation (code, GET_MODE (x),
2330: XEXP (x, 0), XEXP (x, 1));
2331: break;
2332:
2333: case 'b':
2334: case '3':
2335: new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
2336: XEXP (x, 0), XEXP (x, 1), XEXP (x, 2));
2337: break;
2338: }
2339:
2340: if (new)
2341: validate_change (insn, loc, new, 1);
2342: }
2343:
2344: /* Show that register modified no longer contain known constants. We are
2345: called from note_stores with parts of the new insn. */
2346:
2347: void
2348: mark_stores (dest, x)
2349: rtx dest;
2350: rtx x;
2351: {
2352: if (GET_CODE (dest) == SUBREG)
2353: dest = SUBREG_REG (dest);
2354:
2355: if (GET_CODE (dest) == REG)
2356: global_const_equiv_map[REGNO (dest)] = 0;
2357: }
2358:
2359: /* If any CONST expressions with RTX_INTEGRATED_P are present in the rtx
2360: pointed to by PX, they represent constants in the constant pool.
2361: Replace these with a new memory reference obtained from force_const_mem.
2362: Similarly, ADDRESS expressions with RTX_INTEGRATED_P represent the
2363: address of a constant pool entry. Replace them with the address of
2364: a new constant pool entry obtained from force_const_mem. */
2365:
2366: static void
2367: restore_constants (px)
2368: rtx *px;
2369: {
2370: rtx x = *px;
2371: int i, j;
2372: char *fmt;
2373:
2374: if (x == 0)
2375: return;
2376:
2377: if (GET_CODE (x) == CONST_DOUBLE)
2378: {
2379: /* We have to make a new CONST_DOUBLE to ensure that we account for
2380: it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
2381: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2382: {
2383: REAL_VALUE_TYPE d;
2384:
2385: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
2386: *px = immed_real_const_1 (d, GET_MODE (x));
2387: }
2388: else
2389: *px = immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
2390: VOIDmode);
2391: }
2392:
2393: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == CONST)
2394: {
2395: restore_constants (&XEXP (x, 0));
2396: *px = validize_mem (force_const_mem (GET_MODE (x), XEXP (x, 0)));
2397: }
2398: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == SUBREG)
2399: {
2400: /* This must be (subreg/i:M1 (const/i:M2 ...) 0). */
2401: rtx new = XEXP (SUBREG_REG (x), 0);
2402:
2403: restore_constants (&new);
2404: new = force_const_mem (GET_MODE (SUBREG_REG (x)), new);
2405: PUT_MODE (new, GET_MODE (x));
2406: *px = validize_mem (new);
2407: }
2408: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == ADDRESS)
2409: {
2410: restore_constants (&XEXP (x, 0));
2411: *px = XEXP (force_const_mem (GET_MODE (x), XEXP (x, 0)), 0);
2412: }
2413: else
2414: {
2415: fmt = GET_RTX_FORMAT (GET_CODE (x));
2416: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
2417: {
2418: switch (*fmt++)
2419: {
2420: case 'E':
2421: for (j = 0; j < XVECLEN (x, i); j++)
2422: restore_constants (&XVECEXP (x, i, j));
2423: break;
2424:
2425: case 'e':
2426: restore_constants (&XEXP (x, i));
2427: break;
2428: }
2429: }
2430: }
2431: }
2432:
2433: /* Output the assembly language code for the function FNDECL
2434: from its DECL_SAVED_INSNS. Used for inline functions that are output
2435: at end of compilation instead of where they came in the source. */
2436:
2437: void
2438: output_inline_function (fndecl)
2439: tree fndecl;
2440: {
2441: rtx head = DECL_SAVED_INSNS (fndecl);
2442: rtx last;
2443:
2444: temporary_allocation ();
2445:
2446: current_function_decl = fndecl;
2447:
2448: /* This call is only used to initialize global variables. */
2449: init_function_start (fndecl, "lossage", 1);
2450:
2451: /* Redo parameter determinations in case the FUNCTION_...
2452: macros took machine-specific actions that need to be redone. */
2453: assign_parms (fndecl, 1);
2454:
2455: /* Set stack frame size. */
2456: assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl), 0);
2457:
2458: restore_reg_data (FIRST_PARM_INSN (head));
2459:
2460: stack_slot_list = STACK_SLOT_LIST (head);
2461:
2462: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_ALLOCA)
2463: current_function_calls_alloca = 1;
2464:
2465: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_SETJMP)
2466: current_function_calls_setjmp = 1;
2467:
2468: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_LONGJMP)
2469: current_function_calls_longjmp = 1;
2470:
2471: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_STRUCT)
2472: current_function_returns_struct = 1;
2473:
2474: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_PCC_STRUCT)
2475: current_function_returns_pcc_struct = 1;
2476:
2477: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_NEEDS_CONTEXT)
2478: current_function_needs_context = 1;
2479:
2480: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
2481: current_function_has_nonlocal_label = 1;
2482:
2483: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_POINTER)
2484: current_function_returns_pointer = 1;
2485:
2486: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_CONST_POOL)
2487: current_function_uses_const_pool = 1;
2488:
2489: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
2490: current_function_uses_pic_offset_table = 1;
2491:
2492: current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (head);
2493: current_function_pops_args = POPS_ARGS (head);
2494:
2495: /* There is no need to output a return label again. */
2496: return_label = 0;
2497:
2498: expand_function_end (DECL_SOURCE_FILE (fndecl), DECL_SOURCE_LINE (fndecl));
2499:
2500: /* Find last insn and rebuild the constant pool. */
2501: for (last = FIRST_PARM_INSN (head);
2502: NEXT_INSN (last); last = NEXT_INSN (last))
2503: {
2504: if (GET_RTX_CLASS (GET_CODE (last)) == 'i')
2505: {
2506: restore_constants (&PATTERN (last));
2507: restore_constants (®_NOTES (last));
2508: }
2509: }
2510:
2511: set_new_first_and_last_insn (FIRST_PARM_INSN (head), last);
2512: set_new_first_and_last_label_num (FIRST_LABELNO (head), LAST_LABELNO (head));
2513:
2514: /* Compile this function all the way down to assembly code. */
2515: rest_of_compilation (fndecl);
2516:
2517: current_function_decl = 0;
2518:
2519: permanent_allocation ();
2520: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.