|
|
1.1 root 1: /* Emit RTL for the GNU C-Compiler expander.
2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* Middle-to-low level generation of rtx code and insns.
23:
24: This file contains the functions `gen_rtx', `gen_reg_rtx'
25: and `gen_label_rtx' that are the usual ways of creating rtl
26: expressions for most purposes.
27:
28: It also has the functions for creating insns and linking
29: them in the doubly-linked chain.
30:
31: The patterns of the insns are created by machine-dependent
32: routines in insn-emit.c, which is generated automatically from
33: the machine description. These routines use `gen_rtx' to make
34: the individual rtx's of the pattern; what is machine dependent
35: is the kind of rtx's they make and what arguments they use. */
36:
37: #include "config.h"
38: #include <stdio.h>
39: #include "varargs.h"
40: #include "rtl.h"
41: #include "regs.h"
42: #include "insn-config.h"
43:
44: #define max(A,B) ((A) > (B) ? (A) : (B))
45: #define min(A,B) ((A) < (B) ? (A) : (B))
46:
47: /* This is reset to FIRST_PSEUDO_REGISTER at the start each function.
48: After rtl generation, it is 1 plus the largest register number used. */
49:
50: int reg_rtx_no = FIRST_PSEUDO_REGISTER;
51:
52: /* This is *not* reset after each function. It gives each CODE_LABEL
53: in the entire compilation a unique label number. */
54:
55: static int label_num = 1;
56:
57: /* Value of `label_num' at start of current function. */
58:
59: static int first_label_num;
60:
61: /* Nonzero means do not generate NOTEs for source line numbers. */
62:
63: static int no_line_numbers;
64:
65: /* Commonly used rtx's, so that we only need space for one copy.
66: These are initialized once for the entire compilation.
67: All of these except perhaps fconst0_rtx and dconst0_rtx
68: are unique; no other rtx-object will be equal to any of these. */
69:
70: rtx pc_rtx; /* (PC) */
71: rtx cc0_rtx; /* (CC0) */
72: rtx cc1_rtx; /* (CC1) (not actually used nowadays) */
73: rtx const0_rtx; /* (CONST_INT 0) */
74: rtx const1_rtx; /* (CONST_INT 1) */
75: rtx fconst0_rtx; /* (CONST_DOUBLE:SF 0) */
76: rtx dconst0_rtx; /* (CONST_DOUBLE:DF 0) */
77:
78: /* All references to the following fixed hard registers go through
79: these unique rtl objects. On machines where the frame-pointer and
80: arg-pointer are the same register, they use the same unique object.
81:
82: After register allocation, other rtl objects which used to be pseudo-regs
83: may be clobbered to refer to the frame-pointer register.
84: But references that were originally to the frame-pointer can be
85: distinguished from the others because they contain frame_pointer_rtx.
86:
87: In an inline procedure, the stack and frame pointer rtxs may not be
88: used for anything else. */
89: rtx stack_pointer_rtx; /* (REG:Pmode STACK_POINTER_REGNUM) */
90: rtx frame_pointer_rtx; /* (REG:Pmode FRAME_POINTER_REGNUM) */
91: rtx arg_pointer_rtx; /* (REG:Pmode ARG_POINTER_REGNUM) */
92: rtx struct_value_rtx; /* (REG:Pmode STRUCT_VALUE_REGNUM) */
93: rtx struct_value_incoming_rtx; /* (REG:Pmode STRUCT_VALUE_INCOMING_REGNUM) */
94: rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */
95: rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
96:
97: /* The ends of the doubly-linked chain of rtl for the current function.
98: Both are reset to null at the start of rtl generation for the function. */
99:
100: static rtx first_insn = NULL;
101: static rtx last_insn = NULL;
102:
103: /* The ends of a similar chain of rtl insns to become part
104: of the SEQUENCE returned by a gen_... function (in insn-emit.c).
105: This allows define_expand to use subroutines that call emit_insn. */
106: static rtx sequence_first_insn = NULL;
107: static rtx sequence_last_insn = NULL;
108:
109: /* Nonzero if emit_insn should add to the sequence_first_insn chain
110: instead of the ordinary chain. */
111: int emit_to_sequence;
112:
113: /* First insn used for something other than copying parms or changing their modes. */
114: static rtx first_noninit_insn = NULL;
115:
116: /* INSN_UID for next insn emitted.
117: Reset to 1 for each function compiled. */
118:
119: static int cur_insn_uid = 1;
120:
121: /* Line number and source file of the last line-number NOTE emitted.
122: This is used to avoid generating duplicates. */
123:
124: static int last_linenum = 0;
125: static char *last_filename = 0;
126:
127: /* A vector indexed by pseudo reg number. The allocated length
128: of this vector is regno_pointer_flag_length. Since this
129: vector is needed during the expansion phase when the total
130: number of registers in the function is not yet known,
131: it is copied and made bigger when necessary. */
132:
133: char *regno_pointer_flag;
134: int regno_pointer_flag_length;
135:
136: /* Indexed by pseudo register number, gives the rtx for that pseudo.
137: Allocated in parallel with regno_pointer_flag. */
138:
139: rtx *regno_reg_rtx;
140:
141: /* Chain of all CONST_DOUBLEs made for this function;
142: so we can uniquize them. */
143:
144: rtx real_constant_chain;
145:
146: /* rtx gen_rtx (code, mode, [element1, ..., elementn])
147: **
148: ** This routine generates an RTX of the size specified by
149: ** <code>, which is an RTX code. The RTX structure is initialized
150: ** from the arguments <element1> through <elementn>, which are
151: ** interpreted according to the specific RTX type's format. The
152: ** special machine mode associated with the rtx (if any) is specified
153: ** in <mode>.
154: **
155: ** gen_rtx() can be invoked in a way which resembles the lisp-like
156: ** rtx it will generate. For example, the following rtx structure:
157: **
158: ** (plus:QI (mem:QI (reg:SI 1))
159: ** (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3))))
160: **
161: ** ...would be generated by the following C code:
162: **
163: ** gen_rtx (PLUS, QImode,
164: ** gen_rtx (MEM, QImode,
165: ** gen_rtx (REG, SImode, 1)),
166: ** gen_rtx (MEM, QImode,
167: ** gen_rtx (PLUS, SImode,
168: ** gen_rtx (REG, SImode, 2),
169: ** gen_rtx (REG, SImode, 3)))),
170: */
171:
172: /*VARARGS2*/
173: rtx
174: gen_rtx (va_alist)
175: va_dcl
176: {
177: va_list p;
178: enum rtx_code code;
179: enum machine_mode mode;
180: register char *argp; /* Pointer to arguments... */
181: register int i; /* Array indices... */
182: register char *fmt; /* Current rtx's format... */
183: register rtx rt_val; /* RTX to return to caller... */
184:
185: va_start (p);
186: code = va_arg (p, enum rtx_code);
187: mode = va_arg (p, enum machine_mode);
188:
189: if (code == CONST_INT)
190: {
191: int arg = va_arg (p, int);
192: if (arg == 0)
193: return const0_rtx;
194: if (arg == 1)
195: return const1_rtx;
196: rt_val = rtx_alloc (code);
197: INTVAL (rt_val) = arg;
198: }
199: else if (code == CONST_DOUBLE)
200: {
201: int arg0 = va_arg (p, int);
202: int arg1 = va_arg (p, int);
203: if (arg0 == XINT (fconst0_rtx, 0)
204: && arg1 == XINT (fconst0_rtx, 1))
205: return (mode == DFmode ? dconst0_rtx : fconst0_rtx);
206: rt_val = rtx_alloc (code);
207: rt_val->mode = mode;
208: XINT (rt_val, 0) = arg0;
209: XINT (rt_val, 1) = arg1;
210: }
211: else
212: {
213: rt_val = rtx_alloc (code); /* Allocate the storage space. */
214: rt_val->mode = mode; /* Store the machine mode... */
215:
216: fmt = GET_RTX_FORMAT (code); /* Find the right format... */
217: for (i = 0; i < GET_RTX_LENGTH (code); i++)
218: {
219: switch (*fmt++)
220: {
221: case '0': /* Unused field. */
222: break;
223:
224: case 'i': /* An integer? */
225: XINT (rt_val, i) = va_arg (p, int);
226: break;
227:
228: case 's': /* A string? */
229: XSTR (rt_val, i) = va_arg (p, char *);
230: break;
231:
232: case 'e': /* An expression? */
233: case 'u': /* An insn? Same except when printing. */
234: XEXP (rt_val, i) = va_arg (p, rtx);
235: break;
236:
237: case 'E': /* An RTX vector? */
238: XVEC (rt_val, i) = va_arg (p, rtvec);
239: break;
240:
241: default:
242: abort();
243: }
244: }
245: }
246: va_end (p);
247: return rt_val; /* Return the new RTX... */
248: }
249:
250: /* gen_rtvec (n, [rt1, ..., rtn])
251: **
252: ** This routine creates an rtvec and stores within it the
253: ** pointers to rtx's which are its arguments.
254: */
255:
256: /*VARARGS1*/
257: rtvec
258: gen_rtvec (va_alist)
259: va_dcl
260: {
261: int n, i;
262: rtx first;
263: va_list p;
264: rtx *vector;
265:
266: va_start (p);
267: n = va_arg (p, int);
268:
269: if (n == 0)
270: return NULL_RTVEC; /* Don't allocate an empty rtvec... */
271:
272: vector = (rtx *) alloca (n * sizeof (rtx));
273: for (i = 0; i < n; i++)
274: vector[i] = va_arg (p, rtx);
275: va_end (p);
276:
277: return gen_rtvec_v (n, vector);
278: }
279:
280: rtvec
281: gen_rtvec_v (n, argp)
282: int n;
283: rtx *argp;
284: {
285: register int i;
286: register rtvec rt_val;
287:
288: if (n == 0)
289: return NULL_RTVEC; /* Don't allocate an empty rtvec... */
290:
291: rt_val = rtvec_alloc (n); /* Allocate an rtvec... */
292:
293: for (i = 0; i < n; i++)
294: rt_val->elem[i].rtx = *argp++;
295:
296: return rt_val;
297: }
298:
299: /* Generate a REG rtx for a new pseudo register of mode MODE.
300: This pseudo is assigned the next sequential register number. */
301:
302: rtx
303: gen_reg_rtx (mode)
304: enum machine_mode mode;
305: {
306: register rtx val;
307:
308: /* Make sure regno_pointer_flag and regno_reg_rtx are large
309: enough to have an element for this pseudo reg number. */
310:
311: if (reg_rtx_no == regno_pointer_flag_length)
312: {
313: rtx *new1;
314: char *new =
315: (char *) oballoc (regno_pointer_flag_length * 2);
316: bzero (new, regno_pointer_flag_length * 2);
317: bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
318: regno_pointer_flag = new;
319:
320: new1 = (rtx *) oballoc (regno_pointer_flag_length * 2 * sizeof (rtx));
321: bzero (new1, regno_pointer_flag_length * 2 * sizeof (rtx));
322: bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx));
323: regno_reg_rtx = new1;
324:
325: regno_pointer_flag_length *= 2;
326: }
327:
328: val = gen_rtx (REG, mode, reg_rtx_no);
329: regno_reg_rtx[reg_rtx_no++] = val;
330: return val;
331: }
332:
333: /* Identify REG as a probable pointer register. */
334:
335: void
336: mark_reg_pointer (reg)
337: rtx reg;
338: {
339: REGNO_POINTER_FLAG (REGNO (reg)) = 1;
340: }
341:
342: /* Return 1 plus largest pseudo reg number used in the current function. */
343:
344: int
345: max_reg_num ()
346: {
347: return reg_rtx_no;
348: }
349:
350: /* Return 1 + the largest label number used so far. */
351:
352: int
353: max_label_num ()
354: {
355: return label_num;
356: }
357:
358: /* Return first label number used in this function (if any were used). */
359:
360: int
361: get_first_label_num ()
362: {
363: return first_label_num;
364: }
365:
366: /* Assuming that X is an rtx (MEM, REG or SUBREG) for a fixed-point number,
367: return a MEM or SUBREG rtx that refers to the least-significant part of X.
368: MODE specifies how big a part of X to return;
369: it must not be larger than a word.
370: If X is a MEM whose address is a QUEUED, the value may be so also. */
371:
372: rtx
373: gen_lowpart (mode, x)
374: enum machine_mode mode;
375: register rtx x;
376: {
377: /* This case loses if X is a subreg. To catch bugs early,
378: complain if an invalid MODE is used even in other cases. */
379: if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
380: abort ();
381: if (GET_CODE (x) == SUBREG)
382: return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
383: ? SUBREG_REG (x)
384: : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x)));
385: if (GET_MODE (x) == mode)
386: return x;
387: if (GET_CODE (x) == CONST_INT)
388: return gen_rtx (CONST_INT, VOIDmode, INTVAL (x) & GET_MODE_MASK (mode));
389: if (GET_CODE (x) == MEM)
390: {
391: register int offset = 0;
392: #ifdef WORDS_BIG_ENDIAN
393: offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
394: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD));
395: #endif
396: #ifdef BYTES_BIG_ENDIAN
397: /* Adjust the address so that the address-after-the-data
398: is unchanged. */
399: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (mode))
400: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
401: #endif
402: return gen_rtx (MEM, mode,
403: memory_address (mode,
404: plus_constant (XEXP (x, 0), offset)));
405: }
406: else if (GET_CODE (x) == REG)
407: {
408: #ifdef WORDS_BIG_ENDIAN
409: if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
410: {
411: return gen_rtx (SUBREG, mode, x,
412: ((GET_MODE_SIZE (GET_MODE (x))
413: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD))
414: / UNITS_PER_WORD));
415: }
416: #endif
417: return gen_rtx (SUBREG, mode, x, 0);
418: }
419: else
420: abort ();
421: }
422:
423: /* Like `gen_lowpart', but refer to the most significant part. */
424:
425: rtx
426: gen_highpart (mode, x)
427: enum machine_mode mode;
428: register rtx x;
429: {
430: if (GET_CODE (x) == MEM)
431: {
432: register int offset = 0;
433: #ifndef WORDS_BIG_ENDIAN
434: offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
435: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD));
436: #endif
437: #ifndef BYTES_BIG_ENDIAN
438: if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
439: offset -= (GET_MODE_SIZE (mode)
440: - min (UNITS_PER_WORD,
441: GET_MODE_SIZE (GET_MODE (x))));
442: #endif
443: return gen_rtx (MEM, mode,
444: memory_address (mode,
445: plus_constant (XEXP (x, 0), offset)));
446: }
447: else if (GET_CODE (x) == REG)
448: {
449: #ifndef WORDS_BIG_ENDIAN
450: if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
451: {
452: return gen_rtx (SUBREG, mode, x,
453: ((GET_MODE_SIZE (GET_MODE (x))
454: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD))
455: / UNITS_PER_WORD));
456: }
457: #endif
458: return gen_rtx (SUBREG, mode, x, 0);
459: }
460: else
461: abort ();
462: }
463:
464: /* Return 1 iff X, assumed to be a SUBREG,
465: refers to the least significant part of its containing reg.
466: If X is not a SUBREG, always return 1 (it is its own low part!). */
467:
468: int
469: subreg_lowpart_p (x)
470: rtx x;
471: {
472: if (GET_CODE (x) != SUBREG)
473: return 1;
474: #ifdef WORDS_BIG_ENDIAN
475: if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
476: {
477: register enum machine_mode mode = GET_MODE (SUBREG_REG (x));
478: return (SUBREG_WORD (x)
479: == ((GET_MODE_SIZE (GET_MODE (x))
480: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD))
481: / UNITS_PER_WORD));
482: }
483: #endif
484: return SUBREG_WORD (x) == 0;
485: }
486:
487: /* Return a memory reference like MEMREF, but with its mode changed
488: to MODE and its address changed to ADDR.
489: (VOIDmode means don't change the mode.
490: NULL for ADDR means don't change the address.) */
491:
492: rtx
493: change_address (memref, mode, addr)
494: rtx memref;
495: enum machine_mode mode;
496: rtx addr;
497: {
498: rtx new;
499:
500: if (mode == VOIDmode)
501: mode = GET_MODE (memref);
502: if (addr == 0)
503: addr = XEXP (memref, 0);
504:
505: new = gen_rtx (MEM, mode, memory_address (mode, addr));
506: new->volatil = memref->volatil;
507: new->unchanging = memref->unchanging;
508: new->in_struct = memref->in_struct;
509: return new;
510: }
511:
512: /* Return a newly created CODE_LABEL rtx with a unique label number. */
513:
514: rtx
515: gen_label_rtx ()
516: {
517: register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, label_num++);
518: LABEL_NUSES (label) = 0;
519: return label;
520: }
521:
522: /* For procedure integration. */
523:
524: /* Return a newly created INLINE_HEADER rtx. Should allocate this
525: from a permanent obstack when the opportunity arises. */
526:
527: rtx
528: gen_inline_header_rtx (insn, last_insn,
529: first_labelno, last_labelno,
530: max_parm_regnum, max_regnum, args_size)
531: rtx insn, last_insn;
532: int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;
533: {
534: rtx header = gen_rtx (INLINE_HEADER, VOIDmode,
535: cur_insn_uid++, NULL,
536: insn, last_insn,
537: first_labelno, last_labelno,
538: max_parm_regnum, max_regnum, args_size);
539: return header;
540: }
541:
542: /* Install new pointers to the first and last insns in the chain.
543: Used for an inline-procedure after copying the insn chain. */
544:
545: void
546: set_new_first_and_last_insn (first, last)
547: rtx first, last;
548: {
549: first_insn = first;
550: last_insn = last;
551: }
552:
553: /* Go through all the RTL insn bodies and copy any invalid shared structure.
554: It does not work to do this twice, because the mark bits set here
555: are not cleared afterwards. */
556:
557: static int unshare_copies = 0; /* Count rtx's that were copied. */
558:
559: static rtx copy_rtx_if_shared ();
560:
561: void
562: unshare_all_rtl (insn)
563: register rtx insn;
564: {
565: for (; insn; insn = NEXT_INSN (insn))
566: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
567: || GET_CODE (insn) == CALL_INSN)
568: {
569: rtx tail;
570: PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
571: /* Copy the contents of the reg-notes */
572: for (tail = REG_NOTES (insn); tail; tail = XEXP (tail, 1))
573: /* But if contents are an insn, don't copy that. */
574: if (GET_CODE (tail) == EXPR_LIST)
575: XEXP (tail, 0) = copy_rtx_if_shared (XEXP (tail, 0));
576: }
577: }
578:
579: /* Mark ORIG as in use, and return a copy of it if it was already in use.
580: Recursively does the same for subexpressions. */
581:
582: static rtx
583: copy_rtx_if_shared (orig)
584: rtx orig;
585: {
586: register rtx x = orig;
587: register int i;
588: register enum rtx_code code;
589: register char *format_ptr;
590: int copied = 0;
591:
592: code = GET_CODE (x);
593:
594: /* These types may be freely shared. */
595:
596: switch (code)
597: {
598: case REG:
599: case QUEUED:
600: case CONST_INT:
601: case CONST_DOUBLE:
602: case SYMBOL_REF:
603: case CODE_LABEL:
604: case PC:
605: case CC0:
606: return x;
607:
608: case MEM:
609: /* A MEM is allowed to be shared if its address is constant
610: or is a constant plus one of the special registers. */
611: if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
612: return x;
613: if (GET_CODE (XEXP (x, 0)) == PLUS
614: && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
615: && (REGNO (XEXP (XEXP (x, 0), 0)) == FRAME_POINTER_REGNUM
616: || REGNO (XEXP (XEXP (x, 0), 0)) == ARG_POINTER_REGNUM)
617: && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
618: if (GET_CODE (XEXP (x, 0)) == REG
619: && (REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM
620: || REGNO (XEXP (x, 0)) == ARG_POINTER_REGNUM)
621: && CONSTANT_ADDRESS_P (XEXP (x, 1)))
622: return x;
623: }
624:
625: /* This rtx may not be shared. If it has already been seen,
626: replace it with a copy of itself. */
627:
628: if (x->used)
629: {
630: register rtx copy;
631:
632: unshare_copies++;
633:
634: copy = rtx_alloc (code);
635: bcopy (x, copy, sizeof (int) * (GET_RTX_LENGTH (code) + 1));
636: x = copy;
637: copied = 1;
638: }
639: x->used = 1;
640:
641: /* Now scan the subexpressions recursively.
642: We can store any replaced subexpressions directly into X
643: since we know X is not shared! Any vectors in X
644: must be copied if X was copied. */
645:
646: format_ptr = GET_RTX_FORMAT (code);
647:
648: for (i = 0; i < GET_RTX_LENGTH (code); i++)
649: {
650: switch (*format_ptr++)
651: {
652: case 'e':
653: XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i));
654: break;
655:
656: case 'E':
657: if (XVEC (x, i) != NULL)
658: {
659: register int j;
660:
661: if (copied)
662: XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
663: for (j = 0; j < XVECLEN (x, i); j++)
664: XVECEXP (x, i, j)
665: = copy_rtx_if_shared (XVECEXP (x, i, j));
666: }
667: break;
668: }
669: }
670: return x;
671: }
672:
673: /* Copy X if necessary so that it won't be altered by changes in OTHER.
674: Return X or the rtx for the pseudo reg the value of X was copied into.
675: OTHER must be valid as a SET_DEST. */
676:
677: rtx
678: make_safe_from (x, other)
679: rtx x, other;
680: {
681: rtx out = other;
682: while (1)
683: switch (GET_CODE (other))
684: {
685: case SUBREG:
686: other = SUBREG_REG (other);
687: break;
688: case STRICT_LOW_PART:
689: case SIGN_EXTEND:
690: case ZERO_EXTEND:
691: other = XEXP (other, 0);
692: break;
693: default:
694: goto done;
695: }
696: done:
697: if ((GET_CODE (other) == MEM
698: && ! CONSTANT_P (x)
699: && GET_CODE (x) != CONST_DOUBLE
700: && GET_CODE (x) != REG)
701: || (GET_CODE (other) == REG
702: && (REGNO (other) < FIRST_PSEUDO_REGISTER
703: || reg_mentioned_p (other, x))))
704: {
705: rtx temp = gen_reg_rtx (GET_MODE (x));
706: emit_move_insn (temp, x);
707: return temp;
708: }
709: return x;
710: }
711:
712: /* Emission of insns (adding them to the doubly-linked list). */
713:
714: /* Return the first insn of the current function. */
715:
716: rtx
717: get_insns ()
718: {
719: return first_insn;
720: }
721:
722: /* Return the last insn of the current function. */
723:
724: rtx
725: get_last_insn ()
726: {
727: return last_insn;
728: }
729:
730: /* Return a number larger than any instruction's uid in this function. */
731:
732: int
733: get_max_uid ()
734: {
735: return cur_insn_uid;
736: }
737:
738: /* Make and return an INSN rtx, initializing all its slots.
739: Store PATTERN in the pattern slots.
740: PAT_FORMALS is an idea that never really went anywhere. */
741:
742: static rtx
743: make_insn_raw (pattern, pat_formals)
744: rtx pattern;
745: rtvec pat_formals;
746: {
747: register rtx insn;
748:
749: insn = rtx_alloc(INSN);
750: INSN_UID(insn) = cur_insn_uid++;
751:
752: PATTERN (insn) = pattern;
753: INSN_CODE (insn) = -1;
754: LOG_LINKS(insn) = NULL;
755: REG_NOTES(insn) = NULL;
756:
757: return insn;
758: }
759:
760: /* Like `make_insn' but make a JUMP_INSN instead of an insn. */
761:
762: static rtx
763: make_jump_insn_raw (pattern, pat_formals)
764: rtx pattern;
765: rtvec pat_formals;
766: {
767: register rtx insn;
768:
769: insn = rtx_alloc(JUMP_INSN);
770: INSN_UID(insn) = cur_insn_uid++;
771:
772: PATTERN (insn) = pattern;
773: INSN_CODE (insn) = -1;
774: LOG_LINKS(insn) = NULL;
775: REG_NOTES(insn) = NULL;
776: JUMP_LABEL(insn) = NULL;
777:
778: return insn;
779: }
780:
781: /* Add INSN to the end of the doubly-linked list.
782: INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */
783:
784: static void
785: add_insn (insn)
786: register rtx insn;
787: {
788: if (emit_to_sequence)
789: {
790: PREV_INSN (insn) = sequence_last_insn;
791: NEXT_INSN (insn) = 0;
792:
793: if (NULL != sequence_last_insn)
794: NEXT_INSN (sequence_last_insn) = insn;
795:
796: if (NULL == sequence_first_insn)
797: sequence_first_insn = insn;
798:
799: sequence_last_insn = insn;
800: }
801: else
802: {
803: PREV_INSN (insn) = last_insn;
804: NEXT_INSN (insn) = 0;
805:
806: if (NULL != last_insn)
807: NEXT_INSN (last_insn) = insn;
808:
809: if (NULL == first_insn)
810: first_insn = insn;
811:
812: last_insn = insn;
813: }
814: }
815:
816: /* Add INSN, an rtx of code INSN, into the doubly-linked list
817: after insn AFTER. */
818:
819: static void
820: add_insn_after (insn, after)
821: rtx insn, after;
822: {
823: NEXT_INSN (insn) = NEXT_INSN (after);
824: PREV_INSN (insn) = after;
825:
826: if (NEXT_INSN (insn))
827: PREV_INSN (NEXT_INSN (insn)) = insn;
828: else
829: last_insn = insn;
830: NEXT_INSN (after) = insn;
831: }
832:
833: /* Delete all insns made since FROM.
834: FROM becomes the new last instruction. */
835:
836: void
837: delete_insns_since (from)
838: rtx from;
839: {
840: NEXT_INSN (from) = 0;
841: last_insn = from;
842: }
843:
844: /* Move a consecutive bunch of insns to a different place in the chain.
845: The insns to be moved are those between FROM and TO.
846: They are moved to a new position after the insn AFTER. */
847:
848: void
849: reorder_insns (from, to, after)
850: rtx from, to, after;
851: {
852: /* Splice this bunch out of where it is now. */
853: if (PREV_INSN (from))
854: NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
855: if (NEXT_INSN (to))
856: PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
857: if (last_insn == to)
858: last_insn = PREV_INSN (from);
859: if (first_insn == from)
860: first_insn = NEXT_INSN (to);
861:
862: /* Make the new neighbors point to it and it to them. */
863: if (NEXT_INSN (after))
864: {
865: PREV_INSN (NEXT_INSN (after)) = to;
866: NEXT_INSN (to) = NEXT_INSN (after);
867: }
868: PREV_INSN (from) = after;
869: NEXT_INSN (after) = from;
870: if (after == last_insn)
871: last_insn = to;
872: }
873:
874: /* Emit an insn of given code and pattern
875: at a specified place within the doubly-linked list. */
876:
877: /* Make an instruction with body PATTERN
878: and output it before the instruction BEFORE. */
879:
880: rtx
881: emit_insn_before (pattern, before)
882: register rtx pattern, before;
883: {
884: register rtx insn;
885:
886: if (GET_CODE (pattern) == SEQUENCE)
887: {
888: register int i;
889: /* For an empty sequence, emit nothing. */
890: if (XVEC (pattern, 0))
891: for (i = 0; i < XVECLEN (pattern, 0); i++)
892: add_insn_after (XVECEXP (pattern, 0, i), PREV_INSN (before));
893: return PREV_INSN (before);
894: }
895:
896: insn = make_insn_raw (pattern, 0);
897:
898: PREV_INSN (insn) = PREV_INSN (before);
899: NEXT_INSN (insn) = before;
900:
901: if (PREV_INSN (insn))
902: NEXT_INSN (PREV_INSN (insn)) = insn;
903: else
904: first_insn = insn;
905: PREV_INSN (before) = insn;
906:
907: return insn;
908: }
909:
910: /* Make an instruction with body PATTERN and code JUMP_INSN
911: and output it before the instruction BEFORE. */
912:
913: rtx
914: emit_jump_insn_before (pattern, before)
915: register rtx pattern, before;
916: {
917: register rtx insn = make_jump_insn_raw (pattern, 0);
918:
919: PREV_INSN (insn) = PREV_INSN (before);
920: NEXT_INSN (insn) = before;
921:
922: if (PREV_INSN (insn))
923: NEXT_INSN (PREV_INSN (insn)) = insn;
924: else
925: first_insn = insn;
926: PREV_INSN (before) = insn;
927:
928: return insn;
929: }
930:
931: /* Make an insn of code INSN with body PATTERN
932: and output it after the insn AFTER. */
933:
934: rtx
935: emit_insn_after (pattern, after)
936: register rtx pattern, after;
937: {
938: if (GET_CODE (pattern) == SEQUENCE)
939: {
940: register int i;
941: /* For an empty sequence, emit nothing. */
942: if (XVEC (pattern, 0))
943: for (i = 0; i < XVECLEN (pattern, 0); i++)
944: {
945: add_insn_after (XVECEXP (pattern, 0, i), after);
946: after = NEXT_INSN (after);
947: }
948: return after;
949: }
950: else
951: {
952: register rtx insn = make_insn_raw (pattern, 0);
953: add_insn_after (insn, after);
954: return insn;
955: }
956: }
957:
958: /* Make an insn of code JUMP_INSN with body PATTERN
959: and output it after the insn AFTER. */
960:
961: rtx
962: emit_jump_insn_after (pattern, after)
963: register rtx pattern, after;
964: {
965: register rtx insn = make_jump_insn_raw (pattern, 0);
966:
967: add_insn_after (insn, after);
968: return insn;
969: }
970:
971: /* Make an insn of code BARRIER
972: and output it after the insn AFTER. */
973:
974: rtx
975: emit_barrier_after (after)
976: register rtx after;
977: {
978: register rtx insn = rtx_alloc (BARRIER);
979:
980: INSN_UID (insn) = cur_insn_uid++;
981:
982: add_insn_after (insn, after);
983: return insn;
984: }
985:
986: /* Emit the label LABEL after the insn AFTER. */
987:
988: void
989: emit_label_after (label, after)
990: rtx label, after;
991: {
992: /* This can be called twice for the same label
993: as a result of the confusion that follows a syntax error!
994: So make it harmless. */
995: if (INSN_UID (label) == 0)
996: {
997: INSN_UID (label) = cur_insn_uid++;
998: add_insn_after (label, after);
999: }
1000: }
1001:
1002: /* Emit a note of subtype SUBTYPE after the insn AFTER. */
1003:
1004: void
1005: emit_note_after (subtype, after)
1006: int subtype;
1007: rtx after;
1008: {
1009: register rtx note = rtx_alloc (NOTE);
1010: INSN_UID (note) = cur_insn_uid++;
1011: XSTR (note, 3) = 0;
1012: XINT (note, 4) = subtype;
1013: add_insn_after (note, after);
1014: }
1015:
1016: /* Make an insn of code INSN with pattern PATTERN
1017: and add it to the end of the doubly-linked list.
1018: If PATTERN is a SEQUENCE, take the elements of it
1019: and emit an insn for each element.
1020:
1021: Returns the last insn emitted. */
1022:
1023: rtx
1024: emit_insn (pattern)
1025: rtx pattern;
1026: {
1027: rtx insn;
1028:
1029: if (GET_CODE (pattern) == SEQUENCE)
1030: {
1031: register int i;
1032: /* For an empty sequence, emit nothing. */
1033: if (XVEC (pattern, 0))
1034: for (i = 0; i < XVECLEN (pattern, 0); i++)
1035: add_insn (insn = XVECEXP (pattern, 0, i));
1036: }
1037: else
1038: {
1039: insn = make_insn_raw (pattern, NULL);
1040: add_insn (insn);
1041: }
1042: return insn;
1043: }
1044:
1045: /* Make an insn of code JUMP_INSN with pattern PATTERN
1046: and add it to the end of the doubly-linked list. */
1047:
1048: rtx
1049: emit_jump_insn (pattern)
1050: rtx pattern;
1051: {
1052: if (GET_CODE (pattern) == SEQUENCE)
1053: return emit_insn (pattern);
1054: else
1055: {
1056: register rtx insn = make_jump_insn_raw (pattern, NULL);
1057: add_insn (insn);
1058: return insn;
1059: }
1060: }
1061:
1062: /* Make an insn of code CALL_INSN with pattern PATTERN
1063: and add it to the end of the doubly-linked list. */
1064:
1065: rtx
1066: emit_call_insn (pattern)
1067: rtx pattern;
1068: {
1069: if (GET_CODE (pattern) == SEQUENCE)
1070: return emit_insn (pattern);
1071: else
1072: {
1073: register rtx insn = make_insn_raw (pattern, NULL);
1074: add_insn (insn);
1075: PUT_CODE (insn, CALL_INSN);
1076: return insn;
1077: }
1078: }
1079:
1080: /* Add the label LABEL to the end of the doubly-linked list. */
1081:
1082: void
1083: emit_label (label)
1084: rtx label;
1085: {
1086: /* This can be called twice for the same label
1087: as a result of the confusion that follows a syntax error!
1088: So make it harmless. */
1089: if (INSN_UID (label) == 0)
1090: {
1091: INSN_UID (label) = cur_insn_uid++;
1092: add_insn (label);
1093: }
1094: }
1095:
1096: /* Make an insn of code BARRIER
1097: and add it to the end of the doubly-linked list. */
1098:
1099: void
1100: emit_barrier ()
1101: {
1102: register rtx barrier = rtx_alloc (BARRIER);
1103: INSN_UID (barrier) = cur_insn_uid++;
1104: add_insn (barrier);
1105: }
1106:
1107: /* Make an insn of code NOTE
1108: with data-fields specified by FILE and LINE
1109: and add it to the end of the doubly-linked list. */
1110:
1111: rtx
1112: emit_note (file, line)
1113: char *file;
1114: int line;
1115: {
1116: register rtx note;
1117:
1118: if (no_line_numbers && line > 0)
1119: return 0;
1120:
1121: if (line > 0)
1122: {
1123: if (file && last_filename && !strcmp (file, last_filename)
1124: && line == last_linenum)
1125: return 0;
1126: last_filename = file;
1127: last_linenum = line;
1128: }
1129:
1130: note = rtx_alloc (NOTE);
1131: INSN_UID (note) = cur_insn_uid++;
1132: XSTR (note, 3) = file;
1133: XINT (note, 4) = line;
1134: add_insn (note);
1135: return note;
1136: }
1137:
1138: /* Return an indication of which type of insn should have X as a body.
1139: The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */
1140:
1141: enum rtx_code
1142: classify_insn (x)
1143: rtx x;
1144: {
1145: if (GET_CODE (x) == CODE_LABEL)
1146: return CODE_LABEL;
1147: if (GET_CODE (x) == CALL)
1148: return CALL_INSN;
1149: if (GET_CODE (x) == RETURN)
1150: return JUMP_INSN;
1151: if (GET_CODE (x) == SET)
1152: {
1153: if (SET_DEST (x) == pc_rtx)
1154: return JUMP_INSN;
1155: else if (GET_CODE (SET_SRC (x)) == CALL)
1156: return CALL_INSN;
1157: else
1158: return INSN;
1159: }
1160: if (GET_CODE (x) == PARALLEL)
1161: {
1162: register int j;
1163: for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
1164: if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
1165: return CALL_INSN;
1166: else if (GET_CODE (XVECEXP (x, 0, j)) == SET
1167: && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx)
1168: return JUMP_INSN;
1169: else if (GET_CODE (XVECEXP (x, 0, j)) == SET
1170: && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
1171: return CALL_INSN;
1172: }
1173: return INSN;
1174: }
1175:
1176: /* Emit the rtl pattern X as an appropriate kind of insn.
1177: If X is a label, it is simply added into the insn chain. */
1178:
1179: rtx
1180: emit (x)
1181: rtx x;
1182: {
1183: enum rtx_code code = classify_insn (x);
1184:
1185: if (code == CODE_LABEL)
1186: emit_label (x);
1187: else if (code == INSN)
1188: emit_insn (x);
1189: else if (code == JUMP_INSN)
1190: {
1191: emit_jump_insn (x);
1192: if (simplejump_p (x) || GET_CODE (x) == RETURN)
1193: emit_barrier ();
1194: }
1195: else if (code == CALL_INSN)
1196: emit_call_insn (x);
1197: }
1198:
1199: /* Generate a SEQUENCE rtx containing the insn-patterns in VEC
1200: following any insns previously placed on sequence_first_insn.
1201: This is how the gen_... function from a DEFINE_EXPAND
1202: constructs the SEQUENCE that it returns. */
1203:
1204: rtx
1205: gen_sequence ()
1206: {
1207: rtx tem;
1208: rtvec newvec;
1209: int i;
1210: int len;
1211:
1212: /* Count the insns in the chain. */
1213: len = 0;
1214: for (tem = sequence_first_insn; tem; tem = NEXT_INSN (tem))
1215: len++;
1216:
1217: /* For an empty sequence... */
1218: if (len == 0)
1219: return gen_rtx (SEQUENCE, VOIDmode, NULL);
1220:
1221: /* If only one insn, return its pattern rather than a SEQUENCE. */
1222: if (len == 1)
1223: {
1224: tem = PATTERN (sequence_first_insn);
1225: sequence_first_insn = 0;
1226: sequence_last_insn = 0;
1227: return tem;
1228: }
1229:
1230: /* Put them in a vector. */
1231: newvec = rtvec_alloc (len);
1232: i = 0;
1233: for (tem = sequence_first_insn; tem; tem = NEXT_INSN (tem), i++)
1234: newvec->elem[i].rtx = tem;
1235:
1236: /* Clear the chain and make a SEQUENCE from this vector. */
1237: sequence_first_insn = 0;
1238: sequence_last_insn = 0;
1239: return gen_rtx (SEQUENCE, VOIDmode, newvec);
1240: }
1241:
1242: /* Set up regno_reg_rtx, reg_rtx_no and regno_pointer_flag
1243: according to the chain of insns starting with FIRST.
1244:
1245: This is used when an inline function's rtl is saved
1246: and passed to rest_of_compilation later. */
1247:
1248: static void restore_reg_data_1 ();
1249:
1250: void
1251: restore_reg_data (first)
1252: rtx first;
1253: {
1254: rtx insn;
1255: int i;
1256:
1257: for (insn = first; insn; insn = NEXT_INSN (insn))
1258: {
1259: switch (GET_CODE (insn))
1260: {
1261: case NOTE:
1262: case CODE_LABEL:
1263: case BARRIER:
1264: break;
1265:
1266: case JUMP_INSN:
1267: case CALL_INSN:
1268: case INSN:
1269: restore_reg_data_1 (PATTERN (insn));
1270: break;
1271: }
1272: }
1273:
1274: /* If any regs are missing, make them up. */
1275: for (i = FIRST_PSEUDO_REGISTER; i < reg_rtx_no; i++)
1276: if (regno_reg_rtx[i] == 0)
1277: regno_reg_rtx[i] = gen_rtx (REG, SImode, i);
1278: }
1279:
1280: static void
1281: restore_reg_data_1 (orig)
1282: rtx orig;
1283: {
1284: register rtx x = orig;
1285: register int i;
1286: register enum rtx_code code;
1287: register char *format_ptr;
1288:
1289: code = GET_CODE (x);
1290:
1291: switch (code)
1292: {
1293: case QUEUED:
1294: case CONST_INT:
1295: case CONST_DOUBLE:
1296: case SYMBOL_REF:
1297: case CODE_LABEL:
1298: case PC:
1299: case CC0:
1300: case LABEL_REF:
1301: return;
1302:
1303: case REG:
1304: if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
1305: {
1306: /* Make sure regno_pointer_flag and regno_reg_rtx are large
1307: enough to have an element for this pseudo reg number. */
1308: if (REGNO (x) >= reg_rtx_no)
1309: {
1310: reg_rtx_no = REGNO (x);
1311:
1312: if (reg_rtx_no == regno_pointer_flag_length)
1313: {
1314: rtx *new1;
1315: char *new =
1316: (char *) oballoc (regno_pointer_flag_length * 2);
1317: bzero (new, regno_pointer_flag_length * 2);
1318: bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
1319: regno_pointer_flag = new;
1320:
1321: new1 = (rtx *) oballoc (regno_pointer_flag_length * 2 * sizeof (rtx));
1322: bzero (new1, regno_pointer_flag_length * 2 * sizeof (rtx));
1323: bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx));
1324: regno_reg_rtx = new1;
1325:
1326: regno_pointer_flag_length *= 2;
1327: }
1328: reg_rtx_no ++;
1329: }
1330: regno_reg_rtx[REGNO (x)] = x;
1331: }
1332: return;
1333:
1334: case MEM:
1335: restore_reg_data_1 (XEXP (x, 0));
1336: return;
1337: }
1338:
1339: /* Now scan the subexpressions recursively. */
1340:
1341: format_ptr = GET_RTX_FORMAT (code);
1342:
1343: for (i = 0; i < GET_RTX_LENGTH (code); i++)
1344: {
1345: switch (*format_ptr++)
1346: {
1347: case 'e':
1348: restore_reg_data_1 (XEXP (x, i));
1349: break;
1350:
1351: case 'E':
1352: if (XVEC (x, i) != NULL)
1353: {
1354: register int j;
1355:
1356: for (j = 0; j < XVECLEN (x, i); j++)
1357: restore_reg_data_1 (XVECEXP (x, i, j));
1358: }
1359: break;
1360: }
1361: }
1362: }
1363:
1364: /* Initialize data structures and variables in this file
1365: before generating rtl for each function.
1366: WRITE_SYMBOLS is nonzero if any kind of debugging info
1367: is to be generated. */
1368:
1369: void
1370: init_emit (write_symbols)
1371: int write_symbols;
1372: {
1373: first_insn = NULL;
1374: last_insn = NULL;
1375: cur_insn_uid = 1;
1376: reg_rtx_no = FIRST_PSEUDO_REGISTER;
1377: last_linenum = 0;
1378: last_filename = 0;
1379: real_constant_chain = 0;
1380: first_label_num = label_num;
1381: sequence_first_insn = NULL;
1382: sequence_last_insn = NULL;
1383: emit_to_sequence = 0;
1384:
1385: no_line_numbers = ! write_symbols;
1386:
1387: /* Init the tables that describe all the pseudo regs. */
1388:
1389: regno_pointer_flag_length = 100;
1390:
1391: regno_pointer_flag
1392: = (char *) oballoc (regno_pointer_flag_length);
1393: bzero (regno_pointer_flag, regno_pointer_flag_length);
1394:
1395: regno_reg_rtx
1396: = (rtx *) oballoc (regno_pointer_flag_length * sizeof (rtx));
1397: bzero (regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
1398: }
1399:
1400: /* Create some permanent unique rtl objects shared between all functions. */
1401:
1402: void
1403: init_emit_once ()
1404: {
1405: /* Create the unique rtx's for certain rtx codes and operand values. */
1406:
1407: pc_rtx = gen_rtx (PC, VOIDmode);
1408: cc0_rtx = gen_rtx (CC0, VOIDmode);
1409:
1410: /* Don't use gen_rtx here since gen_rtx in this case
1411: tries to use these variables. */
1412: const0_rtx = rtx_alloc (CONST_INT);
1413: INTVAL (const0_rtx) = 0;
1414: const1_rtx = rtx_alloc (CONST_INT);
1415: INTVAL (const1_rtx) = 1;
1416:
1417: fconst0_rtx = rtx_alloc (CONST_DOUBLE);
1418: {
1419: union { double d; int i[2]; } u;
1420: u.d = 0;
1421: XINT (fconst0_rtx, 0) = u.i[0];
1422: XINT (fconst0_rtx, 1) = u.i[1];
1423: XEXP (fconst0_rtx, 2) = const0_rtx;
1424: }
1425: PUT_MODE (fconst0_rtx, SFmode);
1426:
1427: dconst0_rtx = rtx_alloc (CONST_DOUBLE);
1428: {
1429: union { double d; int i[2]; } u;
1430: u.d = 0;
1431: XINT (dconst0_rtx, 0) = u.i[0];
1432: XINT (dconst0_rtx, 1) = u.i[1];
1433: XEXP (dconst0_rtx, 2) = const0_rtx;
1434: }
1435: PUT_MODE (dconst0_rtx, DFmode);
1436:
1437: stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM);
1438: frame_pointer_rtx = gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM);
1439: struct_value_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM);
1440:
1441: #ifdef STRUCT_VALUE_INCOMING_REGNUM
1442: if (STRUCT_VALUE_INCOMING_REGNUM != STRUCT_VALUE_REGNUM)
1443: struct_value_incoming_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_INCOMING_REGNUM);
1444: else
1445: #endif
1446: struct_value_incoming_rtx = struct_value_rtx;
1447:
1448: static_chain_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
1449:
1450: #ifdef STATIC_CHAIN_INCOMING_REGNUM
1451: if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
1452: static_chain_incoming_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_INCOMING_REGNUM);
1453: else
1454: #endif
1455: static_chain_incoming_rtx = static_chain_rtx;
1456:
1457: if (FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM)
1458: arg_pointer_rtx = frame_pointer_rtx;
1459: else
1460: arg_pointer_rtx = gen_rtx (REG, Pmode, ARG_POINTER_REGNUM);
1461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.