|
|
1.1 root 1: /* Convert RTL to assembler code and output it, for GNU compiler.
2: Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: /* This is the final pass of the compiler.
22: It looks at the rtl code for a function and outputs assembler code.
23:
24: Call `final_start_function' to output the assembler code for function entry,
25: `final' to output assembler code for some RTL code,
26: `final_end_function' to output assembler code for function exit.
27: If a function is compiled in several pieces, each piece is
28: output separately with `final'.
29:
30: Some optimizations are also done at this level.
31: Move instructions that were made unnecessary by good register allocation
32: are detected and omitted from the output. (Though most of these
33: are removed by the last jump pass.)
34:
35: Instructions to set the condition codes are omitted when it can be
36: seen that the condition codes already had the desired values.
37:
38: In some cases it is sufficient if the inherited condition codes
39: have related values, but this may require the following insn
40: (the one that tests the condition codes) to be modified.
41:
42: The code for the function prologue and epilogue are generated
43: directly as assembler code by the macros FUNCTION_PROLOGUE and
44: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */
45:
46: #include "config.h"
47: #include "gvarargs.h"
48: #include "rtl.h"
49: #include "regs.h"
50: #include "insn-config.h"
1.1.1.4 root 51: #include "insn-flags.h"
1.1 root 52: #include "insn-attr.h"
53: #include "insn-codes.h"
54: #include "recog.h"
55: #include "conditions.h"
56: #include "flags.h"
57: #include "real.h"
58: #include "hard-reg-set.h"
1.1.1.4 root 59: #include "defaults.h"
1.1 root 60:
1.1.1.4 root 61: #include <stdio.h>
62:
63: #include "output.h"
1.1 root 64:
65: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
1.1.1.2 root 66: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
67: #if defined (USG) || defined (NO_STAB_H)
1.1 root 68: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
69: #else
70: #include <stab.h> /* On BSD, use the system's stab.h. */
71: #endif /* not USG */
1.1.1.2 root 72: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
73:
74: #ifdef XCOFF_DEBUGGING_INFO
75: #include "xcoffout.h"
76: #endif
1.1 root 77:
78: /* .stabd code for line number. */
79: #ifndef N_SLINE
80: #define N_SLINE 0x44
81: #endif
82:
83: /* .stabs code for included file name. */
84: #ifndef N_SOL
85: #define N_SOL 0x84
86: #endif
87:
88: #ifndef INT_TYPE_SIZE
89: #define INT_TYPE_SIZE BITS_PER_WORD
90: #endif
91:
92: /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a
93: null default for it to save conditionalization later. */
94: #ifndef CC_STATUS_INIT
95: #define CC_STATUS_INIT
96: #endif
97:
98: /* How to start an assembler comment. */
99: #ifndef ASM_COMMENT_START
100: #define ASM_COMMENT_START ";#"
101: #endif
102:
103: rtx peephole ();
104: void output_asm_insn ();
105: rtx alter_subreg ();
106: static int alter_cond ();
107: void output_asm_label ();
108: static void output_operand ();
109: void output_address ();
110: void output_addr_const ();
111: static void output_source_line ();
112: rtx final_scan_insn ();
113: void profile_function ();
1.1.1.4 root 114: static void profile_after_prologue ();
1.1 root 115:
116: #ifdef HAVE_ATTR_length
117: static int asm_insn_count ();
118: #endif
119:
120: /* Nonzero means this function is a leaf function, with no function calls.
121: This variable exists to be examined in FUNCTION_PROLOGUE
122: and FUNCTION_EPILOGUE. Always zero, unless set by some action. */
123: int leaf_function;
124:
125: int leaf_function_p ();
126:
127: #ifdef LEAF_REGISTERS
128: int only_leaf_regs_used ();
129: static void leaf_renumber_regs ();
130: void leaf_renumber_regs_insn ();
131: #endif
132:
133: /* Last insn processed by final_scan_insn. */
134: static rtx debug_insn = 0;
135:
136: /* Line number of last NOTE. */
137: static int last_linenum;
138:
139: /* Number of basic blocks seen so far;
140: used if profile_block_flag is set. */
141: static int count_basic_blocks;
142:
143: /* Nonzero while outputting an `asm' with operands.
144: This means that inconsistencies are the user's fault, so don't abort.
145: The precise value is the insn being output, to pass to error_for_asm. */
146: static rtx this_is_asm_operands;
147:
148: /* Number of operands of this insn, for an `asm' with operands. */
149: static int insn_noperands;
150:
151: /* Compare optimization flag. */
152:
153: static rtx last_ignored_compare = 0;
154:
155: /* Flag indicating this insn is the start of a new basic block. */
156:
157: static int new_block = 1;
158:
159: /* All the symbol-blocks (levels of scoping) in the compilation
160: are assigned sequence numbers in order of appearance of the
161: beginnings of the symbol-blocks. Both final and dbxout do this,
162: and assume that they will both give the same number to each block.
163: Final uses these sequence numbers to generate assembler label names
164: LBBnnn and LBEnnn for the beginning and end of the symbol-block.
1.1.1.4 root 165: Dbxout uses the sequence numbers to generate references to the same labels
1.1 root 166: from the dbx debugging information.
167:
168: Sdb records this level at the beginning of each function,
169: in order to find the current level when recursing down declarations.
170: It outputs the block beginning and endings
171: at the point in the asm file where the blocks would begin and end. */
172:
173: int next_block_index;
174:
175: /* Assign a unique number to each insn that is output.
176: This can be used to generate unique local labels. */
177:
178: static int insn_counter = 0;
179:
180: #ifdef HAVE_cc0
181: /* This variable contains machine-dependent flags (defined in tm.h)
182: set and examined by output routines
183: that describe how to interpret the condition codes properly. */
184:
185: CC_STATUS cc_status;
186:
187: /* During output of an insn, this contains a copy of cc_status
188: from before the insn. */
189:
190: CC_STATUS cc_prev_status;
191: #endif
192:
193: /* Indexed by hardware reg number, is 1 if that register is ever
194: used in the current function.
195:
196: In life_analysis, or in stupid_life_analysis, this is set
197: up to record the hard regs used explicitly. Reload adds
198: in the hard regs used for holding pseudo regs. Final uses
199: it to generate the code in the function prologue and epilogue
200: to save and restore registers as needed. */
201:
202: char regs_ever_live[FIRST_PSEUDO_REGISTER];
203:
204: /* Nonzero means current function must be given a frame pointer.
205: Set in stmt.c if anything is allocated on the stack there.
206: Set in reload1.c if anything is allocated on the stack there. */
207:
208: int frame_pointer_needed;
209:
210: /* Assign unique numbers to labels generated for profiling. */
211:
212: int profile_label_no;
213:
214: /* Length so far allocated in PENDING_BLOCKS. */
215:
216: static int max_block_depth;
217:
218: /* Stack of sequence numbers of symbol-blocks of which we have seen the
219: beginning but not yet the end. Sequence numbers are assigned at
220: the beginning; this stack allows us to find the sequence number
221: of a block that is ending. */
222:
223: static int *pending_blocks;
224:
225: /* Number of elements currently in use in PENDING_BLOCKS. */
226:
227: static int block_depth;
228:
229: /* Nonzero if have enabled APP processing of our assembler output. */
230:
231: static int app_on;
232:
233: /* If we are outputting an insn sequence, this contains the sequence rtx.
234: Zero otherwise. */
235:
236: rtx final_sequence;
237:
238: /* Indexed by line number, nonzero if there is a note for that line. */
239:
240: static char *line_note_exists;
241:
242: /* Initialize data in final at the beginning of a compilation. */
243:
244: void
245: init_final (filename)
246: char *filename;
247: {
248: next_block_index = 2;
249: app_on = 0;
250: max_block_depth = 20;
251: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks);
252: final_sequence = 0;
253: }
254:
255: /* Called at end of source file,
256: to output the block-profiling table for this entire compilation. */
257:
258: void
259: end_final (filename)
260: char *filename;
261: {
262: int i;
263:
264: if (profile_block_flag)
265: {
266: char name[12];
267:
268: data_section ();
269:
270: /* Output the main header, of 6 words:
271: 0: 1 if this file's initialized, else 0.
272: 1: address of file name.
273: 2: address of table of counts.
274: 4: number of counts in the table.
275: 5: always 0, for compatibility with Sun.
276: 6: extra word added by GNU: address of address table
277: which contains addresses of basic blocks,
278: in parallel with the table of counts. */
279: ASM_OUTPUT_ALIGN (asm_out_file,
280: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
281:
282: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
283: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
284: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
285: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
286: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
287: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
1.1.1.4 root 288: assemble_integer (GEN_INT (count_basic_blocks), UNITS_PER_WORD, 1);
1.1 root 289: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
290: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
291: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
292:
293: /* Output the file name. */
294: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
295: {
296: int len = strlen (filename);
297: char *data_file = (char *) alloca (len + 3);
298: strcpy (data_file, filename);
299: strip_off_ending (data_file, len);
300: strcat (data_file, ".d");
301: assemble_string (data_file, strlen (data_file) + 1);
302: }
303:
304: /* Realign data section. */
305: ASM_OUTPUT_ALIGN (asm_out_file,
306: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
307:
308: /* Make space for the table of counts. */
309: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
1.1.1.5 ! root 310: if (count_basic_blocks != 0)
! 311: assemble_zeros (INT_TYPE_SIZE / BITS_PER_UNIT * count_basic_blocks);
1.1 root 312:
313: /* Output the table of addresses. */
314: readonly_data_section ();
1.1.1.4 root 315: /* Realign in new section */
316: ASM_OUTPUT_ALIGN (asm_out_file,
317: floor_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
1.1 root 318: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3);
319: for (i = 0; i < count_basic_blocks; i++)
320: {
321: char name[12];
322: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
323: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
324: UNITS_PER_WORD, 1);
325: }
326:
327: /* End with the address of the table of addresses,
328: so we can find it easily, as the last word in the file's text. */
329: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
330: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
331: }
332: }
333:
334: /* Enable APP processing of subsequent output.
335: Used before the output from an `asm' statement. */
336:
337: void
338: app_enable ()
339: {
340: if (! app_on)
341: {
342: fprintf (asm_out_file, ASM_APP_ON);
343: app_on = 1;
344: }
345: }
346:
347: /* Enable APP processing of subsequent output.
348: Called from varasm.c before most kinds of output. */
349:
350: void
351: app_disable ()
352: {
353: if (app_on)
354: {
355: fprintf (asm_out_file, ASM_APP_OFF);
356: app_on = 0;
357: }
358: }
359:
360: /* Return the number of slots filled in the current
361: delayed branch sequence (we don't count the insn needing the
362: delay slot). Zero if not in a delayed branch sequence. */
363:
364: #ifdef DELAY_SLOTS
365: int
366: dbr_sequence_length ()
367: {
368: if (final_sequence != 0)
369: return XVECLEN (final_sequence, 0) - 1;
370: else
371: return 0;
372: }
373: #endif
374:
375: /* The next two pages contain routines used to compute the length of an insn
376: and to shorten branches. */
377:
378: /* Arrays for insn lengths, and addresses. The latter is referenced by
379: `insn_current_length'. */
380:
381: static short *insn_lengths;
382: int *insn_addresses;
383:
384: /* Address of insn being processed. Used by `insn_current_length'. */
385: int insn_current_address;
386:
387: /* Indicate the branch shortening hasn't yet been done. */
388:
389: void
390: init_insn_lengths ()
391: {
392: insn_lengths = 0;
393: }
394:
395: /* Obtain the current length of an insn. If branch shortening has been done,
396: get its actual length. Otherwise, get its maximum length. */
397:
398: int
399: get_attr_length (insn)
400: rtx insn;
401: {
402: #ifdef HAVE_ATTR_length
403: rtx body;
404: int i;
405: int length = 0;
406:
407: if (insn_lengths)
408: return insn_lengths[INSN_UID (insn)];
409: else
410: switch (GET_CODE (insn))
411: {
412: case NOTE:
413: case BARRIER:
414: case CODE_LABEL:
415: return 0;
416:
417: case CALL_INSN:
418: length = insn_default_length (insn);
419: break;
420:
421: case JUMP_INSN:
422: body = PATTERN (insn);
423: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
424: {
425: /* This only takes room if jump tables go into the text section. */
426: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
427: length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
428: * GET_MODE_SIZE (GET_MODE (body)));
429:
430: /* Be pessimistic and assume worst-case alignment. */
431: length += (GET_MODE_SIZE (GET_MODE (body)) - 1);
432: #else
433: return 0;
434: #endif
435: }
436: else
437: length = insn_default_length (insn);
438: break;
439:
440: case INSN:
441: body = PATTERN (insn);
442: if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
443: return 0;
444:
445: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
446: length = asm_insn_count (insn) * insn_default_length (insn);
447: else if (GET_CODE (body) == SEQUENCE)
448: for (i = 0; i < XVECLEN (body, 0); i++)
449: length += get_attr_length (XVECEXP (body, 0, i));
450: else
451: length = insn_default_length (insn);
452: }
453:
454: #ifdef ADJUST_INSN_LENGTH
455: ADJUST_INSN_LENGTH (insn, length);
456: #endif
457: return length;
458: #else /* not HAVE_ATTR_length */
459: return 0;
460: #endif /* not HAVE_ATTR_length */
461: }
462:
463: /* Make a pass over all insns and compute their actual lengths by shortening
464: any branches of variable length if possible. */
465:
466: /* Give a default value for the lowest address in a function. */
467:
468: #ifndef FIRST_INSN_ADDRESS
469: #define FIRST_INSN_ADDRESS 0
470: #endif
471:
472: void
473: shorten_branches (first)
474: rtx first;
475: {
476: #ifdef HAVE_ATTR_length
477: rtx insn;
478: int something_changed = 1;
479: int max_uid = 0;
480: char *varying_length;
481: rtx body;
482: int uid;
483:
484: /* Compute maximum UID and allocate arrays. */
485: for (insn = first; insn; insn = NEXT_INSN (insn))
486: if (INSN_UID (insn) > max_uid)
487: max_uid = INSN_UID (insn);
488:
489: max_uid++;
490: insn_lengths = (short *) oballoc (max_uid * sizeof (short));
491: insn_addresses = (int *) oballoc (max_uid * sizeof (int));
492: varying_length = (char *) oballoc (max_uid * sizeof (char));
493:
494: /* Compute initial lengths, addresses, and varying flags for each insn. */
495: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
496: insn != 0;
497: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
498: {
499: uid = INSN_UID (insn);
500: insn_addresses[uid] = insn_current_address;
501: insn_lengths[uid] = 0;
502: varying_length[uid] = 0;
503:
504: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
505: || GET_CODE (insn) == CODE_LABEL)
506: continue;
507:
508: body = PATTERN (insn);
509: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
510: {
511: /* This only takes room if read-only data goes into the text
512: section. */
513: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
514: int unitsize = GET_MODE_SIZE (GET_MODE (body));
515:
516: insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
517: * GET_MODE_SIZE (GET_MODE (body)));
518:
519: /* Account for possible alignment. */
520: insn_lengths[uid]
521: += unitsize - (insn_current_address & (unitsize - 1));
522: #else
523: ;
524: #endif
525: }
526: else if (asm_noperands (body) >= 0)
527: insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
528: else if (GET_CODE (body) == SEQUENCE)
529: {
530: int i;
1.1.1.4 root 531: int const_delay_slots;
532: #ifdef DELAY_SLOTS
533: const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0));
534: #else
535: const_delay_slots = 0;
536: #endif
1.1 root 537: /* Inside a delay slot sequence, we do not do any branch shortening
1.1.1.4 root 538: if the shortening could change the number of delay slots
539: of the branch. */
1.1 root 540: for (i = 0; i < XVECLEN (body, 0); i++)
541: {
542: rtx inner_insn = XVECEXP (body, 0, i);
543: int inner_uid = INSN_UID (inner_insn);
544: int inner_length;
545:
546: if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0)
547: inner_length = (asm_insn_count (PATTERN (inner_insn))
548: * insn_default_length (inner_insn));
549: else
550: inner_length = insn_default_length (inner_insn);
551:
552: insn_lengths[inner_uid] = inner_length;
1.1.1.4 root 553: if (const_delay_slots)
554: {
555: if ((varying_length[inner_uid]
556: = insn_variable_length_p (inner_insn)) != 0)
557: varying_length[uid] = 1;
558: insn_addresses[inner_uid] = (insn_current_address +
559: insn_lengths[uid]);
560: }
561: else
562: varying_length[inner_uid] = 0;
1.1 root 563: insn_lengths[uid] += inner_length;
564: }
565: }
566: else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
567: {
568: insn_lengths[uid] = insn_default_length (insn);
569: varying_length[uid] = insn_variable_length_p (insn);
570: }
571:
572: /* If needed, do any adjustment. */
573: #ifdef ADJUST_INSN_LENGTH
574: ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
575: #endif
576: }
577:
578: /* Now loop over all the insns finding varying length insns. For each,
579: get the current insn length. If it has changed, reflect the change.
580: When nothing changes for a full pass, we are done. */
581:
582: while (something_changed)
583: {
584: something_changed = 0;
585: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
586: insn != 0;
1.1.1.4 root 587: insn = NEXT_INSN (insn))
1.1 root 588: {
589: int new_length;
1.1.1.5 ! root 590: int tmp_length;
1.1 root 591:
592: uid = INSN_UID (insn);
593: insn_addresses[uid] = insn_current_address;
594: if (! varying_length[uid])
1.1.1.4 root 595: {
596: insn_current_address += insn_lengths[uid];
597: continue;
598: }
599: if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
600: {
601: int i;
602:
603: body = PATTERN (insn);
604: new_length = 0;
605: for (i = 0; i < XVECLEN (body, 0); i++)
606: {
607: rtx inner_insn = XVECEXP (body, 0, i);
608: int inner_uid = INSN_UID (inner_insn);
609: int inner_length;
610:
611: insn_addresses[inner_uid] = insn_current_address;
1.1.1.5 ! root 612:
! 613: /* insn_current_length returns 0 for insns with a
! 614: non-varying length. */
! 615: if (! varying_length[inner_uid])
! 616: inner_length = insn_lengths[inner_uid];
! 617: else
! 618: inner_length = insn_current_length (inner_insn);
! 619:
1.1.1.4 root 620: if (inner_length != insn_lengths[inner_uid])
621: {
622: insn_lengths[inner_uid] = inner_length;
623: something_changed = 1;
624: }
625: insn_current_address += insn_lengths[inner_uid];
626: new_length += inner_length;
627: }
628: }
629: else
630: {
631: new_length = insn_current_length (insn);
632: insn_current_address += new_length;
633: }
1.1.1.5 ! root 634:
! 635: #ifdef SHORTEN_WITH_ADJUST_INSN_LENGTH
! 636: #ifdef ADJUST_INSN_LENGTH
! 637: /* If needed, do any adjustment. */
! 638: tmp_length = new_length;
! 639: ADJUST_INSN_LENGTH (insn, new_length);
! 640: insn_current_address += (new_length - tmp_length);
! 641: #endif
! 642: #endif
! 643:
1.1 root 644: if (new_length != insn_lengths[uid])
645: {
646: insn_lengths[uid] = new_length;
647: something_changed = 1;
648: }
649: }
650: }
651: #endif /* HAVE_ATTR_length */
652: }
653:
654: #ifdef HAVE_ATTR_length
655: /* Given the body of an INSN known to be generated by an ASM statement, return
656: the number of machine instructions likely to be generated for this insn.
657: This is used to compute its length. */
658:
659: static int
660: asm_insn_count (body)
661: rtx body;
662: {
663: char *template;
664: int count = 1;
665:
1.1.1.4 root 666: for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR,
667: NULL_PTR, NULL_PTR);
1.1 root 668: *template; template++)
669: if (*template == ';' || *template == '\n')
670: count++;
671:
672: return count;
673: }
674: #endif
675:
676: /* Output assembler code for the start of a function,
677: and initialize some of the variables in this file
678: for the new function. The label for the function and associated
679: assembler pseudo-ops have already been output in `assemble_start_function'.
680:
681: FIRST is the first insn of the rtl for the function being compiled.
682: FILE is the file to write assembler code to.
683: OPTIMIZE is nonzero if we should eliminate redundant
684: test and compare insns. */
685:
686: void
687: final_start_function (first, file, optimize)
688: rtx first;
689: FILE *file;
690: int optimize;
691: {
692: block_depth = 0;
693:
694: this_is_asm_operands = 0;
695:
696: #ifdef NON_SAVING_SETJMP
697: /* A function that calls setjmp should save and restore all the
698: call-saved registers on a system where longjmp clobbers them. */
699: if (NON_SAVING_SETJMP && current_function_calls_setjmp)
700: {
701: int i;
702:
703: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
704: if (!call_used_regs[i] && !call_fixed_regs[i])
705: regs_ever_live[i] = 1;
706: }
707: #endif
708:
709: /* Initial line number is supposed to be output
710: before the function's prologue and label
711: so that the function's address will not appear to be
712: in the last statement of the preceding function. */
713: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)
714: {
715: if (write_symbols == SDB_DEBUG)
716: /* For sdb, let's not, but say we did.
717: We need to set last_linenum for sdbout_function_begin,
718: but we can't have an actual line number before the .bf symbol.
719: (sdb_begin_function_line is not set,
720: and other compilers don't do it.) */
721: last_linenum = NOTE_LINE_NUMBER (first);
1.1.1.2 root 722: #ifdef XCOFF_DEBUGGING_INFO
723: else if (write_symbols == XCOFF_DEBUG)
724: {
725: last_linenum = NOTE_LINE_NUMBER (first);
726: xcoffout_output_first_source_line (file, last_linenum);
727: }
728: #endif
1.1 root 729: else
730: output_source_line (file, first);
731: }
732:
733: #ifdef LEAF_REG_REMAP
734: if (leaf_function)
735: leaf_renumber_regs (first);
736: #endif
737:
738: /* The Sun386i and perhaps other machines don't work right
739: if the profiling code comes after the prologue. */
740: #ifdef PROFILE_BEFORE_PROLOGUE
741: if (profile_flag)
742: profile_function (file);
743: #endif /* PROFILE_BEFORE_PROLOGUE */
744:
745: #ifdef FUNCTION_PROLOGUE
746: /* First output the function prologue: code to set up the stack frame. */
747: FUNCTION_PROLOGUE (file, get_frame_size ());
748: #endif
749:
1.1.1.2 root 750: #if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
751: if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG)
1.1 root 752: next_block_index = 1;
753: #endif
754:
1.1.1.4 root 755: /* If the machine represents the prologue as RTL, the profiling code must
756: be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
757: #ifdef HAVE_prologue
758: if (! HAVE_prologue)
759: #endif
760: profile_after_prologue (file);
761:
762: profile_label_no++;
763: }
764:
765: static void
766: profile_after_prologue (file)
767: FILE *file;
768: {
1.1 root 769: #ifdef FUNCTION_BLOCK_PROFILER
770: if (profile_block_flag)
771: {
772: FUNCTION_BLOCK_PROFILER (file, profile_label_no);
773: }
774: #endif /* FUNCTION_BLOCK_PROFILER */
775:
776: #ifndef PROFILE_BEFORE_PROLOGUE
777: if (profile_flag)
778: profile_function (file);
779: #endif /* not PROFILE_BEFORE_PROLOGUE */
780: }
781:
782: void
783: profile_function (file)
784: FILE *file;
785: {
786: int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE);
787: int sval = current_function_returns_struct;
788: int cxt = current_function_needs_context;
789:
790: data_section ();
791: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
792: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
793: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
794:
795: text_section ();
796:
797: #ifdef STRUCT_VALUE_INCOMING_REGNUM
798: if (sval)
799: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
800: #else
801: #ifdef STRUCT_VALUE_REGNUM
802: if (sval)
803: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
804: #endif
805: #endif
806:
807: #if 0
808: #ifdef STATIC_CHAIN_INCOMING_REGNUM
809: if (cxt)
810: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
811: #else
812: #ifdef STATIC_CHAIN_REGNUM
813: if (cxt)
814: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
815: #endif
816: #endif
817: #endif /* 0 */
818:
819: FUNCTION_PROFILER (file, profile_label_no);
820:
821: #if 0
822: #ifdef STATIC_CHAIN_INCOMING_REGNUM
823: if (cxt)
824: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
825: #else
826: #ifdef STATIC_CHAIN_REGNUM
827: if (cxt)
828: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
829: #endif
830: #endif
831: #endif /* 0 */
832:
833: #ifdef STRUCT_VALUE_INCOMING_REGNUM
834: if (sval)
835: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
836: #else
837: #ifdef STRUCT_VALUE_REGNUM
838: if (sval)
839: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
840: #endif
841: #endif
842: }
843:
844: /* Output assembler code for the end of a function.
845: For clarity, args are same as those of `final_start_function'
846: even though not all of them are needed. */
847:
848: void
849: final_end_function (first, file, optimize)
850: rtx first;
851: FILE *file;
852: int optimize;
853: {
854: if (app_on)
855: {
856: fprintf (file, ASM_APP_OFF);
857: app_on = 0;
858: }
859:
860: #ifdef SDB_DEBUGGING_INFO
861: if (write_symbols == SDB_DEBUG)
862: sdbout_end_function (last_linenum);
863: #endif
864:
1.1.1.4 root 865: #ifdef DWARF_DEBUGGING_INFO
866: if (write_symbols == DWARF_DEBUG)
867: dwarfout_end_function ();
868: #endif
869:
1.1.1.2 root 870: #ifdef XCOFF_DEBUGGING_INFO
871: if (write_symbols == XCOFF_DEBUG)
872: xcoffout_end_function (file, last_linenum);
873: #endif
874:
1.1 root 875: #ifdef FUNCTION_EPILOGUE
876: /* Finally, output the function epilogue:
877: code to restore the stack frame and return to the caller. */
878: FUNCTION_EPILOGUE (file, get_frame_size ());
879: #endif
880:
881: #ifdef SDB_DEBUGGING_INFO
882: if (write_symbols == SDB_DEBUG)
883: sdbout_end_epilogue ();
884: #endif
885:
886: #ifdef DWARF_DEBUGGING_INFO
887: if (write_symbols == DWARF_DEBUG)
888: dwarfout_end_epilogue ();
889: #endif
890:
1.1.1.2 root 891: #ifdef XCOFF_DEBUGGING_INFO
892: if (write_symbols == XCOFF_DEBUG)
893: xcoffout_end_epilogue (file);
894: #endif
895:
1.1 root 896: /* If FUNCTION_EPILOGUE is not defined, then the function body
897: itself contains return instructions wherever needed. */
898: }
899:
900: /* Output assembler code for some insns: all or part of a function.
901: For description of args, see `final_start_function', above.
902:
903: PRESCAN is 1 if we are not really outputting,
904: just scanning as if we were outputting.
905: Prescanning deletes and rearranges insns just like ordinary output.
906: PRESCAN is -2 if we are outputting after having prescanned.
907: In this case, don't try to delete or rearrange insns
908: because that has already been done.
909: Prescanning is done only on certain machines. */
910:
911: void
912: final (first, file, optimize, prescan)
913: rtx first;
914: FILE *file;
915: int optimize;
916: int prescan;
917: {
918: register rtx insn;
919: int max_line = 0;
920:
921: last_ignored_compare = 0;
922: new_block = 1;
923:
1.1.1.4 root 924: /* Make a map indicating which line numbers appear in this function.
925: When producing SDB debugging info, delete troublesome line number
926: notes from inlined functions in other files as well as duplicate
927: line number notes. */
928: #ifdef SDB_DEBUGGING_INFO
929: if (write_symbols == SDB_DEBUG)
930: {
931: rtx last = 0;
932: for (insn = first; insn; insn = NEXT_INSN (insn))
933: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
934: {
935: if ((RTX_INTEGRATED_P (insn)
936: && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0)
937: || (last != 0
938: && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
939: && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)))
940: {
941: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
942: NOTE_SOURCE_FILE (insn) = 0;
943: continue;
944: }
945: last = insn;
946: if (NOTE_LINE_NUMBER (insn) > max_line)
947: max_line = NOTE_LINE_NUMBER (insn);
948: }
949: }
950: else
951: #endif
952: {
953: for (insn = first; insn; insn = NEXT_INSN (insn))
954: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line)
955: max_line = NOTE_LINE_NUMBER (insn);
956: }
1.1 root 957:
958: line_note_exists = (char *) oballoc (max_line + 1);
959: bzero (line_note_exists, max_line + 1);
960:
961: for (insn = first; insn; insn = NEXT_INSN (insn))
962: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
963: line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;
964:
965: init_recog ();
966:
967: CC_STATUS_INIT;
968:
969: /* Output the insns. */
970: for (insn = NEXT_INSN (first); insn;)
971: insn = final_scan_insn (insn, file, optimize, prescan, 0);
972:
973: /* Do basic-block profiling here
974: if the last insn was a conditional branch. */
975: if (profile_block_flag && new_block)
976: {
977: new_block = 0;
978: /* Enable the table of basic-block use counts
979: to point at the code it applies to. */
980: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);
981: /* Before first insn of this basic block, increment the
982: count of times it was entered. */
983: #ifdef BLOCK_PROFILER
984: BLOCK_PROFILER (file, count_basic_blocks);
985: CC_STATUS_INIT;
986: #endif
987: count_basic_blocks++;
988: }
989: }
990:
991: /* The final scan for one insn, INSN.
992: Args are same as in `final', except that INSN
993: is the insn being scanned.
994: Value returned is the next insn to be scanned.
995:
996: NOPEEPHOLES is the flag to disallow peephole processing (currently
997: used for within delayed branch sequence output). */
998:
999: rtx
1000: final_scan_insn (insn, file, optimize, prescan, nopeepholes)
1001: rtx insn;
1002: FILE *file;
1003: int optimize;
1004: int prescan;
1005: int nopeepholes;
1006: {
1007: register int i;
1008: insn_counter++;
1009:
1010: /* Ignore deleted insns. These can occur when we split insns (due to a
1011: template of "#") while not optimizing. */
1012: if (INSN_DELETED_P (insn))
1013: return NEXT_INSN (insn);
1014:
1015: switch (GET_CODE (insn))
1016: {
1017: case NOTE:
1018: if (prescan > 0)
1019: break;
1020:
1021: /* Align the beginning of a loop, for higher speed
1022: on certain machines. */
1023:
1024: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0)
1025: {
1026: #ifdef ASM_OUTPUT_LOOP_ALIGN
1027: rtx next = next_nonnote_insn (insn);
1028: if (next && GET_CODE (next) == CODE_LABEL)
1029: {
1030: ASM_OUTPUT_LOOP_ALIGN (asm_out_file);
1031: }
1032: #endif
1033: break;
1034: }
1035: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
1036: break;
1037:
1.1.1.4 root 1038: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
1039: {
1040: #ifdef FUNCTION_END_PROLOGUE
1041: FUNCTION_END_PROLOGUE (file);
1042: #endif
1043: profile_after_prologue (file);
1044: break;
1045: }
1046:
1047: #ifdef FUNCTION_BEGIN_EPILOGUE
1048: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
1049: {
1050: FUNCTION_BEGIN_EPILOGUE (file);
1051: break;
1052: }
1053: #endif
1054:
1.1 root 1055: if (write_symbols == NO_DEBUG)
1056: break;
1057: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
1058: {
1059: #ifdef SDB_DEBUGGING_INFO
1060: if (write_symbols == SDB_DEBUG)
1061: sdbout_begin_function (last_linenum);
1062: #endif
1.1.1.2 root 1063: #ifdef XCOFF_DEBUGGING_INFO
1064: if (write_symbols == XCOFF_DEBUG)
1065: xcoffout_begin_function (file, last_linenum);
1066: #endif
1.1.1.4 root 1067: #ifdef DWARF_DEBUGGING_INFO
1068: if (write_symbols == DWARF_DEBUG)
1069: dwarfout_begin_function ();
1070: #endif
1.1 root 1071: break;
1072: }
1073: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
1074: break; /* An insn that was "deleted" */
1075: if (app_on)
1076: {
1077: fprintf (file, ASM_APP_OFF);
1078: app_on = 0;
1079: }
1080: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
1081: && (debug_info_level == DINFO_LEVEL_NORMAL
1.1.1.4 root 1082: || debug_info_level == DINFO_LEVEL_VERBOSE
1083: #ifdef DWARF_DEBUGGING_INFO
1084: || write_symbols == DWARF_DEBUG
1085: #endif
1086: )
1087: )
1.1 root 1088: {
1089: /* Beginning of a symbol-block. Assign it a sequence number
1090: and push the number onto the stack PENDING_BLOCKS. */
1091:
1092: if (block_depth == max_block_depth)
1093: {
1094: /* PENDING_BLOCKS is full; make it longer. */
1095: max_block_depth *= 2;
1096: pending_blocks
1097: = (int *) xrealloc (pending_blocks,
1098: max_block_depth * sizeof (int));
1099: }
1100: pending_blocks[block_depth++] = next_block_index;
1101:
1102: /* Output debugging info about the symbol-block beginning. */
1103:
1104: #ifdef SDB_DEBUGGING_INFO
1105: if (write_symbols == SDB_DEBUG)
1106: sdbout_begin_block (file, last_linenum, next_block_index);
1107: #endif
1.1.1.2 root 1108: #ifdef XCOFF_DEBUGGING_INFO
1109: if (write_symbols == XCOFF_DEBUG)
1110: xcoffout_begin_block (file, last_linenum, next_block_index);
1111: #endif
1.1 root 1112: #ifdef DBX_DEBUGGING_INFO
1113: if (write_symbols == DBX_DEBUG)
1114: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);
1115: #endif
1116: #ifdef DWARF_DEBUGGING_INFO
1117: if (write_symbols == DWARF_DEBUG && block_depth > 1)
1118: dwarfout_begin_block (next_block_index);
1119: #endif
1120:
1121: next_block_index++;
1122: }
1123: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
1124: && (debug_info_level == DINFO_LEVEL_NORMAL
1.1.1.4 root 1125: || debug_info_level == DINFO_LEVEL_VERBOSE
1126: #ifdef DWARF_DEBUGGING_INFO
1127: || write_symbols == DWARF_DEBUG
1128: #endif
1129: )
1130: )
1.1 root 1131: {
1132: /* End of a symbol-block. Pop its sequence number off
1133: PENDING_BLOCKS and output debugging info based on that. */
1134:
1135: --block_depth;
1136:
1.1.1.2 root 1137: #ifdef XCOFF_DEBUGGING_INFO
1138: if (write_symbols == XCOFF_DEBUG && block_depth >= 0)
1139: xcoffout_end_block (file, last_linenum, pending_blocks[block_depth]);
1140: #endif
1.1 root 1141: #ifdef DBX_DEBUGGING_INFO
1142: if (write_symbols == DBX_DEBUG && block_depth >= 0)
1143: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",
1144: pending_blocks[block_depth]);
1145: #endif
1146: #ifdef SDB_DEBUGGING_INFO
1147: if (write_symbols == SDB_DEBUG && block_depth >= 0)
1148: sdbout_end_block (file, last_linenum);
1149: #endif
1150: #ifdef DWARF_DEBUGGING_INFO
1151: if (write_symbols == DWARF_DEBUG && block_depth >= 1)
1152: dwarfout_end_block (pending_blocks[block_depth]);
1153: #endif
1154: }
1.1.1.4 root 1155: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL
1156: && (debug_info_level == DINFO_LEVEL_NORMAL
1157: || debug_info_level == DINFO_LEVEL_VERBOSE))
1158: {
1159: #ifdef DWARF_DEBUGGING_INFO
1160: if (write_symbols == DWARF_DEBUG)
1161: dwarfout_label (insn);
1162: #endif
1163: }
1.1 root 1164: else if (NOTE_LINE_NUMBER (insn) > 0)
1165: /* This note is a line-number. */
1166: {
1167: register rtx note;
1168:
1169: #if 0 /* This is what we used to do. */
1170: output_source_line (file, insn);
1171: #endif
1172: int note_after = 0;
1173:
1174: /* If there is anything real after this note,
1175: output it. If another line note follows, omit this one. */
1176: for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))
1177: {
1178: if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)
1179: break;
1.1.1.3 root 1180: /* These types of notes can be significant
1.1.1.4 root 1181: so make sure the preceding line number stays. */
1.1.1.3 root 1182: else if (GET_CODE (note) == NOTE
1183: && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG
1184: || NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END
1185: || NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG))
1186: break;
1.1 root 1187: else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)
1188: {
1.1.1.3 root 1189: /* Another line note follows; we can delete this note
1190: if no intervening line numbers have notes elsewhere. */
1.1 root 1191: int num;
1192: for (num = NOTE_LINE_NUMBER (insn) + 1;
1193: num < NOTE_LINE_NUMBER (note);
1194: num++)
1195: if (line_note_exists[num])
1196: break;
1197:
1.1.1.4 root 1198: if (num >= NOTE_LINE_NUMBER (note))
1.1 root 1199: note_after = 1;
1200: break;
1201: }
1202: }
1203:
1204: /* Output this line note
1205: if it is the first or the last line note in a row. */
1206: if (!note_after)
1207: output_source_line (file, insn);
1208: }
1209: break;
1210:
1211: case BARRIER:
1212: #ifdef ASM_OUTPUT_ALIGN_CODE
1.1.1.4 root 1213: /* Don't litter the assembler output with needless alignments. A
1214: BARRIER will be placed at the end of every function if HAVE_epilogue
1215: is true. */
1216: if (NEXT_INSN (insn))
1217: ASM_OUTPUT_ALIGN_CODE (file);
1.1 root 1218: #endif
1219: break;
1220:
1221: case CODE_LABEL:
1222: CC_STATUS_INIT;
1223: if (prescan > 0)
1224: break;
1225: new_block = 1;
1226: #ifdef SDB_DEBUGGING_INFO
1227: if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
1228: sdbout_label (insn);
1229: #endif
1230: #ifdef DWARF_DEBUGGING_INFO
1231: if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))
1232: dwarfout_label (insn);
1233: #endif
1234: if (app_on)
1235: {
1236: fprintf (file, ASM_APP_OFF);
1237: app_on = 0;
1238: }
1239: if (NEXT_INSN (insn) != 0
1240: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
1241: {
1242: rtx nextbody = PATTERN (NEXT_INSN (insn));
1243:
1244: /* If this label is followed by a jump-table,
1245: make sure we put the label in the read-only section. Also
1246: possibly write the label and jump table together. */
1247:
1248: if (GET_CODE (nextbody) == ADDR_VEC
1249: || GET_CODE (nextbody) == ADDR_DIFF_VEC)
1250: {
1251: #ifndef JUMP_TABLES_IN_TEXT_SECTION
1252: readonly_data_section ();
1.1.1.4 root 1253: #ifdef READONLY_DATA_SECTION
1254: ASM_OUTPUT_ALIGN (file,
1255: exact_log2 (BIGGEST_ALIGNMENT
1256: / BITS_PER_UNIT));
1257: #endif /* READONLY_DATA_SECTION */
1258: #else /* JUMP_TABLES_IN_TEXT_SECTION */
1.1 root 1259: text_section ();
1.1.1.4 root 1260: #endif /* JUMP_TABLES_IN_TEXT_SECTION */
1.1 root 1261: #ifdef ASM_OUTPUT_CASE_LABEL
1262: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
1263: NEXT_INSN (insn));
1264: #else
1265: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
1266: #endif
1267: break;
1268: }
1269: }
1270:
1271: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
1272: break;
1273:
1274: default:
1275: {
1276: register rtx body = PATTERN (insn);
1277: int insn_code_number;
1278: char *template;
1279: rtx note;
1280:
1281: /* An INSN, JUMP_INSN or CALL_INSN.
1282: First check for special kinds that recog doesn't recognize. */
1283:
1284: if (GET_CODE (body) == USE /* These are just declarations */
1285: || GET_CODE (body) == CLOBBER)
1286: break;
1287:
1288: #ifdef HAVE_cc0
1289: /* If there is a REG_CC_SETTER note on this insn, it means that
1290: the setting of the condition code was done in the delay slot
1291: of the insn that branched here. So recover the cc status
1292: from the insn that set it. */
1293:
1.1.1.4 root 1294: note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
1.1 root 1295: if (note)
1296: {
1297: NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
1298: cc_prev_status = cc_status;
1299: }
1300: #endif
1301:
1302: /* Detect insns that are really jump-tables
1303: and output them as such. */
1304:
1305: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
1306: {
1307: register int vlen, idx;
1308:
1309: if (prescan > 0)
1310: break;
1311:
1312: if (app_on)
1313: {
1314: fprintf (file, ASM_APP_OFF);
1315: app_on = 0;
1316: }
1317:
1318: vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
1319: for (idx = 0; idx < vlen; idx++)
1320: {
1321: if (GET_CODE (body) == ADDR_VEC)
1.1.1.4 root 1322: {
1323: #ifdef ASM_OUTPUT_ADDR_VEC_ELT
1324: ASM_OUTPUT_ADDR_VEC_ELT
1325: (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
1326: #else
1327: abort ();
1328: #endif
1329: }
1.1 root 1330: else
1.1.1.4 root 1331: {
1332: #ifdef ASM_OUTPUT_ADDR_DIFF_ELT
1333: ASM_OUTPUT_ADDR_DIFF_ELT
1334: (file,
1335: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
1336: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
1337: #else
1338: abort ();
1339: #endif
1340: }
1.1 root 1341: }
1342: #ifdef ASM_OUTPUT_CASE_END
1343: ASM_OUTPUT_CASE_END (file,
1344: CODE_LABEL_NUMBER (PREV_INSN (insn)),
1345: insn);
1346: #endif
1347:
1348: text_section ();
1349:
1350: break;
1351: }
1352:
1353: /* Do basic-block profiling when we reach a new block.
1354: Done here to avoid jump tables. */
1355: if (profile_block_flag && new_block)
1356: {
1357: new_block = 0;
1358: /* Enable the table of basic-block use counts
1359: to point at the code it applies to. */
1360: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);
1361: /* Before first insn of this basic block, increment the
1362: count of times it was entered. */
1363: #ifdef BLOCK_PROFILER
1364: BLOCK_PROFILER (file, count_basic_blocks);
1365: CC_STATUS_INIT;
1366: #endif
1367: count_basic_blocks++;
1368: }
1369:
1370: if (GET_CODE (body) == ASM_INPUT)
1371: {
1372: /* There's no telling what that did to the condition codes. */
1373: CC_STATUS_INIT;
1374: if (prescan > 0)
1375: break;
1376: if (! app_on)
1377: {
1378: fprintf (file, ASM_APP_ON);
1379: app_on = 1;
1380: }
1381: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0));
1382: break;
1383: }
1384:
1385: /* Detect `asm' construct with operands. */
1386: if (asm_noperands (body) >= 0)
1387: {
1388: int noperands = asm_noperands (body);
1389: rtx *ops;
1390: char *string;
1391:
1392: /* There's no telling what that did to the condition codes. */
1393: CC_STATUS_INIT;
1394: if (prescan > 0)
1395: break;
1396:
1397: /* alloca won't do here, since only return from `final'
1398: would free it. */
1399: if (noperands > 0)
1400: ops = (rtx *) xmalloc (noperands * sizeof (rtx));
1401:
1402: if (! app_on)
1403: {
1404: fprintf (file, ASM_APP_ON);
1405: app_on = 1;
1406: }
1407:
1408: /* Get out the operand values. */
1.1.1.4 root 1409: string = decode_asm_operands (body, ops, NULL_PTR,
1410: NULL_PTR, NULL_PTR);
1.1 root 1411: /* Inhibit aborts on what would otherwise be compiler bugs. */
1412: insn_noperands = noperands;
1413: this_is_asm_operands = insn;
1414: /* Output the insn using them. */
1415: output_asm_insn (string, ops);
1416: this_is_asm_operands = 0;
1417: if (noperands > 0)
1418: free (ops);
1419: break;
1420: }
1421:
1422: if (prescan <= 0 && app_on)
1423: {
1424: fprintf (file, ASM_APP_OFF);
1425: app_on = 0;
1426: }
1427:
1428: if (GET_CODE (body) == SEQUENCE)
1429: {
1430: /* A delayed-branch sequence */
1431: register int i;
1432: rtx next;
1433:
1434: if (prescan > 0)
1435: break;
1436: final_sequence = body;
1437:
1438: /* The first insn in this SEQUENCE might be a JUMP_INSN that will
1439: force the restoration of a comparison that was previously
1440: thought unnecessary. If that happens, cancel this sequence
1441: and cause that insn to be restored. */
1442:
1443: next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1);
1444: if (next != XVECEXP (body, 0, 1))
1445: {
1446: final_sequence = 0;
1447: return next;
1448: }
1449:
1450: for (i = 1; i < XVECLEN (body, 0); i++)
1451: final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1);
1452: #ifdef DBR_OUTPUT_SEQEND
1453: DBR_OUTPUT_SEQEND (file);
1454: #endif
1455: final_sequence = 0;
1456:
1457: /* If the insn requiring the delay slot was a CALL_INSN, the
1458: insns in the delay slot are actually executed before the
1459: called function. Hence we don't preserve any CC-setting
1460: actions in these insns and the CC must be marked as being
1461: clobbered by the function. */
1462: if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)
1463: CC_STATUS_INIT;
1.1.1.3 root 1464:
1465: /* Following a conditional branch sequence, we have a new basic
1466: block. */
1467: if (profile_block_flag)
1468: {
1469: rtx insn = XVECEXP (body, 0, 0);
1470: rtx body = PATTERN (insn);
1471:
1472: if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
1473: && GET_CODE (SET_SRC (body)) != LABEL_REF)
1474: || (GET_CODE (insn) == JUMP_INSN
1475: && GET_CODE (body) == PARALLEL
1476: && GET_CODE (XVECEXP (body, 0, 0)) == SET
1477: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))
1478: new_block = 1;
1479: }
1.1 root 1480: break;
1481: }
1482:
1483: /* We have a real machine instruction as rtl. */
1484:
1485: body = PATTERN (insn);
1486:
1487: #ifdef HAVE_cc0
1488: /* Check for redundant test and compare instructions
1489: (when the condition codes are already set up as desired).
1490: This is done only when optimizing; if not optimizing,
1491: it should be possible for the user to alter a variable
1492: with the debugger in between statements
1493: and the next statement should reexamine the variable
1494: to compute the condition codes. */
1495:
1496: if (optimize
1497: && GET_CODE (body) == SET
1498: && GET_CODE (SET_DEST (body)) == CC0
1499: && insn != last_ignored_compare)
1500: {
1501: if (GET_CODE (SET_SRC (body)) == SUBREG)
1502: SET_SRC (body) = alter_subreg (SET_SRC (body));
1503: else if (GET_CODE (SET_SRC (body)) == COMPARE)
1504: {
1505: if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG)
1506: XEXP (SET_SRC (body), 0)
1507: = alter_subreg (XEXP (SET_SRC (body), 0));
1508: if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG)
1509: XEXP (SET_SRC (body), 1)
1510: = alter_subreg (XEXP (SET_SRC (body), 1));
1511: }
1512: if ((cc_status.value1 != 0
1513: && rtx_equal_p (SET_SRC (body), cc_status.value1))
1514: || (cc_status.value2 != 0
1515: && rtx_equal_p (SET_SRC (body), cc_status.value2)))
1516: {
1517: /* Don't delete insn if it has an addressing side-effect. */
1518: if (! FIND_REG_INC_NOTE (insn, 0)
1519: /* or if anything in it is volatile. */
1520: && ! volatile_refs_p (PATTERN (insn)))
1521: {
1522: /* We don't really delete the insn; just ignore it. */
1523: last_ignored_compare = insn;
1524: break;
1525: }
1526: }
1527: }
1528: #endif
1529:
1.1.1.3 root 1530: /* Following a conditional branch, we have a new basic block.
1531: But if we are inside a sequence, the new block starts after the
1532: last insn of the sequence. */
1533: if (profile_block_flag && final_sequence == 0
1534: && ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
1535: && GET_CODE (SET_SRC (body)) != LABEL_REF)
1536: || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL
1537: && GET_CODE (XVECEXP (body, 0, 0)) == SET
1538: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)))
1.1 root 1539: new_block = 1;
1540:
1541: #ifndef STACK_REGS
1542: /* Don't bother outputting obvious no-ops, even without -O.
1543: This optimization is fast and doesn't interfere with debugging.
1544: Don't do this if the insn is in a delay slot, since this
1545: will cause an improper number of delay insns to be written. */
1546: if (final_sequence == 0
1547: && prescan >= 0
1548: && GET_CODE (insn) == INSN && GET_CODE (body) == SET
1549: && GET_CODE (SET_SRC (body)) == REG
1550: && GET_CODE (SET_DEST (body)) == REG
1551: && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))
1552: break;
1553: #endif
1554:
1555: #ifdef HAVE_cc0
1556: /* If this is a conditional branch, maybe modify it
1557: if the cc's are in a nonstandard state
1558: so that it accomplishes the same thing that it would
1559: do straightforwardly if the cc's were set up normally. */
1560:
1561: if (cc_status.flags != 0
1562: && GET_CODE (insn) == JUMP_INSN
1563: && GET_CODE (body) == SET
1564: && SET_DEST (body) == pc_rtx
1565: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
1566: /* This is done during prescan; it is not done again
1567: in final scan when prescan has been done. */
1568: && prescan >= 0)
1569: {
1570: /* This function may alter the contents of its argument
1571: and clear some of the cc_status.flags bits.
1572: It may also return 1 meaning condition now always true
1573: or -1 meaning condition now always false
1574: or 2 meaning condition nontrivial but altered. */
1575: register int result = alter_cond (XEXP (SET_SRC (body), 0));
1576: /* If condition now has fixed value, replace the IF_THEN_ELSE
1577: with its then-operand or its else-operand. */
1578: if (result == 1)
1579: SET_SRC (body) = XEXP (SET_SRC (body), 1);
1580: if (result == -1)
1581: SET_SRC (body) = XEXP (SET_SRC (body), 2);
1582:
1583: /* The jump is now either unconditional or a no-op.
1584: If it has become a no-op, don't try to output it.
1585: (It would not be recognized.) */
1586: if (SET_SRC (body) == pc_rtx)
1587: {
1588: PUT_CODE (insn, NOTE);
1589: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
1590: NOTE_SOURCE_FILE (insn) = 0;
1591: break;
1592: }
1593: else if (GET_CODE (SET_SRC (body)) == RETURN)
1594: /* Replace (set (pc) (return)) with (return). */
1595: PATTERN (insn) = body = SET_SRC (body);
1596:
1597: /* Rerecognize the instruction if it has changed. */
1598: if (result != 0)
1599: INSN_CODE (insn) = -1;
1600: }
1601:
1602: /* Make same adjustments to instructions that examine the
1603: condition codes without jumping (if this machine has them). */
1604:
1605: if (cc_status.flags != 0
1606: && GET_CODE (body) == SET)
1607: {
1608: switch (GET_CODE (SET_SRC (body)))
1609: {
1610: case GTU:
1611: case GT:
1612: case LTU:
1613: case LT:
1614: case GEU:
1615: case GE:
1616: case LEU:
1617: case LE:
1618: case EQ:
1619: case NE:
1620: {
1621: register int result;
1622: if (XEXP (SET_SRC (body), 0) != cc0_rtx)
1623: break;
1624: result = alter_cond (SET_SRC (body));
1625: if (result == 1)
1626: validate_change (insn, &SET_SRC (body), const_true_rtx, 0);
1627: else if (result == -1)
1628: validate_change (insn, &SET_SRC (body), const0_rtx, 0);
1629: else if (result == 2)
1630: INSN_CODE (insn) = -1;
1631: }
1632: }
1633: }
1634: #endif
1635:
1636: /* Do machine-specific peephole optimizations if desired. */
1637:
1638: if (optimize && !flag_no_peephole && !nopeepholes)
1639: {
1640: rtx next = peephole (insn);
1641: /* When peepholing, if there were notes within the peephole,
1642: emit them before the peephole. */
1643: if (next != 0 && next != NEXT_INSN (insn))
1644: {
1645: rtx prev = PREV_INSN (insn);
1646: rtx note;
1647:
1648: for (note = NEXT_INSN (insn); note != next;
1649: note = NEXT_INSN (note))
1650: final_scan_insn (note, file, optimize, prescan, nopeepholes);
1651:
1652: /* In case this is prescan, put the notes
1653: in proper position for later rescan. */
1654: note = NEXT_INSN (insn);
1655: PREV_INSN (note) = prev;
1656: NEXT_INSN (prev) = note;
1657: NEXT_INSN (PREV_INSN (next)) = insn;
1658: PREV_INSN (insn) = PREV_INSN (next);
1659: NEXT_INSN (insn) = next;
1660: PREV_INSN (next) = insn;
1661: }
1662:
1663: /* PEEPHOLE might have changed this. */
1664: body = PATTERN (insn);
1665: }
1666:
1667: /* Try to recognize the instruction.
1668: If successful, verify that the operands satisfy the
1669: constraints for the instruction. Crash if they don't,
1670: since `reload' should have changed them so that they do. */
1671:
1672: insn_code_number = recog_memoized (insn);
1673: insn_extract (insn);
1674: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1675: {
1676: if (GET_CODE (recog_operand[i]) == SUBREG)
1677: recog_operand[i] = alter_subreg (recog_operand[i]);
1678: }
1679:
1.1.1.5 ! root 1680: for (i = 0; i < insn_n_dups[insn_code_number]; i++)
! 1681: {
! 1682: if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
! 1683: *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
! 1684: }
! 1685:
1.1 root 1686: #ifdef REGISTER_CONSTRAINTS
1687: if (! constrain_operands (insn_code_number, 1))
1688: fatal_insn_not_found (insn);
1689: #endif
1690:
1691: /* Some target machines need to prescan each insn before
1692: it is output. */
1693:
1694: #ifdef FINAL_PRESCAN_INSN
1695: FINAL_PRESCAN_INSN (insn, recog_operand,
1696: insn_n_operands[insn_code_number]);
1697: #endif
1698:
1699: #ifdef HAVE_cc0
1700: cc_prev_status = cc_status;
1701:
1702: /* Update `cc_status' for this instruction.
1703: The instruction's output routine may change it further.
1704: If the output routine for a jump insn needs to depend
1705: on the cc status, it should look at cc_prev_status. */
1706:
1707: NOTICE_UPDATE_CC (body, insn);
1708: #endif
1709:
1710: debug_insn = insn;
1711:
1712: /* If the proper template needs to be chosen by some C code,
1713: run that code and get the real template. */
1714:
1715: template = insn_template[insn_code_number];
1716: if (template == 0)
1717: {
1718: template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
1719:
1720: /* If the C code returns 0, it means that it is a jump insn
1721: which follows a deleted test insn, and that test insn
1722: needs to be reinserted. */
1723: if (template == 0)
1724: {
1725: if (prev_nonnote_insn (insn) != last_ignored_compare)
1726: abort ();
1727: new_block = 0;
1728: return prev_nonnote_insn (insn);
1729: }
1730: }
1731:
1732: /* If the template is the string "#", it means that this insn must
1733: be split. */
1734: if (template[0] == '#' && template[1] == '\0')
1735: {
1736: rtx new = try_split (body, insn, 0);
1737:
1738: /* If we didn't split the insn, go away. */
1739: if (new == insn && PATTERN (new) == body)
1740: abort ();
1741:
1742: new_block = 0;
1743: return new;
1744: }
1745:
1746: if (prescan > 0)
1747: break;
1748:
1749: /* Output assembler code from the template. */
1750:
1751: output_asm_insn (template, recog_operand);
1752:
1753: #if 0
1754: /* It's not at all clear why we did this and doing so interferes
1755: with tests we'd like to do to use REG_WAS_0 notes, so let's try
1756: with this out. */
1757:
1758: /* Mark this insn as having been output. */
1759: INSN_DELETED_P (insn) = 1;
1760: #endif
1761:
1762: debug_insn = 0;
1763: }
1764: }
1765: return NEXT_INSN (insn);
1766: }
1767:
1768: /* Output debugging info to the assembler file FILE
1769: based on the NOTE-insn INSN, assumed to be a line number. */
1770:
1771: static void
1772: output_source_line (file, insn)
1773: FILE *file;
1774: rtx insn;
1775: {
1776: char ltext_label_name[100];
1777: register char *filename = NOTE_SOURCE_FILE (insn);
1778:
1779: last_linenum = NOTE_LINE_NUMBER (insn);
1780:
1781: if (write_symbols != NO_DEBUG)
1782: {
1783: #ifdef SDB_DEBUGGING_INFO
1784: if (write_symbols == SDB_DEBUG
1785: #if 0 /* People like having line numbers even in wrong file! */
1786: /* COFF can't handle multiple source files--lose, lose. */
1787: && !strcmp (filename, main_input_filename)
1788: #endif
1789: /* COFF relative line numbers must be positive. */
1790: && last_linenum > sdb_begin_function_line)
1791: {
1792: #ifdef ASM_OUTPUT_SOURCE_LINE
1793: ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
1794: #else
1795: fprintf (file, "\t.ln\t%d\n",
1796: ((sdb_begin_function_line > -1)
1797: ? last_linenum - sdb_begin_function_line : 1));
1798: #endif
1799: }
1800: #endif
1801:
1.1.1.2 root 1802: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
1803: if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
1.1.1.4 root 1804: dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn));
1.1.1.2 root 1805: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
1.1 root 1806:
1807: #ifdef DWARF_DEBUGGING_INFO
1808: if (write_symbols == DWARF_DEBUG)
1809: dwarfout_line (filename, NOTE_LINE_NUMBER (insn));
1810: #endif
1811: }
1812: }
1813:
1814: /* If X is a SUBREG, replace it with a REG or a MEM,
1815: based on the thing it is a subreg of. */
1816:
1817: rtx
1818: alter_subreg (x)
1819: register rtx x;
1820: {
1821: register rtx y = SUBREG_REG (x);
1822: if (GET_CODE (y) == SUBREG)
1823: y = alter_subreg (y);
1824:
1825: if (GET_CODE (y) == REG)
1826: {
1827: /* If the containing reg really gets a hard reg, so do we. */
1828: PUT_CODE (x, REG);
1829: REGNO (x) = REGNO (y) + SUBREG_WORD (x);
1830: }
1831: else if (GET_CODE (y) == MEM)
1832: {
1833: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
1834: #if BYTES_BIG_ENDIAN
1835: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
1836: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
1837: #endif
1838: PUT_CODE (x, MEM);
1839: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
1840: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
1841: }
1842:
1843: return x;
1844: }
1845:
1846: /* Do alter_subreg on all the SUBREGs contained in X. */
1847:
1848: static rtx
1849: walk_alter_subreg (x)
1850: rtx x;
1851: {
1852: switch (GET_CODE (x))
1853: {
1854: case PLUS:
1855: case MULT:
1856: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
1857: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));
1858: break;
1859:
1860: case MEM:
1861: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
1862: break;
1863:
1864: case SUBREG:
1865: return alter_subreg (x);
1866: }
1867:
1868: return x;
1869: }
1870:
1871: #ifdef HAVE_cc0
1872:
1873: /* Given BODY, the body of a jump instruction, alter the jump condition
1874: as required by the bits that are set in cc_status.flags.
1875: Not all of the bits there can be handled at this level in all cases.
1876:
1877: The value is normally 0.
1878: 1 means that the condition has become always true.
1879: -1 means that the condition has become always false.
1880: 2 means that COND has been altered. */
1881:
1882: static int
1883: alter_cond (cond)
1884: register rtx cond;
1885: {
1886: int value = 0;
1887:
1888: if (cc_status.flags & CC_REVERSED)
1889: {
1890: value = 2;
1891: PUT_CODE (cond, swap_condition (GET_CODE (cond)));
1892: }
1893:
1894: if (cc_status.flags & CC_INVERTED)
1895: {
1896: value = 2;
1897: PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
1898: }
1899:
1900: if (cc_status.flags & CC_NOT_POSITIVE)
1901: switch (GET_CODE (cond))
1902: {
1903: case LE:
1904: case LEU:
1905: case GEU:
1906: /* Jump becomes unconditional. */
1907: return 1;
1908:
1909: case GT:
1910: case GTU:
1911: case LTU:
1912: /* Jump becomes no-op. */
1913: return -1;
1914:
1915: case GE:
1916: PUT_CODE (cond, EQ);
1917: value = 2;
1918: break;
1919:
1920: case LT:
1921: PUT_CODE (cond, NE);
1922: value = 2;
1923: break;
1924: }
1925:
1926: if (cc_status.flags & CC_NOT_NEGATIVE)
1927: switch (GET_CODE (cond))
1928: {
1929: case GE:
1930: case GEU:
1931: /* Jump becomes unconditional. */
1932: return 1;
1933:
1934: case LT:
1935: case LTU:
1936: /* Jump becomes no-op. */
1937: return -1;
1938:
1939: case LE:
1940: case LEU:
1941: PUT_CODE (cond, EQ);
1942: value = 2;
1943: break;
1944:
1945: case GT:
1946: case GTU:
1947: PUT_CODE (cond, NE);
1948: value = 2;
1949: break;
1950: }
1951:
1952: if (cc_status.flags & CC_NO_OVERFLOW)
1953: switch (GET_CODE (cond))
1954: {
1955: case GEU:
1956: /* Jump becomes unconditional. */
1957: return 1;
1958:
1959: case LEU:
1960: PUT_CODE (cond, EQ);
1961: value = 2;
1962: break;
1963:
1964: case GTU:
1965: PUT_CODE (cond, NE);
1966: value = 2;
1967: break;
1968:
1969: case LTU:
1970: /* Jump becomes no-op. */
1971: return -1;
1972: }
1973:
1974: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
1975: switch (GET_CODE (cond))
1976: {
1977: case LE:
1978: case LEU:
1979: case GE:
1980: case GEU:
1981: case LT:
1982: case LTU:
1983: case GT:
1984: case GTU:
1985: abort ();
1986:
1987: case NE:
1988: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
1989: value = 2;
1990: break;
1991:
1992: case EQ:
1993: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
1994: value = 2;
1995: break;
1996: }
1.1.1.4 root 1997:
1998: if (cc_status.flags & CC_NOT_SIGNED)
1999: /* The flags are valid if signed condition operators are converted
2000: to unsigned. */
2001: switch (GET_CODE (cond))
2002: {
2003: case LE:
2004: PUT_CODE (cond, LEU);
2005: value = 2;
2006: break;
2007:
2008: case LT:
2009: PUT_CODE (cond, LTU);
2010: value = 2;
2011: break;
2012:
2013: case GT:
2014: PUT_CODE (cond, GTU);
2015: value = 2;
2016: break;
2017:
2018: case GE:
2019: PUT_CODE (cond, GEU);
2020: value = 2;
2021: break;
2022: }
2023:
1.1 root 2024: return value;
2025: }
2026: #endif
2027:
2028: /* Report inconsistency between the assembler template and the operands.
2029: In an `asm', it's the user's fault; otherwise, the compiler's fault. */
2030:
2031: void
2032: output_operand_lossage (str)
2033: char *str;
2034: {
2035: if (this_is_asm_operands)
2036: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str);
2037: else
2038: abort ();
2039: }
2040:
2041: /* Output of assembler code from a template, and its subroutines. */
2042:
2043: /* Output text from TEMPLATE to the assembler output file,
2044: obeying %-directions to substitute operands taken from
2045: the vector OPERANDS.
2046:
2047: %N (for N a digit) means print operand N in usual manner.
2048: %lN means require operand N to be a CODE_LABEL or LABEL_REF
2049: and print the label name with no punctuation.
2050: %cN means require operand N to be a constant
2051: and print the constant expression with no punctuation.
2052: %aN means expect operand N to be a memory address
2053: (not a memory reference!) and print a reference
2054: to that address.
2055: %nN means expect operand N to be a constant
2056: and print a constant expression for minus the value
2057: of the operand, with no other punctuation. */
2058:
2059: void
2060: output_asm_insn (template, operands)
2061: char *template;
2062: rtx *operands;
2063: {
2064: register char *p;
2065: register int c;
2066:
2067: /* An insn may return a null string template
2068: in a case where no assembler code is needed. */
2069: if (*template == 0)
2070: return;
2071:
2072: p = template;
2073: putc ('\t', asm_out_file);
2074:
2075: #ifdef ASM_OUTPUT_OPCODE
2076: ASM_OUTPUT_OPCODE (asm_out_file, p);
2077: #endif
2078:
2079: while (c = *p++)
2080: {
2081: #ifdef ASM_OUTPUT_OPCODE
2082: if (c == '\n')
2083: {
2084: putc (c, asm_out_file);
2085: while ((c = *p) == '\t')
2086: {
2087: putc (c, asm_out_file);
2088: p++;
2089: }
2090: ASM_OUTPUT_OPCODE (asm_out_file, p);
2091: }
2092: else
2093: #endif
2094: if (c != '%')
2095: putc (c, asm_out_file);
2096: else
2097: {
2098: /* %% outputs a single %. */
2099: if (*p == '%')
2100: {
2101: p++;
2102: putc (c, asm_out_file);
2103: }
2104: /* %= outputs a number which is unique to each insn in the entire
2105: compilation. This is useful for making local labels that are
2106: referred to more than once in a given insn. */
2107: else if (*p == '=')
1.1.1.4 root 2108: {
2109: p++;
2110: fprintf (asm_out_file, "%d", insn_counter);
2111: }
1.1 root 2112: /* % followed by a letter and some digits
2113: outputs an operand in a special way depending on the letter.
2114: Letters `acln' are implemented directly.
2115: Other letters are passed to `output_operand' so that
2116: the PRINT_OPERAND macro can define them. */
2117: else if ((*p >= 'a' && *p <= 'z')
2118: || (*p >= 'A' && *p <= 'Z'))
2119: {
2120: int letter = *p++;
2121: c = atoi (p);
2122:
2123: if (! (*p >= '0' && *p <= '9'))
2124: output_operand_lossage ("operand number missing after %-letter");
2125: else if (this_is_asm_operands && c >= (unsigned) insn_noperands)
2126: output_operand_lossage ("operand number out of range");
2127: else if (letter == 'l')
2128: output_asm_label (operands[c]);
2129: else if (letter == 'a')
2130: output_address (operands[c]);
2131: else if (letter == 'c')
2132: {
2133: if (CONSTANT_ADDRESS_P (operands[c]))
2134: output_addr_const (asm_out_file, operands[c]);
2135: else
2136: output_operand (operands[c], 'c');
2137: }
2138: else if (letter == 'n')
2139: {
2140: if (GET_CODE (operands[c]) == CONST_INT)
1.1.1.4 root 2141: fprintf (asm_out_file,
2142: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
2143: "%d",
2144: #else
2145: "%ld",
2146: #endif
2147: - INTVAL (operands[c]));
1.1 root 2148: else
2149: {
2150: putc ('-', asm_out_file);
2151: output_addr_const (asm_out_file, operands[c]);
2152: }
2153: }
2154: else
2155: output_operand (operands[c], letter);
2156:
2157: while ((c = *p) >= '0' && c <= '9') p++;
2158: }
2159: /* % followed by a digit outputs an operand the default way. */
2160: else if (*p >= '0' && *p <= '9')
2161: {
2162: c = atoi (p);
2163: if (this_is_asm_operands && c >= (unsigned) insn_noperands)
2164: output_operand_lossage ("operand number out of range");
2165: else
2166: output_operand (operands[c], 0);
2167: while ((c = *p) >= '0' && c <= '9') p++;
2168: }
2169: /* % followed by punctuation: output something for that
2170: punctuation character alone, with no operand.
2171: The PRINT_OPERAND macro decides what is actually done. */
2172: #ifdef PRINT_OPERAND_PUNCT_VALID_P
2173: else if (PRINT_OPERAND_PUNCT_VALID_P (*p))
1.1.1.4 root 2174: output_operand (NULL_RTX, *p++);
1.1 root 2175: #endif
2176: else
2177: output_operand_lossage ("invalid %%-code");
2178: }
2179: }
2180:
2181: if (flag_print_asm_name)
2182: {
2183: /* Annotate the assembly with a comment describing the pattern and
2184: alternative used. */
2185: if (debug_insn)
2186: {
2187: register int num = INSN_CODE (debug_insn);
2188: fprintf (asm_out_file, " %s %d %s",
2189: ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);
2190: if (insn_n_alternatives[num] > 1)
2191: fprintf (asm_out_file, "/%d", which_alternative + 1);
2192:
2193: /* Clear this so only the first assembler insn
2194: of any rtl insn will get the special comment for -dp. */
2195: debug_insn = 0;
2196: }
2197: }
2198:
2199: putc ('\n', asm_out_file);
2200: }
2201:
2202: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
2203:
2204: void
2205: output_asm_label (x)
2206: rtx x;
2207: {
2208: char buf[256];
2209:
2210: if (GET_CODE (x) == LABEL_REF)
2211: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
2212: else if (GET_CODE (x) == CODE_LABEL)
2213: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2214: else
2215: output_operand_lossage ("`%l' operand isn't a label");
2216:
2217: assemble_name (asm_out_file, buf);
2218: }
2219:
2220: /* Print operand X using machine-dependent assembler syntax.
2221: The macro PRINT_OPERAND is defined just to control this function.
2222: CODE is a non-digit that preceded the operand-number in the % spec,
2223: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char
2224: between the % and the digits.
2225: When CODE is a non-letter, X is 0.
2226:
2227: The meanings of the letters are machine-dependent and controlled
2228: by PRINT_OPERAND. */
2229:
2230: static void
2231: output_operand (x, code)
2232: rtx x;
2233: int code;
2234: {
2235: if (x && GET_CODE (x) == SUBREG)
2236: x = alter_subreg (x);
1.1.1.4 root 2237:
2238: /* If X is a pseudo-register, abort now rather than writing trash to the
2239: assembler file. */
2240:
2241: if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
2242: abort ();
2243:
1.1 root 2244: PRINT_OPERAND (asm_out_file, x, code);
2245: }
2246:
2247: /* Print a memory reference operand for address X
2248: using machine-dependent assembler syntax.
2249: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */
2250:
2251: void
2252: output_address (x)
2253: rtx x;
2254: {
2255: walk_alter_subreg (x);
2256: PRINT_OPERAND_ADDRESS (asm_out_file, x);
2257: }
2258:
2259: /* Print an integer constant expression in assembler syntax.
2260: Addition and subtraction are the only arithmetic
2261: that may appear in these expressions. */
2262:
2263: void
2264: output_addr_const (file, x)
2265: FILE *file;
2266: rtx x;
2267: {
2268: char buf[256];
2269:
2270: restart:
2271: switch (GET_CODE (x))
2272: {
2273: case PC:
2274: if (flag_pic)
2275: putc ('.', file);
2276: else
2277: abort ();
2278: break;
2279:
2280: case SYMBOL_REF:
2281: assemble_name (file, XSTR (x, 0));
2282: break;
2283:
2284: case LABEL_REF:
2285: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1.1.1.4 root 2286: assemble_name (file, buf);
1.1 root 2287: break;
2288:
2289: case CODE_LABEL:
2290: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1.1.1.4 root 2291: assemble_name (file, buf);
1.1 root 2292: break;
2293:
2294: case CONST_INT:
1.1.1.4 root 2295: fprintf (file,
2296: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
2297: "%d",
2298: #else
2299: "%ld",
2300: #endif
2301: INTVAL (x));
1.1 root 2302: break;
2303:
2304: case CONST:
2305: /* This used to output parentheses around the expression,
2306: but that does not work on the 386 (either ATT or BSD assembler). */
2307: output_addr_const (file, XEXP (x, 0));
2308: break;
2309:
2310: case CONST_DOUBLE:
2311: if (GET_MODE (x) == VOIDmode)
2312: {
1.1.1.4 root 2313: /* We can use %d if the number is one word and positive. */
1.1.1.5 ! root 2314: if (CONST_DOUBLE_HIGH (x))
1.1.1.4 root 2315: fprintf (file,
2316: #if HOST_BITS_PER_WIDE_INT == 64
2317: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
1.1.1.5 ! root 2318: "0x%lx%016lx",
1.1.1.4 root 2319: #else
1.1.1.5 ! root 2320: "0x%x%016x",
1.1.1.4 root 2321: #endif
2322: #else
2323: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
1.1.1.5 ! root 2324: "0x%lx%08lx",
1.1.1.4 root 2325: #else
1.1.1.5 ! root 2326: "0x%x%08x",
1.1.1.4 root 2327: #endif
2328: #endif
1.1 root 2329: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
1.1.1.5 ! root 2330: else if (CONST_DOUBLE_LOW (x) < 0)
! 2331: fprintf (file,
! 2332: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
! 2333: "0x%x",
! 2334: #else
! 2335: "0x%lx",
! 2336: #endif
! 2337: CONST_DOUBLE_LOW (x));
1.1 root 2338: else
1.1.1.4 root 2339: fprintf (file,
2340: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
2341: "%d",
2342: #else
2343: "%ld",
2344: #endif
2345: CONST_DOUBLE_LOW (x));
1.1 root 2346: }
2347: else
2348: /* We can't handle floating point constants;
2349: PRINT_OPERAND must handle them. */
2350: output_operand_lossage ("floating constant misused");
2351: break;
2352:
2353: case PLUS:
2354: /* Some assemblers need integer constants to appear last (eg masm). */
2355: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2356: {
2357: output_addr_const (file, XEXP (x, 1));
2358: if (INTVAL (XEXP (x, 0)) >= 0)
2359: fprintf (file, "+");
2360: output_addr_const (file, XEXP (x, 0));
2361: }
2362: else
2363: {
2364: output_addr_const (file, XEXP (x, 0));
2365: if (INTVAL (XEXP (x, 1)) >= 0)
2366: fprintf (file, "+");
2367: output_addr_const (file, XEXP (x, 1));
2368: }
2369: break;
2370:
2371: case MINUS:
1.1.1.4 root 2372: /* Avoid outputting things like x-x or x+5-x,
2373: since some assemblers can't handle that. */
2374: x = simplify_subtraction (x);
2375: if (GET_CODE (x) != MINUS)
2376: goto restart;
2377:
1.1 root 2378: output_addr_const (file, XEXP (x, 0));
2379: fprintf (file, "-");
1.1.1.4 root 2380: if (GET_CODE (XEXP (x, 1)) == CONST_INT
2381: && INTVAL (XEXP (x, 1)) < 0)
2382: {
2383: fprintf (file, ASM_OPEN_PAREN);
2384: output_addr_const (file, XEXP (x, 1));
2385: fprintf (file, ASM_CLOSE_PAREN);
2386: }
2387: else
2388: output_addr_const (file, XEXP (x, 1));
2389: break;
2390:
2391: case ZERO_EXTEND:
2392: case SIGN_EXTEND:
2393: output_addr_const (file, XEXP (x, 0));
1.1 root 2394: break;
2395:
2396: default:
2397: output_operand_lossage ("invalid expression as operand");
2398: }
2399: }
2400:
2401: /* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
2402: %R prints the value of REGISTER_PREFIX.
2403: %L prints the value of LOCAL_LABEL_PREFIX.
2404: %U prints the value of USER_LABEL_PREFIX.
2405: %I prints the value of IMMEDIATE_PREFIX.
1.1.1.2 root 2406: %O runs ASM_OUTPUT_OPCODE to transform what follows in the string.
1.1 root 2407: Also supported are %d, %x, %s, %e, %f, %g and %%. */
2408:
2409: void
2410: asm_fprintf (va_alist)
2411: va_dcl
2412: {
2413: va_list argptr;
2414: FILE *file;
2415: char buf[10];
2416: char *p, *q, c;
2417:
2418: va_start (argptr);
2419:
2420: file = va_arg (argptr, FILE *);
2421: p = va_arg (argptr, char *);
2422: buf[0] = '%';
2423:
2424: while (c = *p++)
2425: switch (c)
2426: {
2427: case '%':
2428: c = *p++;
2429: q = &buf[1];
2430: while ((c >= '0' && c <= '9') || c == '.')
2431: {
2432: *q++ = c;
2433: c = *p++;
2434: }
2435: switch (c)
2436: {
2437: case '%':
2438: fprintf (file, "%%");
2439: break;
2440:
2441: case 'd': case 'i': case 'u':
2442: case 'x': case 'p': case 'X':
2443: case 'o':
2444: *q++ = c;
2445: *q = 0;
2446: fprintf (file, buf, va_arg (argptr, int));
2447: break;
2448:
2449: case 'e':
2450: case 'f':
2451: case 'g':
2452: *q++ = c;
2453: *q = 0;
2454: fprintf (file, buf, va_arg (argptr, double));
2455: break;
2456:
2457: case 's':
2458: *q++ = c;
2459: *q = 0;
2460: fprintf (file, buf, va_arg (argptr, char *));
2461: break;
2462:
1.1.1.2 root 2463: case 'O':
2464: #ifdef ASM_OUTPUT_OPCODE
2465: ASM_OUTPUT_OPCODE (asm_out_file, p);
2466: #endif
2467: break;
2468:
1.1 root 2469: case 'R':
2470: #ifdef REGISTER_PREFIX
2471: fprintf (file, "%s", REGISTER_PREFIX);
2472: #endif
2473: break;
2474:
2475: case 'I':
2476: #ifdef IMMEDIATE_PREFIX
2477: fprintf (file, "%s", IMMEDIATE_PREFIX);
2478: #endif
2479: break;
2480:
2481: case 'L':
2482: #ifdef LOCAL_LABEL_PREFIX
2483: fprintf (file, "%s", LOCAL_LABEL_PREFIX);
2484: #endif
2485: break;
2486:
2487: case 'U':
2488: #ifdef USER_LABEL_PREFIX
2489: fprintf (file, "%s", USER_LABEL_PREFIX);
2490: #endif
2491: break;
2492:
2493: default:
2494: abort ();
2495: }
2496: break;
2497:
2498: default:
2499: fputc (c, file);
2500: }
2501: }
2502:
2503: /* Split up a CONST_DOUBLE or integer constant rtx
2504: into two rtx's for single words,
2505: storing in *FIRST the word that comes first in memory in the target
2506: and in *SECOND the other. */
2507:
2508: void
2509: split_double (value, first, second)
2510: rtx value;
2511: rtx *first, *second;
2512: {
2513: if (GET_CODE (value) == CONST_INT)
2514: {
2515: /* The rule for using CONST_INT for a wider mode
2516: is that we regard the value as signed.
2517: So sign-extend it. */
2518: rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx);
2519: #if WORDS_BIG_ENDIAN
2520: *first = high;
2521: *second = value;
2522: #else
2523: *first = value;
2524: *second = high;
2525: #endif
2526: }
2527: else if (GET_CODE (value) != CONST_DOUBLE)
2528: {
2529: #if WORDS_BIG_ENDIAN
2530: *first = const0_rtx;
2531: *second = value;
2532: #else
2533: *first = value;
2534: *second = const0_rtx;
2535: #endif
2536: }
2537: else if (GET_MODE (value) == VOIDmode
2538: /* This is the old way we did CONST_DOUBLE integers. */
2539: || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT)
2540: {
2541: /* In an integer, the words are defined as most and least significant.
2542: So order them by the target's convention. */
2543: #if WORDS_BIG_ENDIAN
1.1.1.4 root 2544: *first = GEN_INT (CONST_DOUBLE_HIGH (value));
2545: *second = GEN_INT (CONST_DOUBLE_LOW (value));
1.1 root 2546: #else
1.1.1.4 root 2547: *first = GEN_INT (CONST_DOUBLE_LOW (value));
2548: *second = GEN_INT (CONST_DOUBLE_HIGH (value));
1.1 root 2549: #endif
2550: }
2551: else
2552: {
1.1.1.5 ! root 2553: #ifdef REAL_ARITHMETIC
! 2554: REAL_VALUE_TYPE r; HOST_WIDE_INT l[2];
! 2555: REAL_VALUE_FROM_CONST_DOUBLE (r, value);
! 2556: REAL_VALUE_TO_TARGET_DOUBLE (r, l);
! 2557: *first = GEN_INT (l[0]);
! 2558: *second = GEN_INT (l[1]);
! 2559: #else
1.1 root 2560: if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1.1.1.4 root 2561: || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
1.1 root 2562: && ! flag_pretend_float)
2563: abort ();
2564:
2565: #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN
2566: /* Host and target agree => no need to swap. */
1.1.1.4 root 2567: *first = GEN_INT (CONST_DOUBLE_LOW (value));
2568: *second = GEN_INT (CONST_DOUBLE_HIGH (value));
1.1 root 2569: #else
1.1.1.4 root 2570: *second = GEN_INT (CONST_DOUBLE_LOW (value));
2571: *first = GEN_INT (CONST_DOUBLE_HIGH (value));
1.1 root 2572: #endif
1.1.1.5 ! root 2573: #endif /* no REAL_ARITHMETIC */
1.1 root 2574: }
2575: }
2576:
2577: /* Return nonzero if this function has no function calls. */
2578:
2579: int
2580: leaf_function_p ()
2581: {
2582: rtx insn;
2583:
2584: if (profile_flag || profile_block_flag)
2585: return 0;
2586:
2587: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2588: {
2589: if (GET_CODE (insn) == CALL_INSN)
2590: return 0;
2591: if (GET_CODE (insn) == INSN
2592: && GET_CODE (PATTERN (insn)) == SEQUENCE
2593: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)
2594: return 0;
2595: }
2596: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1))
2597: {
2598: if (GET_CODE (XEXP (insn, 0)) == CALL_INSN)
2599: return 0;
2600: if (GET_CODE (XEXP (insn, 0)) == INSN
2601: && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE
2602: && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN)
2603: return 0;
2604: }
2605:
2606: return 1;
2607: }
2608:
2609: /* On some machines, a function with no call insns
2610: can run faster if it doesn't create its own register window.
2611: When output, the leaf function should use only the "output"
2612: registers. Ordinarily, the function would be compiled to use
2613: the "input" registers to find its arguments; it is a candidate
2614: for leaf treatment if it uses only the "input" registers.
2615: Leaf function treatment means renumbering so the function
2616: uses the "output" registers instead. */
2617:
2618: #ifdef LEAF_REGISTERS
2619:
2620: static char permitted_reg_in_leaf_functions[] = LEAF_REGISTERS;
2621:
2622: /* Return 1 if this function uses only the registers that can be
2623: safely renumbered. */
2624:
2625: int
2626: only_leaf_regs_used ()
2627: {
2628: int i;
2629:
2630: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2631: {
1.1.1.4 root 2632: if ((regs_ever_live[i] || global_regs[i])
2633: && ! permitted_reg_in_leaf_functions[i])
1.1 root 2634: return 0;
2635: }
2636: return 1;
2637: }
2638:
2639: /* Scan all instructions and renumber all registers into those
2640: available in leaf functions. */
2641:
2642: static void
2643: leaf_renumber_regs (first)
2644: rtx first;
2645: {
2646: rtx insn;
2647:
2648: /* Renumber only the actual patterns.
2649: The reg-notes can contain frame pointer refs,
2650: and renumbering them could crash, and should not be needed. */
2651: for (insn = first; insn; insn = NEXT_INSN (insn))
2652: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
2653: leaf_renumber_regs_insn (PATTERN (insn));
2654: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1))
2655: if (GET_RTX_CLASS (GET_CODE (XEXP (insn, 0))) == 'i')
2656: leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0)));
2657: }
2658:
2659: /* Scan IN_RTX and its subexpressions, and renumber all regs into those
2660: available in leaf functions. */
2661:
2662: void
2663: leaf_renumber_regs_insn (in_rtx)
2664: register rtx in_rtx;
2665: {
2666: register int i, j;
2667: register char *format_ptr;
2668:
2669: if (in_rtx == 0)
2670: return;
2671:
2672: /* Renumber all input-registers into output-registers.
2673: renumbered_regs would be 1 for an output-register;
2674: they */
2675:
2676: if (GET_CODE (in_rtx) == REG)
2677: {
2678: int newreg;
2679:
2680: /* Don't renumber the same reg twice. */
2681: if (in_rtx->used)
2682: return;
2683:
2684: newreg = REGNO (in_rtx);
1.1.1.2 root 2685: /* Don't try to renumber pseudo regs. It is possible for a pseudo reg
1.1 root 2686: to reach here as part of a REG_NOTE. */
2687: if (newreg >= FIRST_PSEUDO_REGISTER)
2688: {
2689: in_rtx->used = 1;
2690: return;
2691: }
2692: newreg = LEAF_REG_REMAP (newreg);
2693: if (newreg < 0)
2694: abort ();
2695: regs_ever_live[REGNO (in_rtx)] = 0;
2696: regs_ever_live[newreg] = 1;
2697: REGNO (in_rtx) = newreg;
2698: in_rtx->used = 1;
2699: }
2700:
2701: if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i')
2702: {
2703: /* Inside a SEQUENCE, we find insns.
2704: Renumber just the patterns of these insns,
2705: just as we do for the top-level insns. */
2706: leaf_renumber_regs_insn (PATTERN (in_rtx));
2707: return;
2708: }
2709:
2710: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
2711:
2712: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
2713: switch (*format_ptr++)
2714: {
2715: case 'e':
2716: leaf_renumber_regs_insn (XEXP (in_rtx, i));
2717: break;
2718:
2719: case 'E':
2720: if (NULL != XVEC (in_rtx, i))
2721: {
2722: for (j = 0; j < XVECLEN (in_rtx, i); j++)
2723: leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j));
2724: }
2725: break;
2726:
2727: case 'S':
2728: case 's':
2729: case '0':
2730: case 'i':
1.1.1.4 root 2731: case 'w':
1.1 root 2732: case 'n':
2733: case 'u':
2734: break;
2735:
2736: default:
2737: abort ();
2738: }
2739: }
2740: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.