1991-12-06 16:00:31 -05:00
|
|
|
|
/* Allocate and read RTL for GNU C Compiler.
|
1999-01-06 15:51:20 -05:00
|
|
|
|
Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998 Free Software Foundation, Inc.
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
This file is part of GNU CC.
|
|
|
|
|
|
|
|
|
|
GNU CC is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2, 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 of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with GNU CC; see the file COPYING. If not, write to
|
1995-06-15 08:04:37 -04:00
|
|
|
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
|
|
|
Boston, MA 02111-1307, USA. */
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
Major cutover to using system.h:
* Makefile.in (alias.o, bitmap.o, c-aux-info.o, c-common.o,
c-decl.o, c-iterate.o, c-lang.o, c-lex.o, c-pragma.o, c-typeck.o,
caller-save.o, calls.o, collect2.o, combine.o, cse.o, dbxout.o,
dwarf2out.o, dwarfout.o, emit-rtl.o, except.o, explow.o, expmed.o,
expr.o, final.o, flow.o, function.o, getpwd.o, global.o,
integrate.o, jump.o, local-alloc.o, loop.o, optabs.o, pexecute.o,
prefix.o, print-rtl.o, print-tree.o, profile.o, real.o, recog.o,
reg-stack.o, regclass.o, regmove.o, reload.o, reload1.o, reorg.o,
rtl.o, rtlanal.o, sdbout.o, stmt.o, stor-layout.o, stupid.o,
tlink.o, toplev.o, tree.o, unroll.o, varasm.o, xcoffout.o): Depend
on system.h.
* alias.c, bitmap.c, c-aux-info.c, c-common.c, c-decl.c,
c-iterate.c, c-lang.c, c-lex.c, c-pragma.c, c-typeck.c,
caller-save.c, calls.c, collect2.c, combine.c, cse.c, dbxout.c,
dwarf2out.c, dwarfout.c, emit-rtl.c, except.c, explow.c, expmed.c,
expr.c, final.c, flow.c, function.c, gcc.c, getpwd.c, global.c,
integrate.c, jump.c, local-alloc.c, loop.c, optabs.c, pexecute.c,
prefix.c, print-rtl.c, print-tree.c, profile.c, real.c, recog.c,
reg-stack.c, regclass.c, regmove.c, reload.c, reload1.c, reorg.c,
rtl.c, rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c,
stupid.c, tlink.c, toplev.c, tree.c, unroll.c, varasm.c,
xcoffout.c: Include system.h. Organize include ordering so
that stdarg/varargs comes before other system headers. Remove
spurious casts of functions assured of a prototype in system.h.
From-SVN: r18726
1998-03-20 09:58:42 -05:00
|
|
|
|
#include "system.h"
|
1991-12-06 16:00:31 -05:00
|
|
|
|
#include "rtl.h"
|
1993-03-31 00:50:32 -05:00
|
|
|
|
#include "real.h"
|
Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
* Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
(rtl.o, emit-rtl.o): Add dependency on bitmap.h.
($(HOST_PREFIX_1)rtl.o): Likewise.
($(HOST_PREFIX_1)bitmap.o): New host object.
* emit-rtl.c (toplevel): Include bitmap.h.
(gen_rtx): Handle 't' and 'b' nodes.
* print-rtl.c (print_rtx): Handle printing NOTE_INSN_LIVE notes.
Print block number for block begin/end notes. Print 't' type
nodes as a pointer. Know that the 3rd argument of live range
start/stop notes is really a range_info rtx. If type is 'b', print
out argument as a bitmap.
* rtl.c: Include bitmap.c.
(copy_rtx): Copy tree nodes as is. Copy bitmaps if type is 'b'.
(note_insn_name): Add NOTE_INSN_RANGE_{START,END}, NOTE_INSN_LIVE.
* rtl.def (RANGE_LIVE): New node to hold live information while we
recalculate the basic blocks.
(RANGE_REG, RANGE_INFO): New rtl types for live range splitting.
(RANGE_VAR): New node, to hold information saved in symbol node for New
communicating live range information to the debug output functions.
* rtl.h (rtunion_def): Add rttree and rtbit fields.
(XBITMAP, XTREE): New accessor macros.
(NOTE_LIVE_INFO): Overload NOTE_SOURCE_FILE for NOTE_INSN_LIVE notes.
(NOTE_RANGE_INFO): Similarly for NOTE_INSN_RANGE_{START,END} notes.
(NOTE_BLOCK_LIVE_RANGE_BLOCK): Define.
(NOTE_INSN_RANGE_START, NOTE_INSN_RANGE_END, NOTE_INSN_LIVE): New notes.
(RANGE_LIVE_{BITMAP,ORIG_BLOCK}): New accessor macros.
(RANGE_REG_{SYMBOL,BLOCK}_NODE, RANGE_VAR_*): New accessor macros.
(RANGE_INFO_*): Likewise.
* sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* haifa-sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* tree.h (BLOCK_LIVE_RANGE_{START,END,VAR_FLAG}): New accessor macros.
(BLOCK_LIVE_RANGE_FLAG): Likewise.
(DECL_LIVE_RANGE_RTL): Likewise.
(struct tree_block): Add live_range_flag, live_range_var_flag,
live_range_start and live_range_end.
(struct tree_decl): Add live_range_rtl field.
* gengenrtl.c (type_from_format): Handle 'b' and 't'.
(accessor_from_format): Likewise.
Co-Authored-By: Jeffrey A Law <law@cygnus.com>
From-SVN: r19727
1998-05-13 17:13:47 -04:00
|
|
|
|
#include "bitmap.h"
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
#include "obstack.h"
|
|
|
|
|
#define obstack_chunk_alloc xmalloc
|
|
|
|
|
#define obstack_chunk_free 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 function_obstack. */
|
|
|
|
|
|
|
|
|
|
extern struct obstack *rtl_obstack;
|
|
|
|
|
|
|
|
|
|
/* 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, CLASS) 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,
|
|
|
|
|
|
1998-10-01 12:47:41 -04:00
|
|
|
|
char *mode_name[(int) MAX_MACHINE_MODE + 1] = {
|
1991-12-06 16:00:31 -05:00
|
|
|
|
#include "machmode.def"
|
|
|
|
|
|
|
|
|
|
#ifdef EXTRA_CC_MODES
|
1998-10-01 12:47:41 -04:00
|
|
|
|
EXTRA_CC_NAMES,
|
1991-12-06 16:00:31 -05:00
|
|
|
|
#endif
|
1998-10-01 12:47:41 -04:00
|
|
|
|
/* Add an extra field to avoid a core dump if someone tries to convert
|
|
|
|
|
MAX_MACHINE_MODE to a string. */
|
|
|
|
|
""
|
1991-12-06 16:00:31 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#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[(int) MAX_MACHINE_MODE] = {
|
|
|
|
|
#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,
|
|
|
|
|
|
|
|
|
|
int mode_size[(int) MAX_MACHINE_MODE] = {
|
|
|
|
|
#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,
|
|
|
|
|
|
|
|
|
|
int mode_unit_size[(int) MAX_MACHINE_MODE] = {
|
|
|
|
|
#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) \
|
1998-10-01 12:47:41 -04:00
|
|
|
|
(unsigned char) WIDER,
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
1998-10-01 12:47:41 -04:00
|
|
|
|
unsigned char mode_wider_mode[(int) MAX_MACHINE_MODE] = {
|
1991-12-06 16:00:31 -05:00
|
|
|
|
#include "machmode.def" /* machine modes are documented here */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef DEF_MACHMODE
|
|
|
|
|
|
1998-10-01 12:47:41 -04:00
|
|
|
|
#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \
|
|
|
|
|
((SIZE) * BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT)0 : ((unsigned HOST_WIDE_INT) 1 << (SIZE) * BITS_PER_UNIT) - 1,
|
|
|
|
|
|
|
|
|
|
/* Indexed by machine mode, gives mask of significant bits in mode. */
|
|
|
|
|
|
1998-10-23 00:09:58 -04:00
|
|
|
|
unsigned HOST_WIDE_INT mode_mask_array[(int) MAX_MACHINE_MODE] = {
|
1998-10-01 12:47:41 -04:00
|
|
|
|
#include "machmode.def"
|
|
|
|
|
};
|
|
|
|
|
|
1992-01-04 17:39:21 -05:00
|
|
|
|
/* Indexed by mode class, gives the narrowest mode for each class. */
|
|
|
|
|
|
|
|
|
|
enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
|
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
/* Indexed by rtx code, gives a sequence of operand-types for
|
|
|
|
|
rtx's of that code. The sequence is a C string in which
|
1992-05-07 02:41:23 -04:00
|
|
|
|
each character describes one operand. */
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
"n" like "i", but prints entries from `note_insn_name'
|
1992-07-06 16:15:06 -04:00
|
|
|
|
"w" an integer of width HOST_BITS_PER_WIDE_INT
|
|
|
|
|
prints the integer
|
1991-12-06 16:00:31 -05:00
|
|
|
|
"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
|
|
|
|
|
"V" like "E", but optional:
|
|
|
|
|
the containing rtx may end before this operand
|
|
|
|
|
"u" a pointer to another insn
|
Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
* Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
(rtl.o, emit-rtl.o): Add dependency on bitmap.h.
($(HOST_PREFIX_1)rtl.o): Likewise.
($(HOST_PREFIX_1)bitmap.o): New host object.
* emit-rtl.c (toplevel): Include bitmap.h.
(gen_rtx): Handle 't' and 'b' nodes.
* print-rtl.c (print_rtx): Handle printing NOTE_INSN_LIVE notes.
Print block number for block begin/end notes. Print 't' type
nodes as a pointer. Know that the 3rd argument of live range
start/stop notes is really a range_info rtx. If type is 'b', print
out argument as a bitmap.
* rtl.c: Include bitmap.c.
(copy_rtx): Copy tree nodes as is. Copy bitmaps if type is 'b'.
(note_insn_name): Add NOTE_INSN_RANGE_{START,END}, NOTE_INSN_LIVE.
* rtl.def (RANGE_LIVE): New node to hold live information while we
recalculate the basic blocks.
(RANGE_REG, RANGE_INFO): New rtl types for live range splitting.
(RANGE_VAR): New node, to hold information saved in symbol node for New
communicating live range information to the debug output functions.
* rtl.h (rtunion_def): Add rttree and rtbit fields.
(XBITMAP, XTREE): New accessor macros.
(NOTE_LIVE_INFO): Overload NOTE_SOURCE_FILE for NOTE_INSN_LIVE notes.
(NOTE_RANGE_INFO): Similarly for NOTE_INSN_RANGE_{START,END} notes.
(NOTE_BLOCK_LIVE_RANGE_BLOCK): Define.
(NOTE_INSN_RANGE_START, NOTE_INSN_RANGE_END, NOTE_INSN_LIVE): New notes.
(RANGE_LIVE_{BITMAP,ORIG_BLOCK}): New accessor macros.
(RANGE_REG_{SYMBOL,BLOCK}_NODE, RANGE_VAR_*): New accessor macros.
(RANGE_INFO_*): Likewise.
* sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* haifa-sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* tree.h (BLOCK_LIVE_RANGE_{START,END,VAR_FLAG}): New accessor macros.
(BLOCK_LIVE_RANGE_FLAG): Likewise.
(DECL_LIVE_RANGE_RTL): Likewise.
(struct tree_block): Add live_range_flag, live_range_var_flag,
live_range_start and live_range_end.
(struct tree_decl): Add live_range_rtl field.
* gengenrtl.c (type_from_format): Handle 'b' and 't'.
(accessor_from_format): Likewise.
Co-Authored-By: Jeffrey A Law <law@cygnus.com>
From-SVN: r19727
1998-05-13 17:13:47 -04:00
|
|
|
|
prints the uid of the insn.
|
|
|
|
|
"b" is a pointer to a bitmap header.
|
|
|
|
|
"t" is a tree pointer. */
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
|
|
|
|
|
#include "rtl.def" /* rtl expressions are defined here */
|
|
|
|
|
#undef DEF_RTL_EXPR
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Indexed by rtx code, gives a character representing the "class" of
|
|
|
|
|
that rtx code. See rtl.def for documentation on the defined classes. */
|
|
|
|
|
|
|
|
|
|
char rtx_class[] = {
|
|
|
|
|
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS,
|
|
|
|
|
#include "rtl.def" /* rtl expressions are defined here */
|
|
|
|
|
#undef DEF_RTL_EXPR
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Names for kinds of NOTEs and REG_NOTEs. */
|
|
|
|
|
|
1993-04-25 20:18:16 -04:00
|
|
|
|
char *note_insn_name[] = { 0 , "NOTE_INSN_DELETED",
|
1991-12-06 16:00:31 -05:00
|
|
|
|
"NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
|
|
|
|
|
"NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
|
|
|
|
|
"NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
|
1992-06-29 12:04:35 -04:00
|
|
|
|
"NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
|
1992-07-04 23:31:52 -04:00
|
|
|
|
"NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
|
1996-07-23 15:58:32 -04:00
|
|
|
|
"NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
|
1997-03-28 17:39:20 -05:00
|
|
|
|
"NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
|
Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
* Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
(rtl.o, emit-rtl.o): Add dependency on bitmap.h.
($(HOST_PREFIX_1)rtl.o): Likewise.
($(HOST_PREFIX_1)bitmap.o): New host object.
* emit-rtl.c (toplevel): Include bitmap.h.
(gen_rtx): Handle 't' and 'b' nodes.
* print-rtl.c (print_rtx): Handle printing NOTE_INSN_LIVE notes.
Print block number for block begin/end notes. Print 't' type
nodes as a pointer. Know that the 3rd argument of live range
start/stop notes is really a range_info rtx. If type is 'b', print
out argument as a bitmap.
* rtl.c: Include bitmap.c.
(copy_rtx): Copy tree nodes as is. Copy bitmaps if type is 'b'.
(note_insn_name): Add NOTE_INSN_RANGE_{START,END}, NOTE_INSN_LIVE.
* rtl.def (RANGE_LIVE): New node to hold live information while we
recalculate the basic blocks.
(RANGE_REG, RANGE_INFO): New rtl types for live range splitting.
(RANGE_VAR): New node, to hold information saved in symbol node for New
communicating live range information to the debug output functions.
* rtl.h (rtunion_def): Add rttree and rtbit fields.
(XBITMAP, XTREE): New accessor macros.
(NOTE_LIVE_INFO): Overload NOTE_SOURCE_FILE for NOTE_INSN_LIVE notes.
(NOTE_RANGE_INFO): Similarly for NOTE_INSN_RANGE_{START,END} notes.
(NOTE_BLOCK_LIVE_RANGE_BLOCK): Define.
(NOTE_INSN_RANGE_START, NOTE_INSN_RANGE_END, NOTE_INSN_LIVE): New notes.
(RANGE_LIVE_{BITMAP,ORIG_BLOCK}): New accessor macros.
(RANGE_REG_{SYMBOL,BLOCK}_NODE, RANGE_VAR_*): New accessor macros.
(RANGE_INFO_*): Likewise.
* sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* haifa-sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* tree.h (BLOCK_LIVE_RANGE_{START,END,VAR_FLAG}): New accessor macros.
(BLOCK_LIVE_RANGE_FLAG): Likewise.
(DECL_LIVE_RANGE_RTL): Likewise.
(struct tree_block): Add live_range_flag, live_range_var_flag,
live_range_start and live_range_end.
(struct tree_decl): Add live_range_rtl field.
* gengenrtl.c (type_from_format): Handle 'b' and 't'.
(accessor_from_format): Likewise.
Co-Authored-By: Jeffrey A Law <law@cygnus.com>
From-SVN: r19727
1998-05-13 17:13:47 -04:00
|
|
|
|
"NOTE_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_START",
|
1999-02-25 18:45:42 -05:00
|
|
|
|
"NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
|
|
|
|
|
"NOTE_INSN_BASIC_BLOCK" };
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
|
|
|
|
|
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
|
|
|
|
|
"REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
|
|
|
|
|
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
|
1997-03-28 17:39:20 -05:00
|
|
|
|
"REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
|
1997-09-23 03:14:07 -04:00
|
|
|
|
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
|
1998-09-05 17:57:56 -04:00
|
|
|
|
"REG_BR_PRED", "REG_EH_CONTEXT",
|
1998-12-08 09:04:03 -05:00
|
|
|
|
"REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
|
|
|
|
|
"REG_EH_RETHROW" };
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
Add ATTRIBUTE_NORETURN in a bunch of places:
* cppalloc.c (memory_full): Mark function prototype with
ATTRIBUTE_NORETURN.
* demangle.h (collect_exit): Likewise.
* fix-header.c (v_fatal, fatal): Likewise.
* gcc.c (pfatal_with_name, pfatal_pexecute, fatal, fancy_abort):
Likewise.
* gcov.c (print_usage): Likewise.
* genattr.c (fatal, fancy_abort): Likewise.
* genattrtab.c (fatal, fancy_abort): Likewise.
* gencodes.c (fatal, fancy_abort): Likewise.
* genconfig.c (fatal, fancy_abort): Likewise.
* genemit.c (fatal, fancy_abort): Likewise.
* genextract.c (fatal, fancy_abort): Likewise.
* genflags.c (fatal, fancy_abort): Likewise.
* genopinit.c (fatal, fancy_abort): Likewise.
* genoutput.c (fatal, fancy_abort): Likewise.
* genpeep.c (fatal, fancy_abort): Likewise.
* genrecog.c (fatal, fancy_abort): Likewise.
* libgcc2.c (__eprintf, __default_terminate, __sjthrow,
__sjpopnthrow, __throw): Likewise.
* objc/objc-act.c (objc_fatal): Likewise.
* protoize.c (usage, aux_info_corrupted,
declare_source_confusing): Likewise.
* rtl.c (dump_and_abort): Likewise.
* rtl.h (sets_cc0_p): Likewise.
* toplev.c (float_signal, pipe_closed): Likewise.
From-SVN: r23084
1998-10-14 06:37:09 -04:00
|
|
|
|
static void dump_and_abort PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
|
1997-12-06 19:31:01 -05:00
|
|
|
|
static void read_name PROTO((char *, FILE *));
|
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
/* 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 (rtl_obstack,
|
|
|
|
|
sizeof (struct rtvec_def)
|
|
|
|
|
+ (( n - 1) * sizeof (rtunion)));
|
|
|
|
|
|
|
|
|
|
/* clear out the vector */
|
1996-11-15 14:13:13 -05:00
|
|
|
|
PUT_NUM_ELEM (rt, n);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
rt->elem[i].rtwint = 0;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
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 struct obstack *ob = rtl_obstack;
|
|
|
|
|
register int nelts = GET_RTX_LENGTH (code);
|
|
|
|
|
register int length = sizeof (struct rtx_def)
|
|
|
|
|
+ (nelts - 1) * sizeof (rtunion);
|
|
|
|
|
|
|
|
|
|
/* This function is called more than any other in GCC,
|
|
|
|
|
so we manipulate the obstack directly.
|
|
|
|
|
|
|
|
|
|
Even though rtx objects are word aligned, we may be sharing an obstack
|
|
|
|
|
with tree nodes, which may have to be double-word aligned. So align
|
|
|
|
|
our length to the alignment mask in the obstack. */
|
|
|
|
|
|
|
|
|
|
length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
|
|
|
|
|
|
|
|
|
|
if (ob->chunk_limit - ob->next_free < length)
|
|
|
|
|
_obstack_newchunk (ob, length);
|
|
|
|
|
rt = (rtx)ob->object_base;
|
|
|
|
|
ob->next_free += length;
|
|
|
|
|
ob->object_base = ob->next_free;
|
|
|
|
|
|
1993-01-03 18:59:45 -05:00
|
|
|
|
/* We want to clear everything up to the FLD array. Normally, this is
|
|
|
|
|
one int, but we don't want to assume that and it isn't very portable
|
|
|
|
|
anyway; this is. */
|
|
|
|
|
|
1999-01-11 20:31:09 -05:00
|
|
|
|
memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
|
1993-01-03 18:59:45 -05:00
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
PUT_CODE (rt, code);
|
|
|
|
|
|
|
|
|
|
return rt;
|
|
|
|
|
}
|
1993-09-19 15:07:16 -04:00
|
|
|
|
|
|
|
|
|
/* Free the rtx X and all RTL allocated since X. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rtx_free (x)
|
|
|
|
|
rtx x;
|
|
|
|
|
{
|
|
|
|
|
obstack_free (rtl_obstack, x);
|
|
|
|
|
}
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case REG:
|
|
|
|
|
case QUEUED:
|
|
|
|
|
case CONST_INT:
|
|
|
|
|
case CONST_DOUBLE:
|
|
|
|
|
case SYMBOL_REF:
|
|
|
|
|
case CODE_LABEL:
|
|
|
|
|
case PC:
|
|
|
|
|
case CC0:
|
1992-12-27 06:53:32 -05:00
|
|
|
|
case SCRATCH:
|
1996-07-03 18:07:53 -04:00
|
|
|
|
/* SCRATCH must be shared because they represent distinct values. */
|
1997-11-02 16:19:36 -05:00
|
|
|
|
case ADDRESSOF:
|
1991-12-06 16:00:31 -05:00
|
|
|
|
return orig;
|
1992-12-27 06:53:32 -05:00
|
|
|
|
|
|
|
|
|
case CONST:
|
|
|
|
|
/* CONST can be shared if it contains a SYMBOL_REF. If it contains
|
|
|
|
|
a LABEL_REF, it isn't sharable. */
|
|
|
|
|
if (GET_CODE (XEXP (orig, 0)) == PLUS
|
|
|
|
|
&& GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
|
|
|
|
|
&& GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
|
|
|
|
|
return orig;
|
|
|
|
|
break;
|
|
|
|
|
|
1993-01-14 13:33:41 -05:00
|
|
|
|
/* A MEM with a constant address is not sharable. The problem is that
|
|
|
|
|
the constant address may need to be reloaded. If the mem is shared,
|
|
|
|
|
then reloading one copy of this mem will cause all copies to appear
|
|
|
|
|
to have been reloaded. */
|
1997-11-02 16:19:36 -05:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy = rtx_alloc (code);
|
1999-02-22 08:34:33 -05:00
|
|
|
|
|
|
|
|
|
/* Copy the various flags, and other information. We assume that
|
|
|
|
|
all fields need copying, and then clear the fields that should
|
|
|
|
|
not be copied. That is the sensible default behavior, and forces
|
|
|
|
|
us to explicitly document why we are *not* copying a flag. */
|
1999-03-19 07:43:55 -05:00
|
|
|
|
memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
|
1999-02-22 08:34:33 -05:00
|
|
|
|
|
|
|
|
|
/* We do not copy the USED flag, which is used as a mark bit during
|
|
|
|
|
walks over the RTL. */
|
|
|
|
|
copy->used = 0;
|
|
|
|
|
|
|
|
|
|
/* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */
|
|
|
|
|
if (GET_RTX_CLASS (code) == 'i')
|
|
|
|
|
{
|
|
|
|
|
copy->jump = 0;
|
|
|
|
|
copy->call = 0;
|
|
|
|
|
copy->frame_related = 0;
|
|
|
|
|
}
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
1992-07-06 16:15:06 -04:00
|
|
|
|
case '0':
|
1992-06-27 07:20:07 -04:00
|
|
|
|
case 'u':
|
|
|
|
|
XEXP (copy, i) = XEXP (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
case 'E':
|
|
|
|
|
case 'V':
|
|
|
|
|
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;
|
|
|
|
|
|
Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
* Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
(rtl.o, emit-rtl.o): Add dependency on bitmap.h.
($(HOST_PREFIX_1)rtl.o): Likewise.
($(HOST_PREFIX_1)bitmap.o): New host object.
* emit-rtl.c (toplevel): Include bitmap.h.
(gen_rtx): Handle 't' and 'b' nodes.
* print-rtl.c (print_rtx): Handle printing NOTE_INSN_LIVE notes.
Print block number for block begin/end notes. Print 't' type
nodes as a pointer. Know that the 3rd argument of live range
start/stop notes is really a range_info rtx. If type is 'b', print
out argument as a bitmap.
* rtl.c: Include bitmap.c.
(copy_rtx): Copy tree nodes as is. Copy bitmaps if type is 'b'.
(note_insn_name): Add NOTE_INSN_RANGE_{START,END}, NOTE_INSN_LIVE.
* rtl.def (RANGE_LIVE): New node to hold live information while we
recalculate the basic blocks.
(RANGE_REG, RANGE_INFO): New rtl types for live range splitting.
(RANGE_VAR): New node, to hold information saved in symbol node for New
communicating live range information to the debug output functions.
* rtl.h (rtunion_def): Add rttree and rtbit fields.
(XBITMAP, XTREE): New accessor macros.
(NOTE_LIVE_INFO): Overload NOTE_SOURCE_FILE for NOTE_INSN_LIVE notes.
(NOTE_RANGE_INFO): Similarly for NOTE_INSN_RANGE_{START,END} notes.
(NOTE_BLOCK_LIVE_RANGE_BLOCK): Define.
(NOTE_INSN_RANGE_START, NOTE_INSN_RANGE_END, NOTE_INSN_LIVE): New notes.
(RANGE_LIVE_{BITMAP,ORIG_BLOCK}): New accessor macros.
(RANGE_REG_{SYMBOL,BLOCK}_NODE, RANGE_VAR_*): New accessor macros.
(RANGE_INFO_*): Likewise.
* sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* haifa-sched.c (sched_analyze): Keep live range start/stop notes.
(unlink_other_notes): Likewise.
* tree.h (BLOCK_LIVE_RANGE_{START,END,VAR_FLAG}): New accessor macros.
(BLOCK_LIVE_RANGE_FLAG): Likewise.
(DECL_LIVE_RANGE_RTL): Likewise.
(struct tree_block): Add live_range_flag, live_range_var_flag,
live_range_start and live_range_end.
(struct tree_decl): Add live_range_rtl field.
* gengenrtl.c (type_from_format): Handle 'b' and 't'.
(accessor_from_format): Likewise.
Co-Authored-By: Jeffrey A Law <law@cygnus.com>
From-SVN: r19727
1998-05-13 17:13:47 -04:00
|
|
|
|
case 'b':
|
|
|
|
|
{
|
|
|
|
|
bitmap new_bits = BITMAP_OBSTACK_ALLOC (rtl_obstack);
|
|
|
|
|
bitmap_copy (new_bits, XBITMAP (orig, i));
|
|
|
|
|
XBITMAP (copy, i) = new_bits;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
|
XTREE (copy, i) = XTREE (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
1992-07-06 16:15:06 -04:00
|
|
|
|
case 'w':
|
|
|
|
|
XWINT (copy, i) = XWINT (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'i':
|
1991-12-06 16:00:31 -05:00
|
|
|
|
XINT (copy, i) = XINT (orig, i);
|
|
|
|
|
break;
|
1992-07-06 16:15:06 -04:00
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
case 'S':
|
|
|
|
|
XSTR (copy, i) = XSTR (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
abort ();
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return copy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
|
|
|
|
|
placed in the result directly, rather than being copied. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
copy_most_rtx (orig, may_share)
|
|
|
|
|
register rtx orig;
|
|
|
|
|
register rtx may_share;
|
|
|
|
|
{
|
|
|
|
|
register rtx copy;
|
|
|
|
|
register int i, j;
|
|
|
|
|
register RTX_CODE code;
|
|
|
|
|
register char *format_ptr;
|
|
|
|
|
|
|
|
|
|
if (orig == may_share)
|
|
|
|
|
return orig;
|
|
|
|
|
|
|
|
|
|
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;
|
1997-11-02 16:19:36 -05:00
|
|
|
|
default:
|
|
|
|
|
break;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (orig, i) != may_share)
|
|
|
|
|
XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
|
|
|
|
|
break;
|
1992-06-27 07:20:07 -04:00
|
|
|
|
|
1992-07-06 16:15:06 -04:00
|
|
|
|
case '0':
|
1992-06-27 07:20:07 -04:00
|
|
|
|
case 'u':
|
|
|
|
|
XEXP (copy, i) = XEXP (orig, i);
|
|
|
|
|
break;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
|
case 'V':
|
|
|
|
|
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_most_rtx (XVECEXP (orig, i, j), may_share);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
1992-07-06 16:15:06 -04:00
|
|
|
|
case 'w':
|
|
|
|
|
XWINT (copy, i) = XWINT (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
case 'i':
|
1991-12-06 16:00:31 -05:00
|
|
|
|
XINT (copy, i) = XINT (orig, i);
|
|
|
|
|
break;
|
1992-07-06 16:15:06 -04:00
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
case 'S':
|
|
|
|
|
XSTR (copy, i) = XSTR (orig, i);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
abort ();
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return copy;
|
|
|
|
|
}
|
1999-03-22 08:11:31 -05:00
|
|
|
|
|
|
|
|
|
/* Create a new copy of an rtx. Only copy just one level. */
|
|
|
|
|
rtx
|
|
|
|
|
shallow_copy_rtx (orig)
|
|
|
|
|
rtx orig;
|
|
|
|
|
{
|
|
|
|
|
register int i;
|
|
|
|
|
register char *format_ptr;
|
|
|
|
|
register RTX_CODE code = GET_CODE (orig);
|
|
|
|
|
register rtx 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;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < GET_RTX_LENGTH (code); i++)
|
|
|
|
|
copy->fld[i] = orig->fld[i];
|
|
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
}
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
|
if (expected_c >= 0)
|
|
|
|
|
fprintf (stderr,
|
|
|
|
|
"Expected character %c. Found character %c.",
|
|
|
|
|
expected_c, actual_c);
|
|
|
|
|
fprintf (stderr, " At file position: %ld\n", 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;
|
1997-12-20 06:31:54 -05:00
|
|
|
|
while ((c = getc (infile)))
|
1991-12-06 16:00:31 -05:00
|
|
|
|
{
|
|
|
|
|
if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
|
|
|
|
|
;
|
|
|
|
|
else if (c == ';')
|
|
|
|
|
{
|
1998-04-10 09:41:28 -04:00
|
|
|
|
while ((c = getc (infile)) && c != '\n' && c != EOF)
|
|
|
|
|
;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
else if (c == '/')
|
|
|
|
|
{
|
|
|
|
|
register int prevc;
|
|
|
|
|
c = getc (infile);
|
|
|
|
|
if (c != '*')
|
|
|
|
|
dump_and_abort ('*', c, infile);
|
|
|
|
|
|
|
|
|
|
prevc = 0;
|
1998-04-10 09:41:28 -04:00
|
|
|
|
while ((c = getc (infile)) && c != EOF)
|
1991-12-06 16:00:31 -05:00
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
if (p == str)
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr, "missing name or number");
|
|
|
|
|
dump_and_abort (-1, -1, infile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-03-18 04:55:53 -05:00
|
|
|
|
/* Provide a version of a function to read a long long if the system does
|
|
|
|
|
not provide one. */
|
|
|
|
|
#if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
|
|
|
|
|
HOST_WIDE_INT
|
|
|
|
|
atoll(p)
|
|
|
|
|
const char *p;
|
|
|
|
|
{
|
|
|
|
|
int neg = 0;
|
|
|
|
|
HOST_WIDE_INT tmp_wide;
|
|
|
|
|
|
1998-05-06 08:56:58 -04:00
|
|
|
|
while (ISSPACE(*p))
|
1998-03-18 04:55:53 -05:00
|
|
|
|
p++;
|
|
|
|
|
if (*p == '-')
|
|
|
|
|
neg = 1, p++;
|
|
|
|
|
else if (*p == '+')
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
tmp_wide = 0;
|
1998-05-06 08:56:58 -04:00
|
|
|
|
while (ISDIGIT(*p))
|
1998-03-18 04:55:53 -05:00
|
|
|
|
{
|
|
|
|
|
HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
|
|
|
|
|
if (new_wide < tmp_wide)
|
|
|
|
|
{
|
|
|
|
|
/* Return INT_MAX equiv on overflow. */
|
|
|
|
|
tmp_wide = (~(unsigned HOST_WIDE_INT)0) >> 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
tmp_wide = new_wide;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (neg)
|
|
|
|
|
tmp_wide = -tmp_wide;
|
|
|
|
|
return tmp_wide;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
/* 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;
|
1992-07-06 16:15:06 -04:00
|
|
|
|
HOST_WIDE_INT tmp_wide;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
/* 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_MODES; 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 'V':
|
|
|
|
|
/* 'V' is an optional vector: if a closeparen follows,
|
|
|
|
|
just store NULL for this element. */
|
|
|
|
|
c = read_skip_spaces (infile);
|
|
|
|
|
ungetc (c, infile);
|
|
|
|
|
if (c == ')')
|
|
|
|
|
{
|
|
|
|
|
XVEC (return_rtx, i) = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Now process the vector. */
|
|
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
|
{
|
|
|
|
|
register struct rtx_list *next_rtx, *rtx_list_link;
|
1998-01-17 17:00:51 -05:00
|
|
|
|
struct rtx_list *list_rtx = NULL;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
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
|
1992-07-06 16:15:06 -04:00
|
|
|
|
? rtvec_alloc (list_counter) : NULL_RTVEC);
|
1991-12-06 16:00:31 -05:00
|
|
|
|
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':
|
|
|
|
|
/* 'S' is an optional string: if a closeparen follows,
|
|
|
|
|
just store NULL for this element. */
|
|
|
|
|
c = read_skip_spaces (infile);
|
|
|
|
|
ungetc (c, infile);
|
|
|
|
|
if (c == ')')
|
|
|
|
|
{
|
|
|
|
|
XSTR (return_rtx, i) = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
{
|
|
|
|
|
int saw_paren = 0;
|
|
|
|
|
register char *stringbuf;
|
|
|
|
|
|
|
|
|
|
c = read_skip_spaces (infile);
|
|
|
|
|
if (c == '(')
|
|
|
|
|
{
|
|
|
|
|
saw_paren = 1;
|
|
|
|
|
c = read_skip_spaces (infile);
|
|
|
|
|
}
|
|
|
|
|
if (c != '"')
|
|
|
|
|
dump_and_abort ('"', c, infile);
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
1992-05-09 03:00:44 -04:00
|
|
|
|
c = getc (infile); /* Read the string */
|
|
|
|
|
if (c == '\\')
|
1991-12-06 16:00:31 -05:00
|
|
|
|
{
|
1992-05-09 03:00:44 -04:00
|
|
|
|
c = getc (infile); /* Read the string */
|
1991-12-06 16:00:31 -05:00
|
|
|
|
/* \; makes stuff for a C string constant containing
|
|
|
|
|
newline and tab. */
|
1992-05-09 03:00:44 -04:00
|
|
|
|
if (c == ';')
|
1992-05-09 11:47:31 -04:00
|
|
|
|
{
|
|
|
|
|
obstack_grow (rtl_obstack, "\\n\\t", 4);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
1992-05-09 03:00:44 -04:00
|
|
|
|
else if (c == '"')
|
1991-12-06 16:00:31 -05:00
|
|
|
|
break;
|
1992-05-09 03:00:44 -04:00
|
|
|
|
|
|
|
|
|
obstack_1grow (rtl_obstack, c);
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
|
1992-05-09 03:00:44 -04:00
|
|
|
|
obstack_1grow (rtl_obstack, 0);
|
|
|
|
|
stringbuf = (char *) obstack_finish (rtl_obstack);
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
if (saw_paren)
|
|
|
|
|
{
|
|
|
|
|
c = read_skip_spaces (infile);
|
|
|
|
|
if (c != ')')
|
|
|
|
|
dump_and_abort (')', c, infile);
|
|
|
|
|
}
|
|
|
|
|
XSTR (return_rtx, i) = stringbuf;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
1992-07-06 16:15:06 -04:00
|
|
|
|
case 'w':
|
|
|
|
|
read_name (tmp_char, infile);
|
|
|
|
|
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
|
|
|
|
|
tmp_wide = atoi (tmp_char);
|
|
|
|
|
#else
|
1998-01-28 18:25:15 -05:00
|
|
|
|
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
|
1992-07-06 16:15:06 -04:00
|
|
|
|
tmp_wide = atol (tmp_char);
|
1998-01-28 18:25:15 -05:00
|
|
|
|
#else
|
1998-03-18 04:55:53 -05:00
|
|
|
|
/* Prefer atoll over atoq, since the former is in the ISO C9X draft.
|
|
|
|
|
But prefer not to use our hand-rolled function above either. */
|
|
|
|
|
#if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
|
1998-01-30 03:04:59 -05:00
|
|
|
|
tmp_wide = atoll (tmp_char);
|
|
|
|
|
#else
|
1998-01-28 18:25:15 -05:00
|
|
|
|
tmp_wide = atoq (tmp_char);
|
|
|
|
|
#endif
|
1998-01-30 03:04:59 -05:00
|
|
|
|
#endif
|
1992-07-06 16:15:06 -04:00
|
|
|
|
#endif
|
|
|
|
|
XWINT (return_rtx, i) = tmp_wide;
|
|
|
|
|
break;
|
|
|
|
|
|
1991-12-06 16:00:31 -05:00
|
|
|
|
case 'i':
|
|
|
|
|
case 'n':
|
|
|
|
|
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.
|
1992-01-04 17:39:21 -05:00
|
|
|
|
It initializes the vector `rtx_length', the extra CC modes, if any,
|
|
|
|
|
and computes certain commonly-used modes. */
|
1991-12-06 16:00:31 -05:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_rtl ()
|
|
|
|
|
{
|
1992-01-04 17:39:21 -05:00
|
|
|
|
int min_class_size[(int) MAX_MODE_CLASS];
|
|
|
|
|
enum machine_mode mode;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
|
|
|
rtx_length[i] = strlen (rtx_format[i]);
|
|
|
|
|
|
|
|
|
|
/* Make CONST_DOUBLE bigger, if real values are bigger than
|
|
|
|
|
it normally expects to have room for.
|
|
|
|
|
Note that REAL_VALUE_TYPE is not defined by default,
|
|
|
|
|
since tree.h is not included. But the default dfn as `double'
|
|
|
|
|
would do no harm. */
|
|
|
|
|
#ifdef REAL_VALUE_TYPE
|
|
|
|
|
i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
|
|
|
|
|
if (rtx_length[(int) CONST_DOUBLE] < i)
|
|
|
|
|
{
|
|
|
|
|
char *s = (char *) xmalloc (i + 1);
|
|
|
|
|
rtx_length[(int) CONST_DOUBLE] = i;
|
|
|
|
|
rtx_format[(int) CONST_DOUBLE] = s;
|
|
|
|
|
*s++ = 'e';
|
|
|
|
|
*s++ = '0';
|
|
|
|
|
/* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
|
1993-05-17 16:07:45 -04:00
|
|
|
|
of as many `w's as we now have elements. Subtract two from
|
|
|
|
|
the size to account for the 'e' and the '0'. */
|
|
|
|
|
for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
|
1992-07-06 16:15:06 -04:00
|
|
|
|
*s++ = 'w';
|
1991-12-06 16:00:31 -05:00
|
|
|
|
*s++ = 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef EXTRA_CC_MODES
|
|
|
|
|
for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
|
|
|
|
|
{
|
|
|
|
|
mode_class[i] = MODE_CC;
|
1998-10-23 00:09:58 -04:00
|
|
|
|
mode_mask_array[i] = mode_mask_array[(int) CCmode];
|
1991-12-06 16:00:31 -05:00
|
|
|
|
mode_size[i] = mode_size[(int) CCmode];
|
|
|
|
|
mode_unit_size[i] = mode_unit_size[(int) CCmode];
|
1998-10-01 12:47:41 -04:00
|
|
|
|
mode_wider_mode[i - 1] = i;
|
|
|
|
|
mode_wider_mode[i] = (unsigned char)VOIDmode;
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|
|
|
|
|
#endif
|
1992-01-04 17:39:21 -05:00
|
|
|
|
|
1993-10-07 17:05:34 -04:00
|
|
|
|
/* Find the narrowest mode for each class. */
|
1992-01-04 17:39:21 -05:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < (int) MAX_MODE_CLASS; i++)
|
|
|
|
|
min_class_size[i] = 1000;
|
|
|
|
|
|
|
|
|
|
for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
|
|
|
|
|
mode = (enum machine_mode) ((int) mode + 1))
|
|
|
|
|
{
|
|
|
|
|
if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
|
|
|
|
|
{
|
|
|
|
|
class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
|
|
|
|
|
min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
|
|
|
|
|
}
|
|
|
|
|
}
|
1991-12-06 16:00:31 -05:00
|
|
|
|
}
|