123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 |
- /* Manage RTL for C-Compiler
- Copyright (C) 1987 Free Software Foundation, Inc.
- This file is part of GNU CC.
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the GNU CC General Public
- License for full details.
- Everyone is granted permission to copy, modify and redistribute
- GNU CC, but only under the conditions described in the
- GNU CC General Public License. A copy of this license is
- supposed to have been given to you along with GNU CC so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
- /* This file contains the low level primitives for allocating,
- printing and reading rtl expressions and vectors.
- It also contains some functions for semantic analysis
- on rtl expressions. */
- #include "config.h"
- #include <ctype.h>
- #include <stdio.h>
- #include <strings.h>
- #include "rtl.h"
- #include <obstack.h>
- #define obstack_chunk_alloc xmalloc
- #define obstack_chunk_free free
- extern int xmalloc ();
- extern void free ();
- /* We use the same obstack used for the tree.
- That way, the TREE_RTL of top-level variables and functions
- is permanent. */
- extern struct obstack *current_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_rtx. */
- 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, TYPE, SIZE, UNIT) NAME,
- char *mode_name[] = {
- #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, TYPE, SIZE, UNIT) SIZE,
- 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, TYPE, SIZE, UNIT) UNIT,
- int mode_unit_size[] = {
- #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
- "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
- };
- /* Allocate an rtx vector of N elements.
- Store the length, and initialize all elements to zero. */
- rtvec
- rtvec_alloc (n)
- int n;
- {
- rtvec rt;
- int i;
- rt = (rtvec) obstack_alloc (current_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. */
- rtx
- rtx_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 (current_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. */
- rtx
- copy_rtx (orig)
- register rtx orig;
- {
- register rtx copy;
- register int i, j;
- register RTX_CODE code;
- register char *format_ptr;
- code = GET_CODE (orig);
- if (code == REG
- || code == CONST_INT
- || code == CONST_DOUBLE
- || code == SYMBOL_REF
- || code == CODE_LABEL
- || code == PC
- || code == CC0)
- return orig;
- copy = rtx_alloc (code);
- PUT_MODE (copy, GET_MODE (orig));
-
- 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) = 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;
- }
- /* Return 1 unless X is a value effectively constant.
- The frame pointer, arg pointer, etc. are considered constant. */
- int
- rtx_varies_p (x)
- rtx x;
- {
- register RTX_CODE code = GET_CODE (x);
- register int i;
- register char *fmt;
- if (code == MEM || code == QUEUED)
- return 1;
- if (code == CONST || code == CONST_INT || code == UNCHANGING)
- return 0;
- if (code == REG)
- return ! (REGNO (x) == FRAME_POINTER_REGNUM
- || REGNO (x) == ARG_POINTER_REGNUM);
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- if (rtx_varies_p (XEXP (x, i)))
- return 1;
- return 0;
- }
- /* Return 1 if X refers to a memory location whose address
- is not effectively constant, or if X refers to a BLKmode memory object. */
- int
- rtx_addr_varies_p (x)
- rtx x;
- {
- register RTX_CODE code = GET_CODE (x);
- register int i;
- register char *fmt;
- if (code == MEM)
- return GET_MODE (x) == BLKmode || rtx_varies_p (XEXP (x, 0));
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- if (rtx_addr_varies_p (XEXP (x, i)))
- return 1;
- return 0;
- }
- /* Return nonzero if INSN alters memory at an address that is not fixed. */
- int
- insn_store_addr_varies_p (insn)
- rtx insn;
- {
- register rtx x = PATTERN (insn);
- if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
- return rtx_addr_varies_p (SET_DEST (x));
- else if (GET_CODE (x) == PARALLEL)
- {
- register int i;
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- {
- register rtx y = XVECEXP (x, 0, i);
- if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
- if (rtx_addr_varies_p (SET_DEST (y)))
- return 1;
- }
- }
- return 0;
- }
- /* Nonzero if register REG appears somewhere within IN. */
- int
- reg_mentioned_p (reg, in)
- register rtx reg, in;
- {
- register char *fmt;
- register int i;
- register enum rtx_code code = GET_CODE (in);
- if (GET_CODE (in) == REG)
- return REGNO (in) == REGNO (reg);
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code); i >= 0; i--)
- {
- if (fmt[i] == 'E')
- {
- register int j;
- for (j = XVECLEN (in, i) - 1; j >= 0; j--)
- if (reg_mentioned_p (reg, XVECEXP (in, i, j)))
- return 1;
- }
- else if (fmt[i] == 'e'
- && reg_mentioned_p (reg, XEXP (in, i)))
- return 1;
- }
- return 0;
- }
- /* Nonzero if register REG is used in an insn between
- FROM_INSN and TO_INSN (exclusive of those two). */
- int
- reg_used_between_p (reg, from_insn, to_insn)
- rtx reg, from_insn, to_insn;
- {
- register rtx insn;
- register RTX_CODE code;
- for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
- if (((code = GET_CODE (insn)) == INSN
- || code == JUMP_INSN || code == CALL_INSN)
- && reg_mentioned_p (reg, PATTERN (insn)))
- return 1;
- return 0;
- }
- /* Call FUN on each register or MEM that is stored into or clobbered by X.
- (X would be the pattern of an insn).
- FUN receives two arguments:
- the REG, MEM, CC0 or PC being stored in or clobbered,
- the SET or CLOBBER rtx that does the store. */
-
- void
- note_stores (x, fun)
- register rtx x;
- void (*fun) ();
- {
- if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
- {
- register rtx dest = SET_DEST (x);
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == VOLATILE
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- (*fun) (dest, x);
- }
- else if (GET_CODE (x) == PARALLEL)
- {
- register int i;
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- {
- register rtx y = XVECEXP (x, 0, i);
- if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
- {
- register rtx dest = SET_DEST (y);
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == VOLATILE
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- (*fun) (dest, y);
- }
- }
- }
- }
- /* Return nonzero if register REG's old contents don't survive after INSN.
- This can be because REG dies in INSN or because INSN entirely sets REG.
- "Entirely set" means set directly and not through a SUBREG,
- ZERO_EXTRACT or SIGN_EXTRACT, so no trace of the old contents remains.
- REG may be a hard or pseudo reg. Renumbering is not taken into account,
- but for this use that makes no difference, since regs don't overlap
- during their lifetimes. Therefore, this function may be used
- at any time after deaths have been computed (in flow.c). */
- int
- dead_or_set_p (insn, reg)
- rtx insn;
- rtx reg;
- {
- register rtx link;
- register int regno = REGNO (reg);
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REGNO (XEXP (link, 0)) == regno
- && ((enum reg_note) GET_MODE (link) == REG_DEAD
- || (enum reg_note) GET_MODE (link) == REG_INC))
- return 1;
- if (GET_CODE (PATTERN (insn)) == SET)
- return SET_DEST (PATTERN (insn)) == reg;
- else if (GET_CODE (PATTERN (insn)) == PARALLEL)
- {
- register int i;
- for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
- {
- if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
- && SET_DEST (XVECEXP (PATTERN (insn), 0, i)) == reg)
- return 1;
- }
- }
- return 0;
- }
- /* 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 void
- print_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 (GET_MODE (in_rtx) != VOIDmode)
- 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':
- 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;
- 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, ")");
- sawclose = 1;
- }
- /* External entry point for printing a chain of INSNs
- starting with RTX_FIRST onto file OUTF. */
- void
- print_rtl (outf, rtx_first)
- FILE *outf;
- rtx rtx_first;
- {
- register rtx tmp_rtx;
- outfile = outf;
- sawclose = 0;
- for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
- {
- print_rtx (tmp_rtx);
- fprintf (outfile, "\n");
- }
- }
- /* Subroutines of read_rtx. */
- /* Dump code after printing a message. Used when read_rtx finds
- invalid data. */
- static void
- dump_and_abort (expected_c, actual_c, infile)
- int expected_c, actual_c;
- FILE *infile;
- {
- int c, i;
- fprintf (stderr,
- "Expected character %c. Read character %c. At file position: %ld\n",
- expected_c, actual_c, ftell (infile));
- fprintf (stderr, "Following characters are:\n\t");
- for (i = 0; i < 200; i++)
- {
- c = getc (infile);
- if (EOF == c) break;
- putc (c, stderr);
- }
- fprintf (stderr, "Aborting.\n");
- abort ();
- }
- /* Read chars from INFILE until a non-whitespace char
- and return that. Comments, both Lisp style and C style,
- are treated as whitespace.
- Tools such as genflags use this function. */
- int
- read_skip_spaces (infile)
- FILE *infile;
- {
- register int c;
- while (c = getc (infile))
- {
- if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
- ;
- else if (c == ';')
- {
- while ((c = getc (infile)) && c != '\n') ;
- }
- else if (c == '/')
- {
- register int prevc;
- c = getc (infile);
- if (c != '*')
- dump_and_abort ('*', c, infile);
-
- prevc = 0;
- while (c = getc (infile))
- {
- if (prevc == '*' && c == '/')
- break;
- prevc = c;
- }
- }
- else break;
- }
- return c;
- }
- /* Read an rtx code name into the buffer STR[].
- It is terminated by any of the punctuation chars of rtx printed syntax. */
- static void
- read_name (str, infile)
- char *str;
- FILE *infile;
- {
- register char *p;
- register int c;
- c = read_skip_spaces(infile);
- p = str;
- while (1)
- {
- if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
- break;
- if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
- || c == '(' || c == '[')
- {
- ungetc (c, infile);
- break;
- }
- *p++ = c;
- c = getc (infile);
- }
- *p = NULL;
- }
- /* Read an rtx in printed representation from INFILE
- and return an actual rtx in core constructed accordingly.
- read_rtx is not used in the compiler proper, but rather in
- the utilities gen*.c that construct C code from machine descriptions. */
- rtx
- read_rtx (infile)
- FILE *infile;
- {
- register int i, j, list_counter;
- RTX_CODE tmp_code;
- register char *format_ptr;
- /* tmp_char is a buffer used for reading decimal integers
- and names of rtx types and machine modes.
- Therefore, 256 must be enough. */
- char tmp_char[256];
- rtx return_rtx;
- register int c;
- int tmp_int;
- /* Linked list structure for making RTXs: */
- struct rtx_list
- {
- struct rtx_list *next;
- rtx value; /* Value of this node... */
- };
- c = read_skip_spaces (infile); /* Should be open paren. */
- if (c != '(')
- dump_and_abort ('(', c, infile);
- read_name (tmp_char, infile);
- tmp_code = UNKNOWN;
- for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
- {
- if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
- {
- tmp_code = (RTX_CODE) i; /* get value for name */
- break;
- }
- }
- if (tmp_code == UNKNOWN)
- {
- fprintf (stderr,
- "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
- tmp_char);
- }
- /* (NIL) stands for an expression that isn't there. */
- if (tmp_code == NIL)
- {
- /* Discard the closeparen. */
- while ((c = getc (infile)) && c != ')');
- return 0;
- }
- return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
- then we free this space below. */
- format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
- /* If what follows is `: mode ', read it and
- store the mode in the rtx. */
- i = read_skip_spaces (infile);
- if (i == ':')
- {
- register int k;
- read_name (tmp_char, infile);
- for (k = 0; k < NUM_MACHINE_MODE; k++)
- if (!strcmp (GET_MODE_NAME (k), tmp_char))
- break;
- PUT_MODE (return_rtx, (enum machine_mode) k );
- }
- else
- ungetc (i, infile);
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
- switch (*format_ptr++)
- {
- /* 0 means a field for internal use only.
- Don't expect it to be present in the input. */
- case '0':
- break;
- case 'e':
- case 'u':
- XEXP (return_rtx, i) = read_rtx (infile);
- break;
- case 'E':
- {
- register struct rtx_list *next_rtx, *rtx_list_link;
- struct rtx_list *list_rtx;
- c = read_skip_spaces (infile);
- if (c != '[')
- dump_and_abort ('[', c, infile);
- /* add expressions to a list, while keeping a count */
- next_rtx = NULL;
- list_counter = 0;
- while ((c = read_skip_spaces (infile)) && c != ']')
- {
- ungetc (c, infile);
- list_counter++;
- rtx_list_link = (struct rtx_list *)
- alloca (sizeof (struct rtx_list));
- rtx_list_link->value = read_rtx (infile);
- if (next_rtx == 0)
- list_rtx = rtx_list_link;
- else
- next_rtx->next = rtx_list_link;
- next_rtx = rtx_list_link;
- rtx_list_link->next = 0;
- }
- /* get vector length and allocate it */
- XVEC (return_rtx, i) = (list_counter
- ? rtvec_alloc (list_counter)
- : NULL);
- if (list_counter > 0)
- {
- next_rtx = list_rtx;
- for (j = 0; j < list_counter; j++,
- next_rtx = next_rtx->next)
- XVECEXP (return_rtx, i, j) = next_rtx->value;
- }
- /* close bracket gotten */
- }
- break;
- case 's':
- {
- int saw_paren = 0;
- register char *stringbuf;
- int stringbufsize;
- c = read_skip_spaces (infile);
- if (c == '(')
- {
- saw_paren = 1;
- c = read_skip_spaces (infile);
- }
- if (c != '"')
- dump_and_abort ('"', c, infile);
- j = 0;
- stringbufsize = 10;
- stringbuf = (char *) xmalloc (stringbufsize + 1);
- while (1)
- {
- if (j >= stringbufsize - 4)
- {
- stringbufsize *= 2;
- stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
- }
- stringbuf[j] = getc (infile); /* Read the string */
- if (stringbuf[j] == '\\')
- {
- stringbuf[j] = getc (infile); /* Read the string */
- /* \; makes stuff for a C string constant containing
- newline and tab. */
- if (stringbuf[j] == ';')
- {
- strcpy (&stringbuf[j], "\\n\\t");
- j += 3;
- }
- }
- else if (stringbuf[j] == '"')
- break;
- j++;
- }
- stringbuf[j] = 0; /* NUL terminate the string */
- stringbuf = (char *) xrealloc (stringbuf, j + 1);
- if (saw_paren)
- {
- c = read_skip_spaces (infile);
- if (c != ')')
- dump_and_abort (')', c, infile);
- }
- XSTR (return_rtx, i) = stringbuf;
- }
- break;
- case 'i':
- read_name (tmp_char, infile);
- tmp_int = atoi (tmp_char);
- XINT (return_rtx, i) = tmp_int;
- break;
- default:
- fprintf (stderr,
- "switch format wrong in rtl.read_rtx(). format was: %c.\n",
- format_ptr[-1]);
- fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
- abort ();
- }
- c = read_skip_spaces (infile);
- if (c != ')')
- dump_and_abort (')', c, infile);
- return return_rtx;
- }
- /* This is called once per compilation, before any rtx's are constructed.
- It initializes the vector `rtx_length'. */
- void
- init_rtl()
- {
- int i;
- for (i = 0; i < NUM_RTX_CODE; i++)
- rtx_length[i] = strlen (rtx_format[i]);
- }
|