📄 rtl.c
字号:
/* Allocate, read and print RTL for C-Compiler Copyright (C) 1987, 1988 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "config.h"#include <ctype.h>#include <stdio.h>#include "rtl.h"#include "obstack.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern int xmalloc ();extern void free ();/* Obstack used for allocating RTL objects. Between functions, this is the permanent_obstack. While parsing and expanding a function, this is maybepermanent_obstack so we can save it if it is an inline function. During optimization and output, this is temporary_obstack. */extern struct obstack *rtl_obstack;#define MIN(x,y) ((x < y) ? x : y)extern long ftell();/* Indexed by rtx code, gives number of operands for an rtx with that code. Does NOT include rtx header data (code and links). This array is initialized in init_rtl. */int rtx_length[NUM_RTX_CODE + 1];/* Indexed by rtx code, gives the name of that kind of rtx, as a C string. */#define DEF_RTL_EXPR(ENUM, NAME, FORMAT) NAME ,char *rtx_name[] = {#include "rtl.def" /* rtl expressions are documented here */};#undef DEF_RTL_EXPR/* Indexed by machine mode, gives the name of that machine mode. This name does not include the letters "mode". */#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) NAME,char *mode_name[] = {#include "machmode.def"};#undef DEF_MACHMODE/* Indexed by machine mode, gives the length of the mode, in bytes. GET_MODE_CLASS uses this. */#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) CLASS,enum mode_class mode_class[] = {#include "machmode.def"};#undef DEF_MACHMODE/* Indexed by machine mode, gives the length of the mode, in bytes. GET_MODE_SIZE uses this. */#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \ (SIZE*UNITS_PER_WORD+3)/4,int mode_size[] = {#include "machmode.def"};#undef DEF_MACHMODE/* Indexed by machine mode, gives the length of the mode's subunit. GET_MODE_UNIT_SIZE uses this. */#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \ (UNIT*UNITS_PER_WORD+3)/4,int mode_unit_size[] = {#include "machmode.def" /* machine modes are documented here */};#undef DEF_MACHMODE/* Indexed by machine mode, gives next wider natural mode (QI -> HI -> SI -> DI, etc.) Widening multiply instructions use this. */#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \ (enum machine_mode) WIDER,enum machine_mode mode_wider_mode[] = {#include "machmode.def" /* machine modes are documented here */};#undef DEF_MACHMODE/* Indexed by rtx code, gives a sequence of operand-types for rtx's of that code. The sequence is a C string in which each charcter describes one operand. */char *rtx_format[] = { /* "*" undefined. can cause a warning message "0" field is unused (or used in a phase-dependent manner) prints nothing "i" an integer prints the integer "s" a pointer to a string prints the string "S" like "s", but optional: the containing rtx may end before this operand "e" a pointer to an rtl expression prints the expression "E" a pointer to a vector that points to a number of rtl expressions prints a list of the rtl expressions "u" a pointer to another insn prints the uid of the insn. */#define DEF_RTL_EXPR(ENUM, NAME, FORMAT) FORMAT ,#include "rtl.def" /* rtl expressions are defined here */#undef DEF_RTL_EXPR};/* Names for kinds of NOTEs and REG_NOTEs. */char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED", "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END", "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END", "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP", "NOTE_INSN_LOOP_CONT" };char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0", "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL", "REG_NONNEG", "REG_UNSET" };/* Allocate an rtx vector of N elements. Store the length, and initialize all elements to zero. */rtvecrtvec_alloc (n) int n;{ rtvec rt; int i; rt = (rtvec) obstack_alloc (rtl_obstack, sizeof (struct rtvec_def) + (( n - 1) * sizeof (rtunion))); /* clear out the vector */ PUT_NUM_ELEM(rt, n); for (i=0; i < n; i++) rt->elem[i].rtvec = NULL; /* @@ not portable due to rtunion */ return rt;}/* Allocate an rtx of code CODE. The CODE is stored in the rtx; all the rest is initialized to zero. */rtxrtx_alloc (code) RTX_CODE code;{ rtx rt; register int nelts = GET_RTX_LENGTH (code); register int length = sizeof (struct rtx_def) + (nelts - 1) * sizeof (rtunion); rt = (rtx) obstack_alloc (rtl_obstack, length); * (int *) rt = 0; PUT_CODE (rt, code); return rt;}/* Create a new copy of an rtx. Recursively copies the operands of the rtx, except for those few rtx codes that are sharable. */rtxcopy_rtx (orig) register rtx orig;{ register rtx copy; register int i, j; register RTX_CODE code; register char *format_ptr; code = GET_CODE (orig); switch (code) { case REG: case QUEUED: case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: case CODE_LABEL: case PC: case CC0: return orig; } copy = rtx_alloc (code); PUT_MODE (copy, GET_MODE (orig)); copy->in_struct = orig->in_struct; copy->volatil = orig->volatil; copy->unchanging = orig->unchanging; copy->integrated = orig->integrated; format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) { switch (*format_ptr++) { case 'e': XEXP (copy, i) = XEXP (orig, i); if (XEXP (orig, i) != NULL) XEXP (copy, i) = copy_rtx (XEXP (orig, i)); break; case 'E': XVEC (copy, i) = XVEC (orig, i); if (XVEC (orig, i) != NULL) { XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); for (j = 0; j < XVECLEN (copy, i); j++) XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); } break; default: XINT (copy, i) = XINT (orig, i); break; } } return copy;}/* Printing rtl for debugging dumps. */static FILE *outfile;char spaces[] = " ";static int sawclose = 0;/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */static voidprint_rtx (in_rtx) register rtx in_rtx;{ static int indent; register int i, j; register char *format_ptr; if (sawclose) { fprintf (outfile, "\n%s", (spaces + (sizeof spaces - indent * 2))); sawclose = 0; } if (in_rtx == 0) { fprintf (outfile, "(nil)"); sawclose = 1; return; } /* print name of expression code */ fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); if (in_rtx->in_struct) fprintf (outfile, "/s"); if (in_rtx->volatil) fprintf (outfile, "/v"); if (in_rtx->unchanging) fprintf (outfile, "/u"); if (in_rtx->integrated) fprintf (outfile, "/i"); if (GET_MODE (in_rtx) != VOIDmode) { /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST) fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx))); else fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); } format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) switch (*format_ptr++) { case 'S': case 's': if (XSTR (in_rtx, i) == 0) fprintf (outfile, " \"\""); else fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i)); sawclose = 1; break; /* 0 indicates a field for internal use that should not be printed. */ case '0': break; case 'e': indent += 2; if (!sawclose) fprintf (outfile, " "); print_rtx (XEXP (in_rtx, i)); indent -= 2; break; case 'E': indent += 2; if (sawclose) { fprintf (outfile, "\n%s", (spaces + (sizeof spaces - indent * 2))); sawclose = 0; } fprintf (outfile, "[ "); if (NULL != XVEC (in_rtx, i)) { indent += 2; if (XVECLEN (in_rtx, i)) sawclose = 1; for (j = 0; j < XVECLEN (in_rtx, i); j++) print_rtx (XVECEXP (in_rtx, i, j)); indent -= 2; } if (sawclose) fprintf (outfile, "\n%s", (spaces + (sizeof spaces - indent * 2))); fprintf (outfile, "] "); sawclose = 1; indent -= 2; break; case 'i': fprintf (outfile, " %d", XINT (in_rtx, i)); sawclose = 0; break; /* Print NOTE_INSN names rather than integer codes. */ case 'n': if (XINT (in_rtx, i) <= 0) fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); else fprintf (outfile, " %d", XINT (in_rtx, i)); sawclose = 0; break; case 'u': if (XEXP (in_rtx, i) != NULL) fprintf(outfile, " %d", INSN_UID (XEXP (in_rtx, i))); else fprintf(outfile, " 0"); sawclose = 0; break; default: fprintf (stderr, "switch format wrong in rtl.print_rtx(). format was: %c.\n", format_ptr[-1]); abort (); } fprintf (outfile, ")");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -