----------------------------------

GCC-2.6.1 COMES TO FREEBSD-current
----------------------------------
Everybody needs to 'make world'.

Oakland, Nov 2nd 1994.  In a surprise move this sunny afternoon, the release-
engineer for the slightly delayed FreeBSD-2.0, Poul-Henning Kamp (28),
decided to pull in the new version 2.6.1 of the GNU C-compiler.
The new version of the compiler was release today at noon, and hardly 9
hours later it was committed into the FreeBSD-current source-repository.
"It's is simply because we have had too much trouble with the version 2.6.0
of the compiler" Poul-Henning told the FreeBSD-Gazette, "we took a gamble
when we decided to use that as our compiler for the 2.0 release, but it
seems to pay of in the end now" he concludes.
The move has not been discussed on the "core" list at all, and will come as
a surprise for most Poul-Hennings peers.  "I have only discussed it with
Jordan [J. K. Hubbard, the FreeBSD's resident humourist], and we agreed that
we needed to do it, so ... I did it!".  After a breath he added with a grin:
"My email will probably get an all time 'disk-full' now!".
This will bring quite a flag-day to the FreeBSD developers, the patch-file
is almost 1.4 Megabyte, and they will have to run "make world" to get
entirely -current again.  "Too bad, but we just had to do this."  Was
the only comment from Poul-Henning to these problems.
When asked how this move would impact the 2.0 release-date, Poul-Hennings
face grew dark, he mumbled some very Danish words while he moved his fingers
in strange geometrical patterns.  Immediately something ecclipsed the Sun, a
minor tremor shook the buildings, and the temperature fell significantly.
We decided not to pursure the question.

-----------
JOB-SECTION
-----------
Are you a dedicated GCC-hacker ?
We BADLY need somebody to look at the 'freebsd' OS in gcc, sanitize it and
carry the patches back to the GNU people.  In particular, we need to get
out of the "i386-only" spot we are in now.  I have the stuff to take a
gnu-dist into bmake-form, and will do that part.

Please apply to phk@freebsd.org

No Novice Need Apply.
This commit is contained in:
Poul-Henning Kamp 1994-11-03 06:52:42 +00:00
parent e0115bffa0
commit fe7dee4700
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=4113
95 changed files with 17504 additions and 11186 deletions

View file

@ -0,0 +1,178 @@
diff -u -r /freebsd/gcc-2.6.1/cccp.c ./cccp.c
--- /freebsd/gcc-2.6.1/cccp.c Tue Oct 25 15:37:44 1994
+++ ./cccp.c Wed Nov 2 17:36:25 1994
@@ -188,7 +188,7 @@
#ifndef VMS
#ifndef HAVE_STRERROR
extern int sys_nerr;
-#if defined(bsd4_4) || defined(__NetBSD__)
+#if defined(bsd4_4) || defined(__NetBSD__) || defined(__FreeBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
Only in .: cccp.c.orig
Only in .: cccp.o
Only in .: cexp.o
diff -u -r /freebsd/gcc-2.6.1/collect2.c ./collect2.c
--- /freebsd/gcc-2.6.1/collect2.c Thu Oct 20 15:05:46 1994
+++ ./collect2.c Wed Nov 2 17:36:25 1994
@@ -41,7 +41,7 @@
extern int errno;
#endif
-#if defined(bsd4_4) || defined(__NetBSD__)
+#if defined(bsd4_4) || defined(__NetBSD__) || defined(__FreeBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
Only in .: collect2.c.orig
diff -u -r /freebsd/gcc-2.6.1/config/i386/freebsd.h ./config/i386/freebsd.h
--- /freebsd/gcc-2.6.1/config/i386/freebsd.h Tue Oct 18 17:59:52 1994
+++ ./config/i386/freebsd.h Wed Nov 2 17:36:37 1994
@@ -33,11 +33,13 @@
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__ -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)"
+#if 0
#define INCLUDE_DEFAULTS { \
{ "/usr/include", 0 }, \
{ "/usr/include/g++", 1 }, \
{ 0, 0} \
}
+#endif
/* Like the default, except no -lg. */
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
Only in ./config/i386: freebsd.h.orig
diff -u -r /freebsd/gcc-2.6.1/config/i386/x-freebsd ./config/i386/x-freebsd
--- /freebsd/gcc-2.6.1/config/i386/x-freebsd Mon Oct 31 04:52:41 1994
+++ ./config/i386/x-freebsd Wed Nov 2 18:45:36 1994
@@ -1,3 +1,6 @@
# Don't run fixproto
STMP_FIXPROTO =
-CLIB=-lgnumalloc
+CLIB = -lgnumalloc
+
+# Find FreeBSD's includes before resorting to GCC's
+LIBGCC2_INCLUDES -I/usr/include
Only in .: config.h
Only in .: config.status
Only in ./cp: Makefile
diff -u -r /freebsd/gcc-2.6.1/cp/g++.c ./cp/g++.c
--- /freebsd/gcc-2.6.1/cp/g++.c Sat Oct 29 04:17:44 1994
+++ ./cp/g++.c Wed Nov 2 17:36:42 1994
@@ -84,7 +84,7 @@
#endif
extern int sys_nerr;
-#if defined(bsd4_4) || defined(__NetBSD__)
+#if defined(bsd4_4) || defined(__NetBSD__) || defined(__FreeBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
Only in ./cp: g++.c.orig
Only in ./cp: include
Only in ./cp: stage1
Only in ./cp: stage2
Only in ./cp: stage3
Only in ./cp: stage4
Only in .: cpp
Only in .: float.h-nat
diff -u -r /freebsd/gcc-2.6.1/gcc.c ./gcc.c
--- /freebsd/gcc-2.6.1/gcc.c Thu Oct 27 15:49:58 1994
+++ ./gcc.c Wed Nov 2 17:36:43 1994
@@ -166,7 +166,7 @@
#endif
extern int sys_nerr;
-#if defined(bsd4_4) || defined(__NetBSD__)
+#if defined(bsd4_4) || defined(__NetBSD__) || defined (__FreeBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
Only in .: gcc.c.orig
Only in .: gfloat.h
diff -u -r /freebsd/gcc-2.6.1/ginclude/stdarg.h ./ginclude/stdarg.h
--- /freebsd/gcc-2.6.1/ginclude/stdarg.h Fri Jul 8 19:04:27 1994
+++ ./ginclude/stdarg.h Wed Nov 2 17:36:49 1994
@@ -136,13 +136,13 @@
But on BSD NET2 we must not test or define or undef it.
(Note that the comments in NET 2's ansi.h
are incorrect for _VA_LIST_--see stdio.h!) */
-#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__FreeBSD__)
+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__)
/* The macro _VA_LIST is used in SCO Unix 3.2. */
#ifndef _VA_LIST
/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
#ifndef _VA_LIST_T_H
#define _VA_LIST_T_H
-#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__FreeBSD__))
+#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__)
#define _VA_LIST_
#endif
#define _VA_LIST
Only in ./ginclude: stdarg.h.orig
diff -u -r /freebsd/gcc-2.6.1/ginclude/stddef.h ./ginclude/stddef.h
--- /freebsd/gcc-2.6.1/ginclude/stddef.h Fri Oct 7 16:22:35 1994
+++ ./ginclude/stddef.h Wed Nov 2 17:36:54 1994
@@ -22,7 +22,7 @@
/* On 4.3bsd-net2, make sure ansi.h is included, so we have
one less case to deal with in the following. */
-#if defined (__BSD_NET2__) || defined (____386BSD____) || defined (__FreeBSD__)
+#if defined (__BSD_NET2__) || defined (____386BSD____)
#include <machine/ansi.h>
#endif
Only in ./ginclude: stddef.h.orig
diff -u -r /freebsd/gcc-2.6.1/ginclude/varargs.h ./ginclude/varargs.h
--- /freebsd/gcc-2.6.1/ginclude/varargs.h Fri Jul 8 19:04:32 1994
+++ ./ginclude/varargs.h Wed Nov 2 17:36:59 1994
@@ -151,13 +151,13 @@
/* Michael Eriksson <mer@sics.se> at Thu Sep 30 11:00:57 1993:
Sequent defines _VA_LIST_ in <machine/machtypes.h> to be the type to
use for va_list (``typedef _VA_LIST_ va_list'') */
-#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)
+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__)
/* The macro _VA_LIST is used in SCO Unix 3.2. */
#ifndef _VA_LIST
/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
#ifndef _VA_LIST_T_H
#define _VA_LIST_T_H
-#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
+#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__)
#define _VA_LIST_
#endif
#define _VA_LIST
Only in ./ginclude: varargs.h.orig
Only in .: hconfig.h
Only in .: include
Only in .: libgcc.a
Only in .: libgcc1.a
Only in .: libgcc2.a
Only in .: libgcc2.ready
Only in .: md
Only in .: multilib.h
Only in .: objc-headers
Only in .: obstack.o
diff -u -r /freebsd/gcc-2.6.1/protoize.c ./protoize.c
--- /freebsd/gcc-2.6.1/protoize.c Tue Oct 4 20:17:40 1994
+++ ./protoize.c Wed Nov 2 17:37:00 1994
@@ -79,7 +79,7 @@
#undef getopt
extern int errno;
-#if defined(bsd4_4) || defined(__NetBSD__)
+#if defined(bsd4_4) || defined(__NetBSD__) || defined (__FreeBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
Only in .: protoize.c.orig
Only in .: stage1
Only in .: stmp-fixinc
Only in .: stmp-headers
Only in .: stmp-int-hdrs
Only in .: tconfig.h
Only in .: tm.h
Only in .: version.o
Only in .: xlimits.h

261
gnu/gnu2bmake/gcc-2.6.1.tcl Executable file
View file

@ -0,0 +1,261 @@
#!/usr/local/bin/tclsh
#
# ----------------------------------------------------------------------------
# "THE BEER-WARE LICENSE" (Revision 42):
# <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
# ----------------------------------------------------------------------------
#
# $FreeBSD$
#
source gnu2bmake.tcl
#######################################################################
# Parameters to tweak
########
set sdir /freebsd/A/gcc-2.6.1
set ddir /freebsd/A/cc261
#######################################################################
# Do the stunt
########
sh "cd $sdir ; sh configure i386--freebsd"
# .h files on their way to ~/include
set l_include {config tm pcp tree input c-lex c-tree flags machmode real
rtl c-parse c-gperf function defaults convert obstack insn-attr
bytecode bc-emit insn-flags expr insn-codes regs hard-reg-set
insn-config loop recog bc-typecd bc-opcode bc-optab typeclass
output basic-block reload integrate conditions bytetypes bi-run
bc-arity multilib stack}
# other files on their way to ~/include
set l_include_x {tree.def machmode.def rtl.def modemap.def bc-typecd.def}
# .h files going into ~/include/i386
set l_include_i386 {perform gstabs gas bsd i386 unix }
# .c source for cpp
set l_cpp {cccp cexp version}
# .c source for cc1
set l_cc1 [zap_suffix [makefile_macro C_OBJS $sdir]]
append l_cc1 " " [zap_suffix [makefile_macro OBJS $sdir]]
append l_cc1 " " [zap_suffix [makefile_macro BC_OBJS $sdir]]
# .c source for cc
set l_cc {gcc version}
append l_cc " " [zap_suffix [makefile_macro OBSTACK $sdir]]
# .c source for c++
set l_cplus [zap_suffix [makefile_macro OBSTACK $sdir]]
# .c source for c++ from "cp" subdir
set l_cplus_cp {g++}
# .c source for cc1plus
set l_cc1plus {c-common}
append l_cc1plus " " [zap_suffix [makefile_macro OBJS $sdir]]
append l_cc1plus " " [zap_suffix [makefile_macro BC_OBJS $sdir]]
# .c source for cc1plus from "cp" subdir
set l_cc1plus_cp {}
append l_cc1plus_cp " " [zap_suffix [makefile_macro CXX_OBJS $sdir/cp]]
# .h file for cc1plus from "cp" subdir
set l_cc1plus_h {lex parse cp-tree decl class hash}
# other file for cc1plus from "cp" subdir
set l_cc1plus_x {tree.def input.c}
# All files used more than once go into the lib.
set l_common [common_set $l_cpp $l_cc1 $l_cc $l_cc1plus $l_cplus]
set l_cpp [reduce_by $l_cpp $l_common]
set l_cc1 [reduce_by $l_cc1 $l_common]
set l_cc [reduce_by $l_cc $l_common]
set l_cplus [reduce_by $l_cplus $l_common]
set l_cc1plus [reduce_by $l_cc1plus $l_common]
# functions in libgcc1
set l_libgcc1 [makefile_macro LIB1FUNCS $sdir]
# functions in libgcc2
set l_libgcc2 [makefile_macro LIB2FUNCS $sdir]
# .c files in libgcc
set l_libgcc {libgcc1.c libgcc2.c}
# .h files in libgcc
set l_libgcc_h {tconfig longlong glimits gbl-ctors}
set version [makefile_macro version $sdir]
set target [makefile_macro target $sdir]
# do ~
sh "rm -rf $ddir"
sh "mkdir $ddir"
set f [open $ddir/Makefile.inc w]
puts $f "#\n# \$FreeBSD\$\n#\n"
puts $f "CFLAGS+=\t-I\${.CURDIR} -I\${.CURDIR}/../include"
puts $f "CFLAGS+=\t-Dbsd4_4"
puts $f "CFLAGS+=\t-DGCC_INCLUDE_DIR=\\\"FOO\\\""
puts $f "CFLAGS+=\t-DGPLUSPLUS_INCLUDE_DIR=\\\"FOO\\\""
puts $f "CFLAGS+=\t-DTOOL_INCLUDE_DIR=\\\"FOO\\\""
puts $f "CFLAGS+=\t-DDEFAULT_TARGET_VERSION=\\\"$version\\\""
puts $f "CFLAGS+=\t-DDEFAULT_TARGET_MACHINE=\\\"$target\\\""
puts $f "CFLAGS+=\t-DMD_EXEC_PREFIX=\\\"/usr/libexec/\\\""
puts $f "CFLAGS+=\t-DSTANDARD_STARTFILE_PREFIX=\\\"/usr/lib\\\""
close $f
set f [open $ddir/Makefile w]
puts $f "#\n# \$FreeBSD\$\n#\n"
puts $f "PGMDIR=\tcc_int cpp cc1 cc cc1plus c++ libgcc"
puts $f "SUBDIR=\t\$(PGMDIR)"
puts $f "\n.include <bsd.subdir.mk>"
close $f
# do ~/legal
sh "mkdir $ddir/legal"
sh "cp $sdir/gen-*.c $sdir/md $ddir/legal"
set f [open $ddir/README w]
puts $f {
$FreeBSD$
This directory contains gcc in a form that uses "bmake" makefiles.
This is not the place you want to start, if you want to hack gcc.
we have included everything here which is part of the source-code
of gcc, but still, don't use this as a hacking-base.
If you suspect a problem with gcc, or just want to hack it in general,
get a complete gcc-X.Y.Z.tar.gz from somewhere, and use that.
Please look in the directory src/gnu/gnu2bmake to find the tools
to generate these files.
Thankyou.
}
# do ~/libgcc
sh "mkdir $ddir/libgcc"
set f [open $ddir/libgcc/Makefile w]
puts $f "#\n# \$FreeBSD\$\n#\n"
puts $f "LIB=\tgcc"
puts $f "INSTALL_PIC_ARCHIVE=\tyes"
puts $f "SHLIB_MAJOR=\t26"
puts $f "SHLIB_MINOR=\t1"
puts $f ""
puts $f "LIB1OBJS=\t[add_suffix $l_libgcc1 .o]"
puts $f "LIB2OBJS=\t[add_suffix $l_libgcc2 .o]"
puts $f {
OBJS= ${LIB1OBJS} ${LIB2OBJS}
LIB1SOBJS=${LIB1OBJS:.o=.so}
LIB2SOBJS=${LIB2OBJS:.o=.so}
P1OBJS=${LIB1OBJS:.o=.po}
P2OBJS=${LIB2OBJS:.o=.po}
${LIB1OBJS}: libgcc1.c
${CC} -c ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc1.c
@${LD} -x -r ${.TARGET}
@mv a.out ${.TARGET}
${LIB2OBJS}: libgcc2.c
${CC} -c ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc2.c
@${LD} -x -r ${.TARGET}
@mv a.out ${.TARGET}
.if !defined(NOPIC)
${LIB1SOBJS}: libgcc1.c
${CC} -c -fpic ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc1.c
${LIB2SOBJS}: libgcc2.c
${CC} -c -fpic ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc2.c
.endif
.if !defined(NOPROFILE)
${P1OBJS}: libgcc1.c
${CC} -c -p ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc1.c
${P2OBJS}: libgcc2.c
${CC} -c -p ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.CURDIR}/libgcc2.c
.endif
.include <bsd.lib.mk>
}
close $f
copy_c $sdir $ddir/libgcc $l_libgcc
# do ~/include
sh "mkdir $ddir/include"
copy_l $sdir $ddir/include [add_suffix $l_include .h]
copy_l $sdir $ddir/include $l_include_x
copy_l $sdir $ddir/include [add_suffix $l_libgcc_h .h]
# do ~/include/i386
sh "mkdir $ddir/include/i386"
copy_l $sdir/config/i386 $ddir/include/i386 [add_suffix $l_include_i386 .h]
# do ~/cc_int
mk_lib $ddir cc_int [add_suffix $l_common .c] {
"NOPROFILE=\t1"
"\ninstall:\n\t@true"
}
copy_c $sdir $ddir/cc_int $l_common
# do ~/cpp
mk_prog $ddir cpp [add_suffix $l_cpp .c] {
"BINDIR=\t/usr/libexec"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int/obj"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int"
"LDADD+=\t-lcc_int"
}
copy_c $sdir $ddir/cpp $l_cpp
cp $sdir/cpp.1 $ddir/cpp/cpp.1
# do ~/c++
mk_prog $ddir c++ [add_suffix "$l_cplus $l_cplus_cp" .c] {
"BINDIR=\t/usr/bin"
"NOMAN=\t1"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int/obj"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int"
"LDADD+=\t-lcc_int"
}
copy_c $sdir $ddir/c++ $l_cplus
copy_c $sdir/cp $ddir/c++ $l_cplus_cp
# do ~/cc
mk_prog $ddir cc [add_suffix $l_cc .c] {
"BINDIR=\t/usr/bin"
"MLINKS+=cc.1 gcc.1"
"MLINKS+=cc.1 c++.1"
"MLINKS+=cc.1 g++.1"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int/obj"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int"
"LDADD+=\t-lcc_int"
"\nafterinstall:\n\tcd \$(DESTDIR)\$(BINDIR) ; rm gcc ; ln -s cc gcc"
}
copy_c $sdir $ddir/cc $l_cc
cp $sdir/gcc.1 $ddir/cc/cc.1
# do ~/cc1
mk_prog $ddir cc1 [add_suffix $l_cc1 .c] {
"BINDIR=\t/usr/libexec"
"NOMAN=\t1"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int/obj"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int"
"LDADD+=\t-lcc_int"
}
copy_c $sdir $ddir/cc1 $l_cc1
# do ~/cc1plus
mk_prog $ddir cc1plus [add_suffix "$l_cc1plus_cp $l_cc1plus" .c] {
"BINDIR=\t/usr/libexec"
"NOMAN=\t1"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int/obj"
"LDDESTDIR+=\t-L\${.CURDIR}/../cc_int"
"LDADD+=\t-lcc_int"
}
copy_l $sdir/cp $ddir/cc1plus $l_cc1plus_x
copy_c $sdir $ddir/cc1plus $l_cc1plus
copy_c $sdir/cp $ddir/cc1plus $l_cc1plus_cp
copy_l $sdir/cp $ddir/cc1plus [add_suffix $l_cc1plus_h .h]
exit 0

View file

@ -5,10 +5,10 @@
LIB= gcc LIB= gcc
INSTALL_PIC_ARCHIVE= yes INSTALL_PIC_ARCHIVE= yes
SHLIB_MAJOR= 26 SHLIB_MAJOR= 26
SHLIB_MINOR= 0 SHLIB_MINOR= 1
LIB1OBJS= _mulsi3.o _udivsi3.o _divsi3.o _umodsi3.o _modsi3.o _lshrsi3.o _lshlsi3.o _ashrsi3.o _ashlsi3.o _divdf3.o _muldf3.o _negdf2.o _adddf3.o _subdf3.o _fixdfsi.o _fixsfsi.o _floatsidf.o _floatsisf.o _truncdfsf2.o _extendsfdf2.o _addsf3.o _negsf2.o _subsf3.o _mulsf3.o _divsf3.o _eqdf2.o _nedf2.o _gtdf2.o _gedf2.o _ltdf2.o _ledf2.o _eqsf2.o _nesf2.o _gtsf2.o _gesf2.o _ltsf2.o _lesf2.o LIB1OBJS= _mulsi3.o _udivsi3.o _divsi3.o _umodsi3.o _modsi3.o _lshrsi3.o _lshlsi3.o _ashrsi3.o _ashlsi3.o _divdf3.o _muldf3.o _negdf2.o _adddf3.o _subdf3.o _fixdfsi.o _fixsfsi.o _floatsidf.o _floatsisf.o _truncdfsf2.o _extendsfdf2.o _addsf3.o _negsf2.o _subsf3.o _mulsf3.o _divsf3.o _eqdf2.o _nedf2.o _gtdf2.o _gedf2.o _ltdf2.o _ledf2.o _eqsf2.o _nesf2.o _gtsf2.o _gesf2.o _ltsf2.o _lesf2.o
LIB2OBJS= _muldi3.o _divdi3.o _moddi3.o _udivdi3.o _umoddi3.o _negdi2.o _lshrdi3.o _lshldi3.o _ashldi3.o _ashrdi3.o _ffsdi2.o _udiv_w_sdiv.o _udivmoddi4.o _cmpdi2.o _ucmpdi2.o _floatdidf.o _floatdisf.o _fixunsdfsi.o _fixunssfsi.o _fixunsdfdi.o _fixdfdi.o _fixunssfdi.o _fixsfdi.o _fixxfdi.o _fixunsxfdi.o _floatdixf.o _fixunsxfsi.o _fixtfdi.o _fixunstfdi.o _floatditf.o __gcc_bcmp.o _varargs.o _eprintf.o _op_new.o _op_vnew.o _new_handler.o _op_delete.o _op_vdel.o _bb.o _shtab.o _clear_cache.o _trampoline.o __main.o _exit.o _ctors.o LIB2OBJS= _muldi3.o _divdi3.o _moddi3.o _udivdi3.o _umoddi3.o _negdi2.o _lshrdi3.o _lshldi3.o _ashldi3.o _ashrdi3.o _ffsdi2.o _udiv_w_sdiv.o _udivmoddi4.o _cmpdi2.o _ucmpdi2.o _floatdidf.o _floatdisf.o _fixunsdfsi.o _fixunssfsi.o _fixunsdfdi.o _fixdfdi.o _fixunssfdi.o _fixsfdi.o _fixxfdi.o _fixunsxfdi.o _floatdixf.o _fixunsxfsi.o _fixtfdi.o _fixunstfdi.o _floatditf.o __gcc_bcmp.o _varargs.o _eprintf.o _op_new.o _op_vnew.o _new_handler.o _op_delete.o _op_vdel.o _bb.o _shtab.o _clear_cache.o _trampoline.o __main.o _exit.o _ctors.o _eh.o _pure.o
OBJS= ${LIB1OBJS} ${LIB2OBJS} OBJS= ${LIB1OBJS} ${LIB2OBJS}
LIB1SOBJS=${LIB1OBJS:.o=.so} LIB1SOBJS=${LIB1OBJS:.o=.so}

View file

@ -1,11 +1,13 @@
# #
# $Id: Makefile.inc,v 1.5 1994/09/19 21:37:42 wollman Exp $ # $Id: Makefile.inc,v 1.6 1994/10/25 07:02:18 davidg Exp $
# #
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../include CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../include
CFLAGS+= -Dbsd4_4 CFLAGS+= -Dbsd4_4
CFLAGS+= -DGCC_INCLUDE_DIR=\"FOO\" CFLAGS+= -DGCC_INCLUDE_DIR=\"FOO\"
CFLAGS+= -DDEFAULT_TARGET_VERSION=\"2.6.0\" CFLAGS+= -DTOOL_INCLUDE_DIR=\"FOO\"
CFLAGS+= -DGPLUSPLUS_INCLUDE_DIR=\"FOO\"
CFLAGS+= -DDEFAULT_TARGET_VERSION=\"2.6.1\"
CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"i386--freebsd\" CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"i386--freebsd\"
CFLAGS+= -DMD_EXEC_PREFIX=\"/usr/libexec/\" CFLAGS+= -DMD_EXEC_PREFIX=\"/usr/libexec/\"
CFLAGS+= -DSTANDARD_STARTFILE_PREFIX=\"/usr/lib\" CFLAGS+= -DSTANDARD_STARTFILE_PREFIX=\"/usr/lib\"

View file

@ -1,5 +1,5 @@
$FreeBSD$ $Id$
This directory contains gcc in a form that uses "bmake" makefiles. This directory contains gcc in a form that uses "bmake" makefiles.
This is not the place you want to start, if you want to hack gcc. This is not the place you want to start, if you want to hack gcc.

View file

@ -40,6 +40,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/file.h> /* May get R_OK, etc. on some systems. */ #include <sys/file.h> /* May get R_OK, etc. on some systems. */
#include <errno.h>
/* Defined to the name of the compiler; if using a cross compiler, the /* Defined to the name of the compiler; if using a cross compiler, the
Makefile should compile this file with the proper name Makefile should compile this file with the proper name
@ -78,8 +79,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif #endif
#endif #endif
extern int errno, sys_nerr; #ifndef errno
#if defined(bsd4_4) || defined(__NetBSD__) extern int errno;
#endif
extern int sys_nerr;
#if defined(bsd4_4) || defined(__NetBSD__) || defined(__FreeBSD__)
extern const char *const sys_errlist[]; extern const char *const sys_errlist[];
#else #else
extern char *sys_errlist[]; extern char *sys_errlist[];
@ -390,7 +395,7 @@ main (argc, argv)
#endif #endif
args = (int *) malloc (argc * sizeof (int)); args = (int *) malloc (argc * sizeof (int));
bzero (args, argc * sizeof (int)); bzero ((char *) args, argc * sizeof (int));
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{ {
@ -431,7 +436,7 @@ main (argc, argv)
&& (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL) && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|| strcmp (argv[i], "-Tdata") == 0)) || strcmp (argv[i], "-Tdata") == 0))
quote = argv[i]; quote = argv[i];
else if (((argv[i][2] == '\0' else if (library != NULL && ((argv[i][2] == '\0'
&& (char *) strchr ("cSEM", argv[i][1]) != NULL) && (char *) strchr ("cSEM", argv[i][1]) != NULL)
|| strcmp (argv[i], "-MM") == 0)) || strcmp (argv[i], "-MM") == 0))
{ {
@ -449,7 +454,10 @@ main (argc, argv)
int len; int len;
if (saw_speclang) if (saw_speclang)
continue; {
saw_speclang = 0;
continue;
}
/* If the filename ends in .c or .i, put options around it. /* If the filename ends in .c or .i, put options around it.
But not if a specified -x option is currently active. */ But not if a specified -x option is currently active. */

File diff suppressed because it is too large Load diff

View file

@ -1303,6 +1303,7 @@ duplicate_decls (newdecl, olddecl)
&& DECL_INITIAL (newdecl) != 0); && DECL_INITIAL (newdecl) != 0);
tree oldtype = TREE_TYPE (olddecl); tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl); tree newtype = TREE_TYPE (newdecl);
char *errmsg = 0;
if (TREE_CODE (newtype) == ERROR_MARK if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK) || TREE_CODE (oldtype) == ERROR_MARK)
@ -1528,7 +1529,7 @@ duplicate_decls (newdecl, olddecl)
} }
else else
{ {
char *errmsg = redeclaration_error_message (newdecl, olddecl); errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg) if (errmsg)
{ {
error_with_decl (newdecl, errmsg); error_with_decl (newdecl, errmsg);
@ -1625,7 +1626,7 @@ duplicate_decls (newdecl, olddecl)
} }
/* Optionally warn about more than one declaration for the same name. */ /* Optionally warn about more than one declaration for the same name. */
if (warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
/* Dont warn about a function declaration /* Dont warn about a function declaration
followed by a definition. */ followed by a definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
@ -2439,6 +2440,21 @@ shadow_label (name)
if (decl != 0) if (decl != 0)
{ {
register tree dup;
/* Check to make sure that the label hasn't already been declared
at this label scope */
for (dup = named_labels; dup; dup = TREE_CHAIN (dup))
if (TREE_VALUE (dup) == decl)
{
error ("duplicate label declaration `%s'",
IDENTIFIER_POINTER (name));
error_with_decl (TREE_VALUE (dup),
"this is a previous declaration");
/* Just use the previous declaration. */
return lookup_label (name);
}
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
IDENTIFIER_LABEL_VALUE (name) = decl = 0; IDENTIFIER_LABEL_VALUE (name) = decl = 0;
} }
@ -3673,7 +3689,7 @@ finish_decl (decl, init, asmspec_tree)
references to it. */ references to it. */
/* This test used to include TREE_STATIC, but this won't be set /* This test used to include TREE_STATIC, but this won't be set
for function level initializers. */ for function level initializers. */
if (TREE_READONLY (decl)) if (TREE_READONLY (decl) || ITERATOR_P (decl))
{ {
preserve_initializer (); preserve_initializer ();
/* Hack? Set the permanent bit for something that is permanent, /* Hack? Set the permanent bit for something that is permanent,
@ -5418,7 +5434,7 @@ finish_struct (t, fieldlist)
#endif #endif
} }
} }
else else if (TREE_TYPE (x) != error_mark_node)
{ {
int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
: TYPE_ALIGN (TREE_TYPE (x))); : TYPE_ALIGN (TREE_TYPE (x)));
@ -5646,37 +5662,6 @@ start_enum (name)
return enumtype; return enumtype;
} }
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
static int
min_precision (value, unsignedp)
tree value;
int unsignedp;
{
int log;
/* If the value is negative, compute its negative minus 1. The latter
adjustment is because the absolute value of the largest negative value
is one larger than the largest positive value. This is equivalent to
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
value = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (value), value));
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
if (integer_zerop (value))
log = 0;
else if (TREE_INT_CST_HIGH (value) != 0)
log = HOST_BITS_PER_WIDE_INT + floor_log2 (TREE_INT_CST_HIGH (value));
else
log = floor_log2 (TREE_INT_CST_LOW (value));
return log + 1 + ! unsignedp;
}
/* After processing and defining all the values of an enumeration type, /* After processing and defining all the values of an enumeration type,
install their decls in the enumeration type and finish it off. install their decls in the enumeration type and finish it off.
ENUMTYPE is the type object and VALUES a list of decl-value pairs. ENUMTYPE is the type object and VALUES a list of decl-value pairs.
@ -5868,6 +5853,7 @@ start_function (declspecs, declarator, nested)
{ {
tree decl1, old_decl; tree decl1, old_decl;
tree restype; tree restype;
int old_immediate_size_expand = immediate_size_expand;
current_function_returns_value = 0; /* Assume, until we see it does. */ current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0; current_function_returns_null = 0;
@ -5877,6 +5863,9 @@ start_function (declspecs, declarator, nested)
named_labels = 0; named_labels = 0;
shadowed_labels = 0; shadowed_labels = 0;
/* Don't expand any sizes in the return type of the function. */
immediate_size_expand = 0;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1); decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1);
/* If the declarator is not suitable for a function definition, /* If the declarator is not suitable for a function definition,
@ -5922,6 +5911,11 @@ start_function (declspecs, declarator, nested)
current_function_prototype_line = DECL_SOURCE_LINE (old_decl); current_function_prototype_line = DECL_SOURCE_LINE (old_decl);
} }
/* If there is no explicit declaration, look for any out-of-scope implicit
declarations. */
if (old_decl == 0)
old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1));
/* Optionally warn of old-fashioned def with no previous prototype. */ /* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
@ -5937,7 +5931,7 @@ start_function (declspecs, declarator, nested)
if the function has already been used. */ if the function has already been used. */
else if (warn_missing_prototypes else if (warn_missing_prototypes
&& old_decl != 0 && TREE_USED (old_decl) && old_decl != 0 && TREE_USED (old_decl)
&& !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)) && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
warning_with_decl (decl1, warning_with_decl (decl1,
"`%s' was used with no prototype before its definition"); "`%s' was used with no prototype before its definition");
/* Optionally warn of any global def with no previous declaration. */ /* Optionally warn of any global def with no previous declaration. */
@ -5949,7 +5943,8 @@ start_function (declspecs, declarator, nested)
/* Optionally warn of any def with no previous declaration /* Optionally warn of any def with no previous declaration
if the function has already been used. */ if the function has already been used. */
else if (warn_missing_declarations else if (warn_missing_declarations
&& old_decl != 0 && TREE_USED (old_decl)) && old_decl != 0 && TREE_USED (old_decl)
&& old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
warning_with_decl (decl1, warning_with_decl (decl1,
"`%s' was used with no declaration before its definition"); "`%s' was used with no declaration before its definition");
@ -6006,6 +6001,8 @@ start_function (declspecs, declarator, nested)
if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl))) if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
TREE_ADDRESSABLE (current_function_decl) = 1; TREE_ADDRESSABLE (current_function_decl) = 1;
immediate_size_expand = old_immediate_size_expand;
return 1; return 1;
} }

View file

@ -395,9 +395,9 @@ static const short yyrline[] = { 0,
1576, 1585, 1590, 1595, 1600, 1604, 1608, 1619, 1626, 1633, 1576, 1585, 1590, 1595, 1600, 1604, 1608, 1619, 1626, 1633,
1640, 1651, 1655, 1658, 1663, 1686, 1720, 1745, 1774, 1789, 1640, 1651, 1655, 1658, 1663, 1686, 1720, 1745, 1774, 1789,
1800, 1804, 1808, 1811, 1816, 1818, 1821, 1823, 1827, 1832, 1800, 1804, 1808, 1811, 1816, 1818, 1821, 1823, 1827, 1832,
1835, 1841, 1846, 1851, 1853, 1862, 1863, 1869, 1871, 1876, 1835, 1841, 1846, 1851, 1853, 1862, 1863, 1869, 1871, 1881,
1878, 1882, 1885, 1891, 1894, 1896, 1898, 1900, 1907, 1912, 1883, 1887, 1890, 1896, 1899, 1901, 1903, 1905, 1912, 1917,
1917, 1919, 1928, 1931, 1936, 1939 1922, 1924, 1933, 1936, 1941, 1944
}; };
static const char * const yytname[] = { "$","error","$illegal.","IDENTIFIER", static const char * const yytname[] = { "$","error","$illegal.","IDENTIFIER",
@ -3252,60 +3252,65 @@ case 348:
case 349: case 349:
#line 1872 "c-parse.y" #line 1872 "c-parse.y"
{ yyval.ttype = get_parm_info (0); { yyval.ttype = get_parm_info (0);
if (pedantic) /* Gcc used to allow this as an extension. However, it does
pedwarn ("ANSI C requires a named argument before `...'"); not work for all targets, and thus has been disabled.
Also, since func (...) and func () are indistinguishable,
it caused problems with the code in expand_builtin which
tries to verify that BUILT_IN_NEXT_ARG is being used
correctly. */
error ("ANSI C requires a named argument before `...'");
; ;
break;} break;}
case 350: case 350:
#line 1877 "c-parse.y" #line 1882 "c-parse.y"
{ yyval.ttype = get_parm_info (1); ; { yyval.ttype = get_parm_info (1); ;
break;} break;}
case 351: case 351:
#line 1879 "c-parse.y" #line 1884 "c-parse.y"
{ yyval.ttype = get_parm_info (0); ; { yyval.ttype = get_parm_info (0); ;
break;} break;}
case 352: case 352:
#line 1884 "c-parse.y" #line 1889 "c-parse.y"
{ push_parm_decl (yyvsp[0].ttype); ; { push_parm_decl (yyvsp[0].ttype); ;
break;} break;}
case 353: case 353:
#line 1886 "c-parse.y" #line 1891 "c-parse.y"
{ push_parm_decl (yyvsp[0].ttype); ; { push_parm_decl (yyvsp[0].ttype); ;
break;} break;}
case 354: case 354:
#line 1893 "c-parse.y" #line 1898 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ; { yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ;
break;} break;}
case 355: case 355:
#line 1895 "c-parse.y" #line 1900 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ; { yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ;
break;} break;}
case 356: case 356:
#line 1897 "c-parse.y" #line 1902 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ; { yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;} break;}
case 357: case 357:
#line 1899 "c-parse.y" #line 1904 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ; { yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype) ; ;
break;} break;}
case 358: case 358:
#line 1901 "c-parse.y" #line 1906 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ; { yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;} break;}
case 359: case 359:
#line 1908 "c-parse.y" #line 1913 "c-parse.y"
{ pushlevel (0); { pushlevel (0);
clear_parm_order (); clear_parm_order ();
declare_parm_level (1); ; declare_parm_level (1); ;
break;} break;}
case 360: case 360:
#line 1912 "c-parse.y" #line 1917 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; { yyval.ttype = yyvsp[0].ttype;
parmlist_tags_warning (); parmlist_tags_warning ();
poplevel (0, 0, 0); ; poplevel (0, 0, 0); ;
break;} break;}
case 362: case 362:
#line 1920 "c-parse.y" #line 1925 "c-parse.y"
{ tree t; { tree t;
for (t = yyvsp[-1].ttype; t; t = TREE_CHAIN (t)) for (t = yyvsp[-1].ttype; t; t = TREE_CHAIN (t))
if (TREE_VALUE (t) == NULL_TREE) if (TREE_VALUE (t) == NULL_TREE)
@ -3313,19 +3318,19 @@ case 362:
yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ; yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ;
break;} break;}
case 363: case 363:
#line 1930 "c-parse.y" #line 1935 "c-parse.y"
{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; { yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
break;} break;}
case 364: case 364:
#line 1932 "c-parse.y" #line 1937 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; { yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;} break;}
case 365: case 365:
#line 1938 "c-parse.y" #line 1943 "c-parse.y"
{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; { yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
break;} break;}
case 366: case 366:
#line 1940 "c-parse.y" #line 1945 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; { yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;} break;}
} }
@ -3526,5 +3531,5 @@ case 366:
yystate = yyn; yystate = yyn;
goto yynewstate; goto yynewstate;
} }
#line 1943 "c-parse.y" #line 1948 "c-parse.y"

View file

@ -655,7 +655,8 @@ type_lists_compatible_p (args1, args2)
/* Allow wait (union {union wait *u; int *i} *) /* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */ and wait (union wait *) to be compatible. */
if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
&& TYPE_NAME (TREE_VALUE (args1)) == 0 && (TYPE_NAME (TREE_VALUE (args1)) == 0
|| TYPE_TRANSPARENT_UNION (TREE_VALUE (args1)))
&& TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)), && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)),
TYPE_SIZE (TREE_VALUE (args2)))) TYPE_SIZE (TREE_VALUE (args2))))
@ -669,7 +670,8 @@ type_lists_compatible_p (args1, args2)
return 0; return 0;
} }
else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
&& TYPE_NAME (TREE_VALUE (args2)) == 0 && (TYPE_NAME (TREE_VALUE (args2)) == 0
|| TYPE_TRANSPARENT_UNION (TREE_VALUE (args2)))
&& TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)), && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)),
TYPE_SIZE (TREE_VALUE (args1)))) TYPE_SIZE (TREE_VALUE (args1))))
@ -990,8 +992,11 @@ default_conversion (exp)
/* Constants can be used directly unless they're not loadable. */ /* Constants can be used directly unless they're not loadable. */
if (TREE_CODE (exp) == CONST_DECL) if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp); exp = DECL_INITIAL (exp);
/* Replace a nonvolatile const static variable with its value. */
else if (optimize && TREE_CODE (exp) == VAR_DECL) /* Replace a nonvolatile const static variable with its value unless
it is an array, in which case we must be sure that taking the
address of the array produces consistent results. */
else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
{ {
exp = decl_constant_value (exp); exp = decl_constant_value (exp);
type = TREE_TYPE (exp); type = TREE_TYPE (exp);
@ -1630,36 +1635,27 @@ convert_arguments (typelist, values, name, fundecl)
} }
else else
{ {
#if 0 /* This turns out not to win--there's no way to write a prototype
for a function whose arg type is a union with no tag. */
/* Nameless union automatically casts the types it contains. */
if (TREE_CODE (type) == UNION_TYPE && TYPE_NAME (type) == 0)
{
tree field;
for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
TYPE_MAIN_VARIANT (TREE_TYPE (val))))
break;
if (field)
val = build1 (CONVERT_EXPR, type, val);
}
#endif
/* Optionally warn about conversions that /* Optionally warn about conversions that
differ from the default conversions. */ differ from the default conversions. */
if (warn_conversion) if (warn_conversion)
{ {
int formal_prec = TYPE_PRECISION (type); int formal_prec = TYPE_PRECISION (type);
if (TREE_CODE (type) != REAL_TYPE if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1); warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) != REAL_TYPE) && INTEGRAL_TYPE_P (TREE_TYPE (val)))
warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1); warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
/* ??? At some point, messages should be written about
conversions between complex types, but that's too messy
to do now. */
else if (TREE_CODE (type) == REAL_TYPE else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
{ {
@ -1669,10 +1665,8 @@ convert_arguments (typelist, values, name, fundecl)
warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1); warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
} }
/* Detect integer changing in width or signedness. */ /* Detect integer changing in width or signedness. */
else if ((TREE_CODE (type) == INTEGER_TYPE else if (INTEGRAL_TYPE_P (type)
|| TREE_CODE (type) == ENUMERAL_TYPE) && INTEGRAL_TYPE_P (TREE_TYPE (val)))
&& (TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE))
{ {
tree would_have_been = default_conversion (val); tree would_have_been = default_conversion (val);
tree type1 = TREE_TYPE (would_have_been); tree type1 = TREE_TYPE (would_have_been);
@ -2798,7 +2792,7 @@ build_unary_op (code, xarg, noconvert)
((code == PREINCREMENT_EXPR ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR) || code == POSTINCREMENT_EXPR)
? "increment" : "decrement")); ? "increment" : "decrement"));
inc = c_sizeof_nowarn (TREE_TYPE (result_type)); inc = c_size_in_bytes (TREE_TYPE (result_type));
} }
else else
inc = integer_one_node; inc = integer_one_node;
@ -3211,6 +3205,18 @@ mark_addressable (exp)
IDENTIFIER_POINTER (DECL_NAME (x))); IDENTIFIER_POINTER (DECL_NAME (x)));
return 0; return 0;
} }
/* If we are making this addressable due to its having
volatile components, give a different error message. Also
handle the case of an unnamed parameter by not trying
to give the name. */
else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
{
error ("cannot put object with volatile field into register");
return 0;
}
pedwarn ("address of register variable `%s' requested", pedwarn ("address of register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x))); IDENTIFIER_POINTER (DECL_NAME (x)));
} }
@ -3868,14 +3874,15 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
/* Arithmetic types all interconvert, and enum is treated like int. */ /* Arithmetic types all interconvert, and enum is treated like int. */
if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
|| codel == COMPLEX_TYPE) || codel == COMPLEX_TYPE)
&& && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE
(coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE))
|| coder == COMPLEX_TYPE))
return convert_and_check (type, rhs); return convert_and_check (type, rhs);
/* Conversion to a union from its member types. */ /* Conversion to a union from its member types. */
else if (codel == UNION_TYPE) else if (codel == UNION_TYPE)
{ {
tree memb_types; tree memb_types;
for (memb_types = TYPE_FIELDS (type); memb_types; for (memb_types = TYPE_FIELDS (type); memb_types;
memb_types = TREE_CHAIN (memb_types)) memb_types = TREE_CHAIN (memb_types))
{ {
@ -3886,6 +3893,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
pedwarn ("ANSI C prohibits argument conversion to union type"); pedwarn ("ANSI C prohibits argument conversion to union type");
return build1 (NOP_EXPR, type, rhs); return build1 (NOP_EXPR, type, rhs);
} }
else if (coder == POINTER_TYPE else if (coder == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE) && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
{ {
@ -3895,44 +3903,59 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
/* Any non-function converts to a [const][volatile] void * /* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same. and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */ Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
if (TYPE_MAIN_VARIANT (ttl) == void_type_node if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node || TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (memb_type, rhstype)) || comp_target_types (memb_type, rhstype))
{ {
/* Const and volatile mean something different for function types, /* Const and volatile mean something different for function
so the usual warnings are not appropriate. */ types, so the usual warnings are not appropriate. */
if (TREE_CODE (ttr) != FUNCTION_TYPE if (TREE_CODE (ttr) != FUNCTION_TYPE
|| TREE_CODE (ttl) != FUNCTION_TYPE) || TREE_CODE (ttl) != FUNCTION_TYPE)
{ {
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
warn_for_assignment ("%s discards `const' from pointer target type", warn_for_assignment ("%s discards `const' from pointer target type",
get_spelling (errtype), funname, parmnum); get_spelling (errtype), funname,
parmnum);
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
warn_for_assignment ("%s discards `volatile' from pointer target type", warn_for_assignment ("%s discards `volatile' from pointer target type",
get_spelling (errtype), funname, parmnum); get_spelling (errtype), funname,
parmnum);
} }
else else
{ {
/* Because const and volatile on functions are restrictions /* Because const and volatile on functions are
that say the function will not do certain things, restrictions that say the function will not do
it is okay to use a const or volatile function certain things, it is okay to use a const or volatile
where an ordinary one is wanted, but not vice-versa. */ function where an ordinary one is wanted, but not
vice-versa. */
if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr)) if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
warn_for_assignment ("%s makes `const *' function pointer from non-const", warn_for_assignment ("%s makes `const *' function pointer from non-const",
get_spelling (errtype), funname, parmnum); get_spelling (errtype), funname,
parmnum);
if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr)) if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile", warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
get_spelling (errtype), funname, parmnum); get_spelling (errtype), funname,
parmnum);
} }
if (pedantic if (pedantic
&& !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl))) && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl)))
pedwarn ("ANSI C prohibits argument conversion to union type"); pedwarn ("ANSI C prohibits argument conversion to union type");
return build1 (NOP_EXPR, type, rhs); return build1 (NOP_EXPR, type, rhs);
} }
} }
/* Can convert integer zero to any pointer type. */
else if (TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE
&& (integer_zerop (rhs)
|| (TREE_CODE (rhs) == NOP_EXPR
&& integer_zerop (TREE_OPERAND (rhs, 0)))))
return build1 (NOP_EXPR, type, null_pointer_node);
} }
} }
/* Conversions among pointers */ /* Conversions among pointers */
else if (codel == POINTER_TYPE && coder == POINTER_TYPE) else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
{ {
@ -5155,8 +5178,8 @@ push_init_level (implicit)
/* Structure elements may require alignment. Do this now /* Structure elements may require alignment. Do this now
if necessary for the subaggregate. */ if necessary for the subaggregate. */
if (constructor_incremental && TREE_CODE (constructor_type) == RECORD_TYPE if (constructor_incremental && constructor_type != 0
&& constructor_fields) && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields)
{ {
/* Advance to offset of this element. */ /* Advance to offset of this element. */
if (! tree_int_cst_equal (constructor_bit_index, if (! tree_int_cst_equal (constructor_bit_index,
@ -6020,6 +6043,7 @@ process_init_element (value)
/* Otherwise, if we have come to a subaggregate, /* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */ and we don't have an element of its type, push into it. */
else if (value != 0 && !constructor_no_implicit else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE)) || fieldcode == UNION_TYPE))
@ -6083,6 +6107,7 @@ process_init_element (value)
/* Otherwise, if we have come to a subaggregate, /* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */ and we don't have an element of its type, push into it. */
else if (value != 0 && !constructor_no_implicit else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE)) || fieldcode == UNION_TYPE))
@ -6126,6 +6151,7 @@ process_init_element (value)
/* Otherwise, if we have come to a subaggregate, /* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */ and we don't have an element of its type, push into it. */
else if (value != 0 && !constructor_no_implicit else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE)) || eltcode == UNION_TYPE))
@ -6142,6 +6168,10 @@ process_init_element (value)
break; break;
} }
/* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
if (constructor_range_end)
value = save_expr (value);
/* Now output the actual element. /* Now output the actual element.
Ordinarily, output once. Ordinarily, output once.
If there is a range, repeat it till we advance past the range. */ If there is a range, repeat it till we advance past the range. */

View file

@ -700,11 +700,17 @@ compute_conversion_costs (function, tta_in, cp, arglen)
int strike_index = 0, win; int strike_index = 0, win;
struct harshness_code lose; struct harshness_code lose;
extern int cp_silent;
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
n_compute_conversion_costs++; n_compute_conversion_costs++;
#endif #endif
#ifndef DEBUG_MATCHING
/* We don't emit any warnings or errors while trying out each candidate. */
cp_silent = 1;
#endif
cp->function = function; cp->function = function;
cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE; cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;
cp->u.bad_arg = 0; /* optimistic! */ cp->u.bad_arg = 0; /* optimistic! */
@ -712,7 +718,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
cp->h.code = 0; cp->h.code = 0;
cp->h.distance = 0; cp->h.distance = 0;
cp->h.int_penalty = 0; cp->h.int_penalty = 0;
bzero (cp->harshness, bzero ((char *) cp->harshness,
(cp->h_len + 1) * sizeof (struct harshness_code)); (cp->h_len + 1) * sizeof (struct harshness_code));
while (ttf && tta) while (ttf && tta)
@ -812,6 +818,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
{ {
cp->h.code = EVIL_CODE; cp->h.code = EVIL_CODE;
cp->u.bad_arg = -1; cp->u.bad_arg = -1;
cp_silent = 0;
return; return;
} }
else else
@ -833,6 +840,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
{ {
cp->h.code = EVIL_CODE; cp->h.code = EVIL_CODE;
cp->u.bad_arg = -2; cp->u.bad_arg = -2;
cp_silent = 0;
return; return;
} }
/* Store index of first default. */ /* Store index of first default. */
@ -855,6 +863,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
if (dont_convert_types) if (dont_convert_types)
{ {
cp->h.code = EVIL_CODE; cp->h.code = EVIL_CODE;
cp_silent = 0;
return; return;
} }
@ -1002,6 +1011,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
cp->h.code |= ELLIPSIS_CODE; cp->h.code |= ELLIPSIS_CODE;
if (user_strikes) if (user_strikes)
cp->h.code |= USER_CODE; cp->h.code |= USER_CODE;
cp_silent = 0;
#ifdef DEBUG_MATCHING #ifdef DEBUG_MATCHING
cp_error ("final eval %s", print_harshness (&cp->h)); cp_error ("final eval %s", print_harshness (&cp->h));
#endif #endif
@ -1428,11 +1438,11 @@ build_scoped_method_call (exp, scopes, name, parms)
if (type != basetype) if (type != basetype)
cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
exp, basetype, type); exp, basetype, type);
name = IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0)); name = TREE_OPERAND (name, 0);
if (basetype != name) if (basetype != get_type_value (name))
cp_error ("qualified type `%T' does not match destructor type `%T'", cp_error ("qualified type `%T' does not match destructor name `~%T'",
basetype, name); basetype, name);
return void_zero_node; return convert (void_type_node, exp);
} }
if (! is_aggr_typedef (basename, 1)) if (! is_aggr_typedef (basename, 1))
@ -1460,15 +1470,16 @@ build_scoped_method_call (exp, scopes, name, parms)
{ {
/* Explicit call to destructor. */ /* Explicit call to destructor. */
name = TREE_OPERAND (name, 0); name = TREE_OPERAND (name, 0);
if (name != constructor_name (TREE_TYPE (decl))) if (! (name == constructor_name (TREE_TYPE (decl))
|| TREE_TYPE (decl) == get_type_value (name)))
{ {
cp_error cp_error
("qualified type `%T' does not match destructor type `%T'", ("qualified type `%T' does not match destructor name `~%T'",
TREE_TYPE (decl), name); TREE_TYPE (decl), name);
return error_mark_node; return error_mark_node;
} }
if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
return void_zero_node; return convert (void_type_node, exp);
return build_delete (TREE_TYPE (decl), decl, integer_two_node, return build_delete (TREE_TYPE (decl), decl, integer_two_node,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
@ -1604,23 +1615,19 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (parms) if (parms)
error ("destructors take no parameters"); error ("destructors take no parameters");
basetype = TREE_TYPE (instance); basetype = TREE_TYPE (instance);
if (IS_AGGR_TYPE (basetype)) if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
if (! ((IS_AGGR_TYPE (basetype)
&& name == constructor_name (basetype))
|| basetype == get_type_value (name)))
{ {
if (name == constructor_name (basetype)) cp_error ("destructor name `~%D' does not match type `%T' of expression",
goto huzzah; name, basetype);
return convert (void_type_node, instance);
} }
else
{
if (basetype == get_type_value (name))
goto huzzah;
}
cp_error ("destructor name `~%D' does not match type `%T' of expression",
name, basetype);
return void_zero_node;
huzzah:
if (! TYPE_HAS_DESTRUCTOR (basetype)) if (! TYPE_HAS_DESTRUCTOR (basetype))
return void_zero_node; return convert (void_type_node, instance);
instance = default_conversion (instance); instance = default_conversion (instance);
instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
return build_delete (build_pointer_type (basetype), return build_delete (build_pointer_type (basetype),
@ -1806,7 +1813,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
} }
else else
{ {
if (TREE_CODE (instance) != CALL_EXPR) if (TREE_CODE (instance) != CALL_EXPR
#ifdef PCC_STATIC_STRUCT_RETURN
&& TREE_CODE (instance) != RTL_EXPR
#endif
)
my_friendly_abort (125); my_friendly_abort (125);
if (TYPE_NEEDS_CONSTRUCTING (basetype)) if (TYPE_NEEDS_CONSTRUCTING (basetype))
instance = build_cplus_new (basetype, instance, 0); instance = build_cplus_new (basetype, instance, 0);
@ -1897,6 +1908,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0); TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
} }
#if 0
/* This breaks reference-to-array parameters. */
if (TREE_CODE (t) == ARRAY_TYPE) if (TREE_CODE (t) == ARRAY_TYPE)
{ {
/* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place. /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
@ -1904,6 +1917,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm)); TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
t = TREE_TYPE (TREE_VALUE (parm)); t = TREE_TYPE (TREE_VALUE (parm));
} }
#endif
if (t == error_mark_node) if (t == error_mark_node)
return error_mark_node; return error_mark_node;
last = build_tree_list (NULL_TREE, t); last = build_tree_list (NULL_TREE, t);
@ -1932,7 +1946,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
constp = 0; constp = 0;
volatilep = 0; volatilep = 0;
parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms); parms = tree_cons (NULL_TREE,
build1 (NOP_EXPR, TYPE_POINTER_TO (basetype),
integer_zero_node), parms);
} }
else else
{ {
@ -1945,6 +1961,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_CALLS_NEW (instance_ptr) = 1; TREE_CALLS_NEW (instance_ptr) = 1;
instance = build_indirect_ref (instance_ptr, NULL_PTR); instance = build_indirect_ref (instance_ptr, NULL_PTR);
#if 0
/* This breaks initialization of a reference from a new
expression of a different type. And it doesn't appear to
serve its original purpose any more, either. jason 10/12/94 */
/* If it's a default argument initialized from a ctor, what we get /* If it's a default argument initialized from a ctor, what we get
from instance_ptr will match the arglist for the FUNCTION_DECL from instance_ptr will match the arglist for the FUNCTION_DECL
of the constructor. */ of the constructor. */
@ -1953,6 +1973,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1)))) && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
parms = build_tree_list (NULL_TREE, instance_ptr); parms = build_tree_list (NULL_TREE, instance_ptr);
else else
#endif
parms = tree_cons (NULL_TREE, instance_ptr, parms); parms = tree_cons (NULL_TREE, instance_ptr, parms);
} }
} }
@ -2012,6 +2033,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
return error_mark_node; return error_mark_node;
#if 0
/* Now, go look for this method name. We do not find destructors here. /* Now, go look for this method name. We do not find destructors here.
Putting `void_list_node' on the end of the parmtypes Putting `void_list_node' on the end of the parmtypes
@ -2021,6 +2043,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
1 + (name == constructor_name (save_basetype) 1 + (name == constructor_name (save_basetype)
|| name == constructor_name_full (save_basetype))); || name == constructor_name_full (save_basetype)));
TREE_CHAIN (last) = NULL_TREE; TREE_CHAIN (last) = NULL_TREE;
#endif
for (pass = 0; pass < 2; pass++) for (pass = 0; pass < 2; pass++)
{ {
@ -2040,7 +2063,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
candidates candidates
= (struct candidate *) alloca ((ever_seen+1) = (struct candidate *) alloca ((ever_seen+1)
* sizeof (struct candidate)); * sizeof (struct candidate));
bzero (candidates, (ever_seen + 1) * sizeof (struct candidate)); bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate));
cp = candidates; cp = candidates;
len = list_length (parms); len = list_length (parms);
ever_seen = 0; ever_seen = 0;
@ -2062,7 +2085,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
tree new_type; tree new_type;
parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
new_type = c_build_type_variant (TREE_TYPE (parm), constp, new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
volatilep); volatilep);
new_type = build_reference_type (new_type); new_type = build_reference_type (new_type);
parm = convert (new_type, parm); parm = convert (new_type, parm);
@ -2147,9 +2170,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& ! DECL_STATIC_FUNCTION_P (function)) && ! DECL_STATIC_FUNCTION_P (function))
continue; continue;
#if 0
if (pass == 0 if (pass == 0
&& DECL_ASSEMBLER_NAME (function) == method_name) && DECL_ASSEMBLER_NAME (function) == method_name)
goto found; goto found;
#endif
if (pass > 0) if (pass > 0)
{ {
@ -2244,6 +2269,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (cp - candidates > 1) if (cp - candidates > 1)
{ {
int n_candidates = cp - candidates; int n_candidates = cp - candidates;
extern int warn_synth;
TREE_VALUE (parms) = instance_ptr; TREE_VALUE (parms) = instance_ptr;
cp = ideal_candidate (save_basetype, candidates, cp = ideal_candidate (save_basetype, candidates,
n_candidates, parms, len); n_candidates, parms, len);
@ -2251,14 +2277,25 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
if (flags & LOOKUP_COMPLAIN) if (flags & LOOKUP_COMPLAIN)
{ {
cp_error ("call of overloaded %s `%D' is ambiguous", TREE_CHAIN (last) = void_list_node;
name_kind, name); cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
name_kind, name, TREE_CHAIN (parmtypes));
print_n_candidates (candidates, n_candidates); print_n_candidates (candidates, n_candidates);
} }
return error_mark_node; return error_mark_node;
} }
if (cp->h.code & EVIL_CODE) if (cp->h.code & EVIL_CODE)
return error_mark_node; return error_mark_node;
if (warn_synth
&& DECL_NAME (cp->function) == ansi_opname[MODIFY_EXPR]
&& DECL_ARTIFICIAL (cp->function)
&& n_candidates == 2)
{
cp_warning ("using synthesized `%#D' for copy assignment",
cp->function);
cp_warning_at (" where cfront would use `%#D'",
candidates->function);
}
} }
else if (cp[-1].h.code & EVIL_CODE) else if (cp[-1].h.code & EVIL_CODE)
{ {
@ -2664,7 +2701,11 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
final_cp->h.code = EVIL_CODE; final_cp->h.code = EVIL_CODE;
return error_mark_node; return error_mark_node;
} }
if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == OFFSET_TYPE) if (TREE_CODE (t) == OFFSET_TYPE)
#if 0
/* This breaks reference-to-array parameters. */
|| TREE_CODE (t) == ARRAY_TYPE
#endif
{ {
/* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place. /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
Also convert OFFSET_TYPE entities to their normal selves. Also convert OFFSET_TYPE entities to their normal selves.
@ -2738,7 +2779,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
{ {
candidates candidates
= (struct candidate *)alloca ((length+1) * sizeof (struct candidate)); = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
bzero (candidates, (length + 1) * sizeof (struct candidate)); bzero ((char *) candidates, (length + 1) * sizeof (struct candidate));
} }
cp = candidates; cp = candidates;

View file

@ -942,7 +942,7 @@ add_method (type, fields, method)
* sizeof (char *) * sizeof (char *)
+ len * sizeof (tree)); + len * sizeof (tree));
tmp_vec = (tree) obstack_base (ob); tmp_vec = (tree) obstack_base (ob);
bcopy (method_vec, tmp_vec, bcopy ((char *) method_vec, (char *) tmp_vec,
(sizeof (struct tree_common) (sizeof (struct tree_common)
+ tree_code_length[(int) TREE_VEC] * sizeof (char *) + tree_code_length[(int) TREE_VEC] * sizeof (char *)
+ (len-1) * sizeof (tree))); + (len-1) * sizeof (tree)));
@ -992,20 +992,18 @@ add_method (type, fields, method)
not duplicates, they are just anonymous fields. This happens not duplicates, they are just anonymous fields. This happens
when we have unnamed bitfields, for example. */ when we have unnamed bitfields, for example. */
static tree static tree
delete_duplicate_fields_1 (field, field_ptr, fields) delete_duplicate_fields_1 (field, fields)
tree field, *field_ptr, fields; tree field, fields;
{ {
tree x; tree x;
tree prev = field_ptr ? *field_ptr : 0; tree prev = 0;
if (DECL_NAME (field) == 0) if (DECL_NAME (field) == 0)
{ {
if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)
return fields; return fields;
for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x))
fields = delete_duplicate_fields_1 (x, field_ptr, fields); fields = delete_duplicate_fields_1 (x, fields);
if (prev)
TREE_CHAIN (prev) = fields;
return fields; return fields;
} }
else else
@ -1017,7 +1015,7 @@ delete_duplicate_fields_1 (field, field_ptr, fields)
if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE)
continue; continue;
TYPE_FIELDS (TREE_TYPE (x)) TYPE_FIELDS (TREE_TYPE (x))
= delete_duplicate_fields_1 (field, (tree *)0, TYPE_FIELDS (TREE_TYPE (x))); = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x)));
if (TYPE_FIELDS (TREE_TYPE (x)) == 0) if (TYPE_FIELDS (TREE_TYPE (x)) == 0)
{ {
if (prev == 0) if (prev == 0)
@ -1039,7 +1037,7 @@ delete_duplicate_fields_1 (field, field_ptr, fields)
x); x);
else if (TREE_CODE (field) == TYPE_DECL else if (TREE_CODE (field) == TYPE_DECL
&& TREE_CODE (x) == TYPE_DECL) && TREE_CODE (x) == TYPE_DECL)
cp_error_at ("duplicate class scope type `%D'", x); cp_error_at ("duplicate nested type `%D'", x);
else if (TREE_CODE (field) == TYPE_DECL else if (TREE_CODE (field) == TYPE_DECL
|| TREE_CODE (x) == TYPE_DECL) || TREE_CODE (x) == TYPE_DECL)
cp_error_at ("duplicate field `%D' (as type and non-type)", cp_error_at ("duplicate field `%D' (as type and non-type)",
@ -1063,7 +1061,7 @@ delete_duplicate_fields (fields)
{ {
tree x; tree x;
for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x)) for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x))
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, &x, TREE_CHAIN (x)); TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
} }
/* Change the access of FDECL to ACCESS in T. /* Change the access of FDECL to ACCESS in T.
@ -1121,10 +1119,14 @@ get_vfield_offset (binfo)
BINFO_OFFSET (binfo)); BINFO_OFFSET (binfo));
} }
/* Get the offset to the start of the original binfo that we derived this /* Get the offset to the start of the original binfo that we derived
binfo from. */ this binfo from. If we find TYPE first, return the offset only
tree get_derived_offset (binfo) that far. The shortened search is useful because the this pointer
tree binfo; on method calling is expected to point to a DECL_CONTEXT (fndecl)
object, and not a baseclass of it. */
static tree
get_derived_offset (binfo, type)
tree binfo, type;
{ {
tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
tree offset2; tree offset2;
@ -1133,6 +1135,8 @@ tree get_derived_offset (binfo)
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
{ {
tree binfos = BINFO_BASETYPES (binfo); tree binfos = BINFO_BASETYPES (binfo);
if (BINFO_TYPE (binfo) == type)
break;
binfo = TREE_VEC_ELT (binfos, i); binfo = TREE_VEC_ELT (binfos, i);
} }
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
@ -1340,7 +1344,7 @@ finish_base_struct (t, b, t_binfo)
tree binfos = BINFO_BASETYPES (t_binfo); tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int first_vfn_base_index = -1; int first_vfn_base_index = -1;
bzero (b, sizeof (struct base_info)); bzero ((char *) b, sizeof (struct base_info));
for (i = 0; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
@ -1682,8 +1686,8 @@ finish_struct_bits (t, max_has_virtual)
tree *tmp; tree *tmp;
int i; int i;
bzero (first_conversions, sizeof (first_conversions)); bzero ((char *) first_conversions, sizeof (first_conversions));
bzero (last_conversions, sizeof (last_conversions)); bzero ((char *) last_conversions, sizeof (last_conversions));
for (tmp = &TREE_VEC_ELT (method_vec, 1); for (tmp = &TREE_VEC_ELT (method_vec, 1);
tmp != TREE_VEC_END (method_vec); tmp += 1) tmp != TREE_VEC_END (method_vec); tmp += 1)
{ {
@ -1830,8 +1834,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
{ {
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
if (TREE_CODE (parmtype) == REFERENCE_TYPE if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
{ {
if (TREE_PROTECTED (fn_fields)) if (TREE_PROTECTED (fn_fields))
TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1; TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
@ -1938,8 +1941,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
&& CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
&& DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE
&& warn_ctor_dtor_privacy) && warn_ctor_dtor_privacy)
warning ("class `%s' only defines a private destructor and has no friends", cp_warning ("`%#T' only defines a private destructor and has no friends",
TYPE_NAME_STRING (t)); t);
break; break;
} }
} }
@ -2060,7 +2063,7 @@ duplicate_tag_error (t)
int interface_only = CLASSTYPE_INTERFACE_ONLY (t); int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t); int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
bzero (TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE; BINFO_BASETYPES(binfo) = NULL_TREE;
CLASSTYPE_AS_LIST (t) = as_list; CLASSTYPE_AS_LIST (t) = as_list;
@ -2151,6 +2154,86 @@ overrides (fndecl, base_fndecl)
return 0; return 0;
} }
static tree
get_class_offset_1 (parent, binfo, context, t, fndecl)
tree parent, binfo, context, t, fndecl;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree rval = NULL_TREE;
if (binfo == parent)
return error_mark_node;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree nrval;
if (TREE_VIA_VIRTUAL (base_binfo))
base_binfo = binfo_member (BINFO_TYPE (base_binfo),
CLASSTYPE_VBASECLASSES (t));
nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
/* See if we have a new value */
if (nrval && (nrval != error_mark_node || rval==0))
{
/* Only compare if we have two offsets */
if (rval && rval != error_mark_node
&& ! tree_int_cst_equal (nrval, rval))
{
/* Only give error if the two offsets are different */
error ("every virtual function must have a unique final overrider");
cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t);
cp_error (" with virtual `%D' from virtual base class", fndecl);
return rval;
}
rval = nrval;
}
if (rval && BINFO_TYPE (binfo) == context)
{
my_friendly_assert (rval == error_mark_node
|| tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
rval = BINFO_OFFSET (binfo);
}
}
return rval;
}
/* Get the offset to the CONTEXT subobject that is related to the
given BINFO. */
static tree
get_class_offset (context, t, binfo, fndecl)
tree context, t, binfo, fndecl;
{
tree first_binfo = binfo;
tree offset;
int i;
if (context == t)
return integer_zero_node;
if (BINFO_TYPE (binfo) == context)
return BINFO_OFFSET (binfo);
/* Check less derived binfos first. */
while (BINFO_BASETYPES (binfo)
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
{
tree binfos = BINFO_BASETYPES (binfo);
binfo = TREE_VEC_ELT (binfos, i);
if (BINFO_TYPE (binfo) == context)
return BINFO_OFFSET (binfo);
}
/* Ok, not found in the less derived binfos, now check the more
derived binfos. */
offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl);
if (offset==0 || TREE_CODE (offset) != INTEGER_CST)
my_friendly_abort (999); /* we have to find it. */
return offset;
}
static void static void
modify_one_vtable (binfo, t, fndecl, pfn) modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn; tree binfo, t, fndecl, pfn;
@ -2174,16 +2257,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
tree vfield = CLASSTYPE_VFIELD (t); tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset; tree this_offset;
offset = integer_zero_node; offset = get_class_offset (context, t, binfo, fndecl);
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
/* Find the right offset for the this pointer based on the /* Find the right offset for the this pointer based on the
base class we just found. We have to take into base class we just found. We have to take into
@ -2193,7 +2267,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
Also, we want just the delta bewteen the most base class Also, we want just the delta bewteen the most base class
that we derived this vfield from and us. */ that we derived this vfield from and us. */
base_offset = size_binop (PLUS_EXPR, base_offset = size_binop (PLUS_EXPR,
get_derived_offset (binfo), get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)),
BINFO_OFFSET (binfo)); BINFO_OFFSET (binfo));
this_offset = size_binop (MINUS_EXPR, offset, base_offset); this_offset = size_binop (MINUS_EXPR, offset, base_offset);
@ -2288,16 +2362,7 @@ fixup_vtable_deltas (binfo, t)
tree vfield = CLASSTYPE_VFIELD (t); tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset; tree this_offset;
offset = integer_zero_node; offset = get_class_offset (context, t, binfo, fndecl);
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
/* Find the right offset for the this pointer based on the /* Find the right offset for the this pointer based on the
base class we just found. We have to take into base class we just found. We have to take into
@ -2307,7 +2372,7 @@ fixup_vtable_deltas (binfo, t)
Also, we want just the delta bewteen the most base class Also, we want just the delta bewteen the most base class
that we derived this vfield from and us. */ that we derived this vfield from and us. */
base_offset = size_binop (PLUS_EXPR, base_offset = size_binop (PLUS_EXPR,
get_derived_offset (binfo), get_derived_offset (binfo, DECL_CONTEXT (fndecl)),
BINFO_OFFSET (binfo)); BINFO_OFFSET (binfo));
this_offset = size_binop (MINUS_EXPR, offset, base_offset); this_offset = size_binop (MINUS_EXPR, offset, base_offset);
@ -2684,6 +2749,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
will fill in the right line number. (mrs) */ will fill in the right line number. (mrs) */
if (DECL_SOURCE_LINE (name)) if (DECL_SOURCE_LINE (name))
DECL_SOURCE_LINE (name) = lineno; DECL_SOURCE_LINE (name) = lineno;
CLASSTYPE_SOURCE_LINE (t) = lineno;
} }
name = DECL_NAME (name); name = DECL_NAME (name);
} }
@ -2713,18 +2779,15 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_GOT_SEMICOLON (t) = 0;
/* A signature type will contain the fields of the signature table. #if 0
Therefore, it's not only an interface. */ /* This is in general too late to do this. I moved the main case up to
if (IS_SIGNATURE (t)) left_curly, what else needs to move? */
if (! IS_SIGNATURE (t))
{ {
CLASSTYPE_INTERFACE_ONLY (t) = 0; my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
SET_CLASSTYPE_INTERFACE_KNOWN (t); my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999);
}
else
{
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
} }
#endif
if (flag_dossier) if (flag_dossier)
build_t_desc (t, 0); build_t_desc (t, 0);
@ -2787,14 +2850,15 @@ finish_struct (t, list_of_fieldlists, warn_anon)
needs_virtual_dtor = 0; needs_virtual_dtor = 0;
} }
#if 0
/* Both of these should be done before now. */
if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t) if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t)
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
{ {
CLASSTYPE_INTERFACE_ONLY (t) = interface_only; my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! interface_only; my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999);
} }
else if (IS_SIGNATURE (t)) #endif
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 0;
/* The three of these are approximations which may later be /* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function modified. Needed at this point to make add_virtual_function
@ -2951,6 +3015,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
} }
if (DECL_NAME (x) == constructor_name (t))
cant_have_default_ctor = cant_synth_copy_ctor = 1;
if (TREE_TYPE (x) == error_mark_node) if (TREE_TYPE (x) == error_mark_node)
continue; continue;
@ -3217,12 +3284,14 @@ finish_struct (t, list_of_fieldlists, warn_anon)
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init; CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals; CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
&& !IS_SIGNATURE (t)) && !IS_SIGNATURE (t))
{ {
/* Here we must cons up a destructor on the fly. */ /* Here we must cons up a destructor on the fly. */
tree dtor = cons_up_default_function (t, name, fields, tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0);
needs_virtual_dtor != 0);
/* If we couldn't make it work, then pretend we didn't need it. */ /* If we couldn't make it work, then pretend we didn't need it. */
if (dtor == void_type_node) if (dtor == void_type_node)
@ -3251,9 +3320,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
if (! fn_fields) if (! fn_fields)
nonprivate_method = 1; nonprivate_method = 1;
@ -3271,7 +3337,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
{ {
tree default_fn = cons_up_default_function (t, name, fields, 2); tree default_fn = cons_up_default_function (t, name, 2);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
@ -3282,9 +3348,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{ {
/* ARM 12.18: You get either X(X&) or X(const X&), but /* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */ not both. --Chip */
tree default_fn = tree default_fn = cons_up_default_function (t, name,
cons_up_default_function (t, name, fields, 3 + cant_have_const_ctor);
cant_have_const_ctor ? 4 : 3);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
@ -3298,9 +3363,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
{ {
tree default_fn = tree default_fn = cons_up_default_function (t, name,
cons_up_default_function (t, name, fields, 5 + no_const_asn_ref);
no_const_asn_ref ? 6 : 5);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
@ -3351,7 +3415,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree flist = NULL_TREE; tree flist = NULL_TREE;
tree name; tree name;
enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); enum access_type access = (enum access_type)TREE_PURPOSE(access_decls);
int i = 0; int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1;
tree tmp; tree tmp;
if (TREE_CODE (fdecl) == TREE_LIST) if (TREE_CODE (fdecl) == TREE_LIST)
@ -3459,6 +3523,27 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* Delete all duplicate fields from the fields */ /* Delete all duplicate fields from the fields */
delete_duplicate_fields (fields); delete_duplicate_fields (fields);
/* Catch function/field name conflict. We don't need to do this for a
signature, since it can only contain the fields constructed in
append_signature_fields. */
if (! IS_SIGNATURE (t))
{
int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
for (x = fields; x; x = TREE_CHAIN (x))
{
tree name = DECL_NAME (x);
int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1;
for (; i < n_methods; ++i)
if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
{
cp_error_at ("data member `%#D' conflicts with", x);
cp_error_at ("function member `%#D'",
TREE_VEC_ELT (method_vec, i));
break;
}
}
}
/* Now we have the final fieldlist for the data fields. Record it, /* Now we have the final fieldlist for the data fields. Record it,
then lay out the structure or union (including the fields). */ then lay out the structure or union (including the fields). */
@ -3498,6 +3583,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree uelt = TYPE_FIELDS (TREE_TYPE (field)); tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt)) for (; uelt; uelt = TREE_CHAIN (uelt))
{ {
if (TREE_CODE (uelt) != FIELD_DECL)
continue;
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
} }
@ -3552,6 +3640,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree uelt = TYPE_FIELDS (TREE_TYPE (field)); tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt)) for (; uelt; uelt = TREE_CHAIN (uelt))
{ {
if (TREE_CODE (uelt) != FIELD_DECL)
continue;
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
} }
@ -4634,11 +4725,42 @@ instantiate_type (lhstype, rhs, complain)
{ {
elem = get_first_fn (rhs); elem = get_first_fn (rhs);
while (elem) while (elem)
if (TREE_TYPE (elem) != lhstype) if (! comptypes (lhstype, TREE_TYPE (elem), 1))
elem = DECL_CHAIN (elem); elem = DECL_CHAIN (elem);
else else
return elem; return elem;
/* No exact match found, look for a compatible function. */
/* No exact match found, look for a compatible template. */
{
tree save_elem = 0;
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL)
{
int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
tree *t = (tree *) alloca (sizeof (tree) * n);
int i, d;
i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), &d, 0);
if (i == 0)
{
if (save_elem)
{
cp_error ("ambiguous template instantiation converting to `%#T'", lhstype);
return error_mark_node;
}
save_elem = instantiate_template (elem, t);
/* Check the return type. */
if (! comptypes (TREE_TYPE (lhstype),
TREE_TYPE (TREE_TYPE (save_elem)), 1))
save_elem = 0;
}
}
if (save_elem)
return save_elem;
}
/* No match found, look for a compatible function. */
elem = get_first_fn (rhs); elem = get_first_fn (rhs);
while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
elem = DECL_CHAIN (elem); elem = DECL_CHAIN (elem);
@ -4660,18 +4782,6 @@ instantiate_type (lhstype, rhs, complain)
} }
return error_mark_node; return error_mark_node;
} }
if (TREE_CODE (save_elem) == TEMPLATE_DECL)
{
int ntparms = TREE_VEC_LENGTH
(DECL_TEMPLATE_PARMS (save_elem));
tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
int i, dummy;
i = type_unification
(DECL_TEMPLATE_PARMS (save_elem), targs,
TYPE_ARG_TYPES (TREE_TYPE (save_elem)),
TYPE_ARG_TYPES (lhstype), &dummy, 0);
save_elem = instantiate_template (save_elem, targs);
}
return save_elem; return save_elem;
} }
if (complain) if (complain)
@ -4864,12 +4974,14 @@ instantiate_type (lhstype, rhs, complain)
} }
TREE_TYPE (rhs) = lhstype; TREE_TYPE (rhs) = lhstype;
lhstype = TREE_TYPE (lhstype); lhstype = TREE_TYPE (lhstype);
TREE_OPERAND (rhs, 0) {
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node) if (fn == error_mark_node)
return error_mark_node; return error_mark_node;
mark_addressable (fn);
mark_addressable (TREE_OPERAND (rhs, 0)); TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
}
return rhs; return rhs;
case ENTRY_VALUE_EXPR: case ENTRY_VALUE_EXPR:

View file

@ -502,8 +502,12 @@ struct lang_type
union tree_node *signature; union tree_node *signature;
union tree_node *signature_pointer_to; union tree_node *signature_pointer_to;
union tree_node *signature_reference_to; union tree_node *signature_reference_to;
int linenum;
}; };
#define CLASSTYPE_SOURCE_LINE(NODE) (TYPE_LANG_SPECIFIC(NODE)->linenum)
/* Indicates whether or not (and how) a template was expanded for this class. /* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class 0=no information yet/non-template class
1=implicit template instantiation 1=implicit template instantiation
@ -1355,7 +1359,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE. /* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */ NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code)); extern void binary_op_error PROTO((enum tree_code));
extern tree c_build_type_variant PROTO((tree, int, int)); extern tree cp_build_type_variant PROTO((tree, int, int));
extern void c_expand_expr_stmt PROTO((tree)); extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */ /* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree)); extern tree check_case_value PROTO((tree));
@ -2011,7 +2015,7 @@ extern void expand_end_all_catch PROTO((void));
extern void start_catch_block PROTO((tree, tree)); extern void start_catch_block PROTO((tree, tree));
extern void end_catch_block PROTO((void)); extern void end_catch_block PROTO((void));
extern void expand_throw PROTO((tree)); extern void expand_throw PROTO((tree));
extern void build_exception_table PROTO((void)); extern int build_exception_table PROTO((void));
extern tree build_throw PROTO((tree)); extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void)); extern void init_exception_processing PROTO((void));
@ -2091,7 +2095,7 @@ extern void reinit_parse_for_method PROTO((int, tree));
#if 0 #if 0
extern void reinit_parse_for_block PROTO((int, struct obstack *, int)); extern void reinit_parse_for_block PROTO((int, struct obstack *, int));
#endif #endif
extern tree cons_up_default_function PROTO((tree, tree, tree, int)); extern tree cons_up_default_function PROTO((tree, tree, int));
extern void check_for_missing_semicolon PROTO((tree)); extern void check_for_missing_semicolon PROTO((tree));
extern void note_got_semicolon PROTO((tree)); extern void note_got_semicolon PROTO((tree));
extern void note_list_got_semicolon PROTO((tree)); extern void note_list_got_semicolon PROTO((tree));
@ -2141,6 +2145,7 @@ extern void clear_anon_parm_name PROTO((void));
extern void do_inline_function_hair PROTO((tree, tree)); extern void do_inline_function_hair PROTO((tree, tree));
/* skip report_type_mismatch */ /* skip report_type_mismatch */
extern char *build_overload_name PROTO((tree, int, int)); extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree));
extern tree cplus_exception_name PROTO((tree)); extern tree cplus_exception_name PROTO((tree));
extern tree build_decl_overload PROTO((tree, tree, int)); extern tree build_decl_overload PROTO((tree, tree, int));
extern tree build_typename_overload PROTO((tree)); extern tree build_typename_overload PROTO((tree));
@ -2254,7 +2259,6 @@ extern tree copy_binfo PROTO((tree));
extern tree binfo_value PROTO((tree, tree)); extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree)); extern tree reverse_path PROTO((tree));
extern tree virtual_member PROTO((tree, tree)); extern tree virtual_member PROTO((tree, tree));
extern tree virtual_offset PROTO((tree, tree, tree));
extern void debug_binfo PROTO((tree)); extern void debug_binfo PROTO((tree));
extern int decl_list_length PROTO((tree)); extern int decl_list_length PROTO((tree));
extern int count_functions PROTO((tree)); extern int count_functions PROTO((tree));
@ -2360,7 +2364,7 @@ extern void GNU_xref_end PROTO((int));
extern void GNU_xref_file PROTO((char *)); extern void GNU_xref_file PROTO((char *));
extern void GNU_xref_start_scope PROTO((HOST_WIDE_INT)); extern void GNU_xref_start_scope PROTO((HOST_WIDE_INT));
extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int, int)); extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int, int));
extern void GNU_xref_def PROTO((tree, char *)); extern void GNU_xref_ref PROTO((tree, char *));
extern void GNU_xref_decl PROTO((tree, tree)); extern void GNU_xref_decl PROTO((tree, tree));
extern void GNU_xref_call PROTO((tree, char *)); extern void GNU_xref_call PROTO((tree, char *));
extern void GNU_xref_function PROTO((tree, tree)); extern void GNU_xref_function PROTO((tree, tree));

View file

@ -304,7 +304,7 @@ build_up_reference (type, arg, flags, checkconst)
/* Pass along const and volatile down into the type. */ /* Pass along const and volatile down into the type. */
if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
target_type = c_build_type_variant (target_type, TYPE_READONLY (type), target_type = cp_build_type_variant (target_type, TYPE_READONLY (type),
TYPE_VOLATILE (type)); TYPE_VOLATILE (type));
targ = arg; targ = arg;
if (TREE_CODE (targ) == SAVE_EXPR) if (TREE_CODE (targ) == SAVE_EXPR)
@ -425,10 +425,11 @@ build_up_reference (type, arg, flags, checkconst)
break; break;
case PARM_DECL: case PARM_DECL:
#if 0
if (targ == current_class_decl) if (targ == current_class_decl)
{ {
error ("address of `this' not available"); error ("address of `this' not available");
#if 0 /* #if 0 */
/* This code makes the following core dump the compiler on a sun4, /* This code makes the following core dump the compiler on a sun4,
if the code below is used. if the code below is used.
@ -465,16 +466,18 @@ build_up_reference (type, arg, flags, checkconst)
TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
put_var_into_stack (targ); put_var_into_stack (targ);
break; break;
#else /* #else */
return error_mark_node; return error_mark_node;
#endif /* #endif */
} }
#endif
/* Fall through. */ /* Fall through. */
case VAR_DECL: case VAR_DECL:
case CONST_DECL: case CONST_DECL:
if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)) if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)
warning ("address needed to build reference for `%s', which is declared `register'", && !DECL_ARTIFICIAL (targ))
IDENTIFIER_POINTER (DECL_NAME (targ))); cp_warning ("address needed to build reference for `%D', which is declared `register'",
targ);
else if (staticp (targ)) else if (staticp (targ))
literal_flag = 1; literal_flag = 1;
@ -491,6 +494,8 @@ build_up_reference (type, arg, flags, checkconst)
return rval; return rval;
} }
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
case INIT_EXPR: case INIT_EXPR:
{ {
@ -631,7 +636,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{ {
int r = TREE_READONLY (expr); int r = TREE_READONLY (expr);
int v = TREE_THIS_VOLATILE (expr); int v = TREE_THIS_VOLATILE (expr);
ttr = c_build_type_variant (TREE_TYPE (expr), r, v); ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
} }
if (! lvalue_p (expr) && if (! lvalue_p (expr) &&
@ -1206,6 +1211,9 @@ cp_convert (type, expr, convtype, flags)
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e); e = convert_from_reference (e);
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
if (TREE_READONLY_DECL_P (e)) if (TREE_READONLY_DECL_P (e))
e = decl_constant_value (e); e = decl_constant_value (e);
@ -1223,18 +1231,13 @@ cp_convert (type, expr, convtype, flags)
if (flag_pedantic_errors) if (flag_pedantic_errors)
return error_mark_node; return error_mark_node;
} }
if (form == OFFSET_TYPE) if (IS_AGGR_TYPE (intype))
cp_error_at ("pointer-to-member expression object not composed with type `%D' object",
TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)));
else if (IS_AGGR_TYPE (intype))
{ {
tree rval; tree rval;
rval = build_type_conversion (CONVERT_EXPR, type, e, 1); rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
if (rval) return rval; if (rval)
if (code == BOOLEAN_TYPE) return rval;
cp_error ("`%#T' used where a `bool' was expected", intype); cp_error ("`%#T' used where a `%T' was expected", intype, type);
else
cp_error ("`%#T' used where an `int' was expected", intype);
return error_mark_node; return error_mark_node;
} }
if (code == BOOLEAN_TYPE) if (code == BOOLEAN_TYPE)
@ -2021,11 +2024,16 @@ type_promotes_to (type)
wider. */ wider. */
else if (TREE_CODE (type) == ENUMERAL_TYPE else if (TREE_CODE (type) == ENUMERAL_TYPE
|| type == wchar_type_node) || type == wchar_type_node)
type = type_for_size {
(MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)), int precision = MAX (TYPE_PRECISION (type),
(flag_traditional TYPE_PRECISION (integer_type_node));
|| (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))) tree totype = type_for_size (precision, 0);
&& TREE_UNSIGNED (type)); if (TREE_UNSIGNED (type)
&& ! int_fits_type_p (TYPE_MAX_VALUE (type), totype))
type = type_for_size (precision, 1);
else
type = totype;
}
else if (C_PROMOTING_INTEGER_TYPE_P (type)) else if (C_PROMOTING_INTEGER_TYPE_P (type))
{ {
/* Traditionally, unsignedness is preserved in default promotions. /* Traditionally, unsignedness is preserved in default promotions.
@ -2040,5 +2048,5 @@ type_promotes_to (type)
else if (type == float_type_node) else if (type == float_type_node)
type = double_type_node; type = double_type_node;
return c_build_type_variant (type, constp, volatilep); return cp_build_type_variant (type, constp, volatilep);
} }

View file

@ -162,6 +162,8 @@ tree wchar_type_node;
tree signed_wchar_type_node; tree signed_wchar_type_node;
tree unsigned_wchar_type_node; tree unsigned_wchar_type_node;
tree wchar_decl_node;
tree float_type_node; tree float_type_node;
tree double_type_node; tree double_type_node;
tree long_double_type_node; tree long_double_type_node;
@ -401,6 +403,11 @@ extern int flag_short_double;
extern int flag_no_builtin; extern int flag_no_builtin;
/* Nonzero means don't recognize the non-ANSI builtin functions.
-ansi sets this. */
extern int flag_no_nonansi_builtin;
/* Nonzero means disable GNU extensions. */ /* Nonzero means disable GNU extensions. */
extern int flag_ansi; extern int flag_ansi;
@ -1743,6 +1750,7 @@ pushtag (name, type, globalize)
#else #else
d = build_decl (TYPE_DECL, name, type); d = build_decl (TYPE_DECL, name, type);
#endif #endif
SET_DECL_ARTIFICIAL (d);
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG) if (write_symbols == DWARF_DEBUG)
{ {
@ -1778,6 +1786,7 @@ pushtag (name, type, globalize)
/* Make nested declarations go into class-level scope. */ /* Make nested declarations go into class-level scope. */
newdecl = 1; newdecl = 1;
d = build_decl (TYPE_DECL, name, type); d = build_decl (TYPE_DECL, name, type);
SET_DECL_ARTIFICIAL (d);
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG) if (write_symbols == DWARF_DEBUG)
{ {
@ -1981,11 +1990,11 @@ decls_match (newdecl, olddecl)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
tree newarg = TREE_VEC_ELT (newargs, i); tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
tree oldarg = TREE_VEC_ELT (oldargs, i); tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
if (TREE_CODE (newarg) != TREE_CODE (oldarg)) if (TREE_CODE (newarg) != TREE_CODE (oldarg))
return 0; return 0;
else if (TREE_CODE (newarg) == IDENTIFIER_NODE) else if (TREE_CODE (newarg) == TYPE_DECL)
/* continue */; /* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1)) else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0; return 0;
@ -2104,6 +2113,7 @@ duplicate_decls (newdecl, olddecl)
after implicit decl. */ after implicit decl. */
; ;
else if (TREE_CODE (olddecl) == FUNCTION_DECL else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl)
&& (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
{ {
/* If you declare a built-in or predefined function name as static, /* If you declare a built-in or predefined function name as static,
@ -2188,9 +2198,8 @@ duplicate_decls (newdecl, olddecl)
newdecl); newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl); cp_error_at ("previous declaration `%#D' here", olddecl);
} }
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
{ {
cp_error ("new declaration `%#D'", newdecl); cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@ -2199,16 +2208,21 @@ duplicate_decls (newdecl, olddecl)
return 0; return 0;
} }
if (olddecl == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (newdecl))
cp_pedwarn ("redeclaration of wchar_t as `%T'",
TREE_TYPE (newdecl));
/* Throw away the redeclaration. */
return 1;
}
/* Already complained about this, so don't do so again. */ /* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{ {
/* Since we're doing this before finish_struct can set the cp_error ("conflicting types for `%#D'", newdecl);
line number on NEWDECL, we just do a regular error here. */
if (DECL_SOURCE_LINE (newdecl) == 0)
cp_error ("conflicting types for `%#D'", newdecl);
else
cp_error_at ("conflicting types for `%#D'", newdecl);
cp_error_at ("previous declaration as `%#D'", olddecl); cp_error_at ("previous declaration as `%#D'", olddecl);
} }
} }
@ -2521,12 +2535,15 @@ duplicate_decls (newdecl, olddecl)
DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl); DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
DECL_TEMPLATE_INSTANTIATIONS (newdecl) DECL_TEMPLATE_INSTANTIATIONS (newdecl)
= DECL_TEMPLATE_INSTANTIATIONS (olddecl); = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
if (DECL_CHAIN (newdecl) == NULL_TREE)
DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
} }
/* Now preserve various other info from the definition. */ /* Now preserve various other info from the definition. */
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl); TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl); TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl); DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
/* Don't really know how much of the language-specific /* Don't really know how much of the language-specific
values we should copy from old to new. */ values we should copy from old to new. */
@ -2678,7 +2695,8 @@ pushdecl (x)
/* don't do anything just yet */; /* don't do anything just yet */;
else if (TREE_CODE (t) != TREE_CODE (x)) else if (TREE_CODE (t) != TREE_CODE (x))
{ {
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL) if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
|| (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
{ {
/* We do nothing special here, because C++ does such nasty /* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL things with TYPE_DECLs. Instead, just let the TYPE_DECL
@ -3892,7 +3910,9 @@ lookup_name_real (name, prefer_type, nonclass)
if (got_scope != NULL_TREE) if (got_scope != NULL_TREE)
{ {
if (got_scope == void_type_node) if (got_scope == error_mark_node)
return error_mark_node;
else if (got_scope == void_type_node)
val = IDENTIFIER_GLOBAL_VALUE (name); val = IDENTIFIER_GLOBAL_VALUE (name);
else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM
/* TFIXME -- don't do this for UPTs in new model. */ /* TFIXME -- don't do this for UPTs in new model. */
@ -4540,14 +4560,29 @@ init_decl_processing ()
sizetype, sizetype,
endlink)), endlink)),
BUILT_IN_ALLOCA, "alloca"); BUILT_IN_ALLOCA, "alloca");
#if 0 /* Define alloca, ffs as builtins.
builtin_function ("alloca", Declare _exit just to mark it as volatile. */
build_function_type (ptr_type_node, if (! flag_no_builtin && !flag_no_nonansi_builtin)
tree_cons (NULL_TREE, {
sizetype, temp = builtin_function ("alloca",
endlink)), build_function_type (ptr_type_node,
BUILT_IN_ALLOCA, NULL_PTR); tree_cons (NULL_TREE,
#endif sizetype,
endlink)),
BUILT_IN_ALLOCA, NULL_PTR);
/* Suppress error if redefined as a non-function. */
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
/* Suppress error if redefined as a non-function. */
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("_exit", build_function_type (void_type_node,
int_endlink),
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
/* Suppress error if redefined as a non-function. */
DECL_BUILT_IN_NONANSI (temp) = 1;
}
builtin_function ("__builtin_abs", int_ftype_int, builtin_function ("__builtin_abs", int_ftype_int,
BUILT_IN_ABS, NULL_PTR); BUILT_IN_ABS, NULL_PTR);
@ -4647,6 +4682,23 @@ init_decl_processing ()
builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR); builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR);
builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
/* Declare these functions volatile
to avoid spurious "control drops through" warnings. */
temp = builtin_function ("abort",
build_function_type (void_type_node, endlink),
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
/* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on
them... */
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("exit", build_function_type (void_type_node,
int_endlink),
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
DECL_BUILT_IN_NONANSI (temp) = 1;
} }
#if 0 #if 0
@ -4708,6 +4760,11 @@ init_decl_processing ()
: signed_wchar_type_node; : signed_wchar_type_node;
record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node); record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node);
/* Artificial declaration of wchar_t -- can be bashed */
wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"),
wchar_type_node);
pushdecl (wchar_decl_node);
/* This is for wide string constants. */ /* This is for wide string constants. */
wchar_array_type_node wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type); = build_array_type (wchar_type_node, array_domain_type);
@ -4758,7 +4815,7 @@ init_decl_processing ()
vtbl_type_node vtbl_type_node
= build_array_type (vtable_entry_type, NULL_TREE); = build_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node); layout_type (vtbl_type_node);
vtbl_type_node = c_build_type_variant (vtbl_type_node, 1, 0); vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node); record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
/* Simplify life by making a "sigtable_entry_type". Give its /* Simplify life by making a "sigtable_entry_type". Give its
@ -4928,7 +4985,7 @@ init_decl_processing ()
NOT_BUILT_IN); NOT_BUILT_IN);
abort_fndecl abort_fndecl
= define_function ("abort", = define_function ("__pure_virtual",
build_function_type (void_type_node, void_list_node), build_function_type (void_type_node, void_list_node),
NOT_BUILT_IN, 0, 0); NOT_BUILT_IN, 0, 0);
@ -5010,7 +5067,6 @@ shadow_tag (declspecs)
tree declspecs; tree declspecs;
{ {
int found_tag = 0; int found_tag = 0;
int warned = 0;
tree ob_modifier = NULL_TREE; tree ob_modifier = NULL_TREE;
register tree link; register tree link;
register enum tree_code code, ok_code = ERROR_MARK; register enum tree_code code, ok_code = ERROR_MARK;
@ -5023,41 +5079,14 @@ shadow_tag (declspecs)
code = TREE_CODE (value); code = TREE_CODE (value);
if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE) if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
{ {
register tree name = TYPE_NAME (value); my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261);
if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0) if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0)
cp_error ("forward declaration of `%#T'", value); cp_error ("forward declaration of `%#T'", value);
if (name == NULL_TREE) t = value;
name = lookup_tag_reverse (value, NULL_TREE); ok_code = code;
found_tag++;
if (name && TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
t = lookup_tag (code, name, inner_binding_level, 1);
if (t == NULL_TREE)
{
push_obstacks (&permanent_obstack, &permanent_obstack);
if (IS_AGGR_TYPE_CODE (code))
t = make_lang_type (code);
else
t = make_node (code);
pushtag (name, t, 0);
pop_obstacks ();
ok_code = code;
}
else if (name != NULL_TREE || code == ENUMERAL_TYPE)
ok_code = code;
if (ok_code != ERROR_MARK)
found_tag++;
else
{
if (!warned)
pedwarn ("useless keyword or type name in declaration");
warned = 1;
}
} }
else if (value == ridpointers[(int) RID_STATIC] else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN] || value == ridpointers[(int) RID_EXTERN]
@ -5097,32 +5126,9 @@ shadow_tag (declspecs)
cp_error ("`%D' can only be specified for objects and functions", cp_error ("`%D' can only be specified for objects and functions",
ob_modifier); ob_modifier);
if (ok_code == RECORD_TYPE if (found_tag == 0)
&& found_tag == 1
&& TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_DECLARED_EXCEPTION (t))
{
if (TYPE_SIZE (t))
cp_error ("redeclaration of exception `%T'", t);
else
{
tree ename, decl;
push_obstacks (&permanent_obstack, &permanent_obstack);
pushclass (t, 0);
ename = TYPE_NAME (t);
if (TREE_CODE (ename) == TYPE_DECL)
ename = DECL_NAME (ename);
decl = build_lang_field_decl (VAR_DECL, ename, t);
pop_obstacks ();
}
}
else if (found_tag == 0)
pedwarn ("abstract declarator used as declaration"); pedwarn ("abstract declarator used as declaration");
else if (!warned && found_tag > 1) else if (found_tag > 1)
pedwarn ("multiple types in one declaration"); pedwarn ("multiple types in one declaration");
} }
} }
@ -5255,8 +5261,7 @@ start_decl (declarator, declspecs, initialized, raises)
if (interface_unknown && flag_external_templates if (interface_unknown && flag_external_templates
&& ! DECL_IN_SYSTEM_HEADER (decl)) && ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface (); warn_if_unknown_interface ();
TREE_PUBLIC (d) = TREE_PUBLIC (decl) = TREE_PUBLIC (d) = TREE_PUBLIC (decl);
flag_external_templates && !interface_unknown;
TREE_STATIC (d) = TREE_STATIC (decl); TREE_STATIC (d) = TREE_STATIC (decl);
DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
&& !(context && !DECL_THIS_EXTERN (decl))); && !(context && !DECL_THIS_EXTERN (decl)));
@ -5714,6 +5719,14 @@ finish_decl (decl, init, asmspec_tree, need_pop)
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
if (type == error_mark_node)
{
if (current_binding_level == global_binding_level && temporary)
end_temporary_allocation ();
return;
}
was_incomplete = (DECL_SIZE (decl) == NULL_TREE); was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
/* Take care of TYPE_DECLs up front. */ /* Take care of TYPE_DECLs up front. */
@ -5808,6 +5821,10 @@ finish_decl (decl, init, asmspec_tree, need_pop)
else if (TREE_CODE (type) == REFERENCE_TYPE else if (TREE_CODE (type) == REFERENCE_TYPE
|| (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type))) || (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type)))
{ {
if (TREE_STATIC (decl))
make_decl_rtl (decl, NULL_PTR,
current_binding_level == global_binding_level
|| pseudo_global_level_p ());
grok_reference_init (decl, type, init, &cleanup); grok_reference_init (decl, type, init, &cleanup);
init = NULL_TREE; init = NULL_TREE;
} }
@ -6315,9 +6332,11 @@ finish_decl (decl, init, asmspec_tree, need_pop)
expand_aggr_init (decl, init, 0); expand_aggr_init (decl, init, 0);
} }
/* Set this to 0 so we can tell whether an aggregate /* Set this to 0 so we can tell whether an aggregate which
which was initialized was ever used. */ was initialized was ever used. Don't do this if it has a
if (TYPE_NEEDS_CONSTRUCTING (type)) destructor, so we don't complain about the 'resource
allocation is initialization' idiom. */
if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE)
TREE_USED (decl) = 0; TREE_USED (decl) = 0;
/* Store the cleanup, if there was one. */ /* Store the cleanup, if there was one. */
@ -6792,6 +6811,7 @@ grokvardecl (type, declarator, specbits, initialized)
decl = build_lang_field_decl (VAR_DECL, declarator, type); decl = build_lang_field_decl (VAR_DECL, declarator, type);
DECL_CONTEXT (decl) = basetype; DECL_CONTEXT (decl) = basetype;
DECL_CLASS_CONTEXT (decl) = basetype; DECL_CLASS_CONTEXT (decl) = basetype;
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
} }
else else
decl = build_decl (VAR_DECL, declarator, type); decl = build_decl (VAR_DECL, declarator, type);
@ -6857,6 +6877,8 @@ build_ptrmemfunc_type (type)
/* Let the front-end know this is a pointer to member function. */ /* Let the front-end know this is a pointer to member function. */
TYPE_PTRMEMFUNC_FLAG(t) = 1; TYPE_PTRMEMFUNC_FLAG(t) = 1;
/* and not really an aggregate. */
IS_AGGR_TYPE (t) = 0;
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node); delta_type_node);
@ -7091,7 +7113,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
dname = decl; dname = decl;
decl = NULL_TREE; decl = NULL_TREE;
if (IDENTIFIER_OPNAME_P (dname)) if (! IDENTIFIER_OPNAME_P (dname)
/* Linux headers use '__op'. Arrgh. */
|| IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))
name = IDENTIFIER_POINTER (dname);
else
{ {
if (IDENTIFIER_TYPENAME_P (dname)) if (IDENTIFIER_TYPENAME_P (dname))
{ {
@ -7102,8 +7128,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
name = operator_name_string (dname); name = operator_name_string (dname);
} }
else
name = IDENTIFIER_POINTER (dname);
break; break;
case RECORD_TYPE: case RECORD_TYPE:
@ -7281,7 +7305,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
goto found; goto found;
} }
for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++) for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
{ {
if (ridpointers[i] == id) if (ridpointers[i] == id)
{ {
@ -7521,10 +7545,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type); volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
staticp = 0; staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
#if 0
/* This sort of redundancy is blessed in a footnote to the Sep 94 WP. */
if (constp > 1) if (constp > 1)
warning ("duplicate `const'"); warning ("duplicate `const'");
if (volatilep > 1) if (volatilep > 1)
warning ("duplicate `volatile'"); warning ("duplicate `volatile'");
#endif
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
if (RIDBIT_SETP (RID_STATIC, specbits)) if (RIDBIT_SETP (RID_STATIC, specbits))
@ -7688,17 +7715,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
break; break;
} }
if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF])) if (previous_declspec)
{ TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
if (previous_declspec)
TREE_CHAIN (previous_declspec)
= IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
else
declspecs
= IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
}
else else
TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC]; declspecs = TREE_CHAIN (scanner);
declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
declspecs);
/* In the recursive call to grokdeclarator we need to know /* In the recursive call to grokdeclarator we need to know
whether we are working on a signature-local typedef. */ whether we are working on a signature-local typedef. */
@ -7707,6 +7730,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
loc_typedecl = loc_typedecl =
grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE); grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE);
if (previous_declspec)
TREE_CHAIN (previous_declspec) = scanner;
if (loc_typedecl != error_mark_node) if (loc_typedecl != error_mark_node)
{ {
@ -7714,6 +7740,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
register int *pi; register int *pi;
TREE_SET_CODE (loc_typedecl, TYPE_DECL); TREE_SET_CODE (loc_typedecl, TYPE_DECL);
/* This is the same field as DECL_ARGUMENTS, which is set for
function typedefs by the above grokdeclarator. */
DECL_NESTED_TYPENAME (loc_typedecl) = 0;
pi = (int *) permalloc (sizeof (struct lang_decl_flags)); pi = (int *) permalloc (sizeof (struct lang_decl_flags));
while (i > 0) while (i > 0)
@ -7983,7 +8012,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_cplus_array_type (type, itype); type = build_cplus_array_type (type, itype);
if (constp || volatilep) if (constp || volatilep)
type = c_build_type_variant (type, constp, volatilep); type = cp_build_type_variant (type, constp, volatilep);
ctype = NULL_TREE; ctype = NULL_TREE;
} }
@ -7992,6 +8021,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
case CALL_EXPR: case CALL_EXPR:
{ {
tree arg_types; tree arg_types;
int funcdecl_p;
tree inner_parms = TREE_OPERAND (declarator, 1);
tree inner_decl = TREE_OPERAND (declarator, 0);
/* Declaring a function type. /* Declaring a function type.
Make sure we have a valid type for the function to return. */ Make sure we have a valid type for the function to return. */
@ -8005,7 +8037,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (constp || volatilep) if (constp || volatilep)
{ {
type = c_build_type_variant (type, constp, volatilep); type = cp_build_type_variant (type, constp, volatilep);
if (IS_AGGR_TYPE (type)) if (IS_AGGR_TYPE (type))
build_pointer_type (type); build_pointer_type (type);
constp = 0; constp = 0;
@ -8026,8 +8058,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = integer_type_node; type = integer_type_node;
} }
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1);
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
funcdecl_p =
inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE;
if (ctype == NULL_TREE if (ctype == NULL_TREE
&& decl_context == FIELD && decl_context == FIELD
&& funcdecl_p
&& (friendp == 0 || dname == current_class_name)) && (friendp == 0 || dname == current_class_name))
ctype = current_class_type; ctype = current_class_type;
@ -8141,27 +8182,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Construct the function type and go to the next /* Construct the function type and go to the next
inner layer of declarator. */ inner layer of declarator. */
{ declarator = TREE_OPERAND (declarator, 0);
int funcdef_p;
tree inner_parms = TREE_OPERAND (declarator, 1);
tree inner_decl = TREE_OPERAND (declarator, 0);
declarator = TREE_OPERAND (declarator, 0); /* FIXME: This is where default args should be fully
processed. */
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
inner_decl = TREE_OPERAND (inner_decl, 1);
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
funcdef_p =
(inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE)
? funcdef_flag : 0;
/* FIXME: This is where default args should be fully
processed. */
arg_types = grokparms (inner_parms, funcdef_p);
}
if (declarator) if (declarator)
{ {
@ -8216,7 +8242,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
signature pointer/reference itself. */ signature pointer/reference itself. */
if (! IS_SIGNATURE (type)) if (! IS_SIGNATURE (type))
{ {
type = c_build_type_variant (type, constp, volatilep); type = cp_build_type_variant (type, constp, volatilep);
if (IS_AGGR_TYPE (type)) if (IS_AGGR_TYPE (type))
build_pointer_type (type); build_pointer_type (type);
constp = 0; constp = 0;
@ -8511,7 +8537,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Note that the grammar rejects storage classes /* Note that the grammar rejects storage classes
in typenames, fields or parameters. */ in typenames, fields or parameters. */
if (constp || volatilep) if (constp || volatilep)
type = c_build_type_variant (type, constp, volatilep); type = cp_build_type_variant (type, constp, volatilep);
/* If the user declares "struct {...} foo" then `foo' will have /* If the user declares "struct {...} foo" then `foo' will have
an anonymous name. Fill that name in now. Nothing can an anonymous name. Fill that name in now. Nothing can
@ -8600,7 +8626,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (IS_SIGNATURE (type)) if (IS_SIGNATURE (type))
error ("`const' or `volatile' specified with signature type"); error ("`const' or `volatile' specified with signature type");
else else
type = c_build_type_variant (type, constp, volatilep); type = cp_build_type_variant (type, constp, volatilep);
/* Special case: "friend class foo" looks like a TYPENAME context. */ /* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp) if (friendp)
@ -8682,7 +8708,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{ {
/* Transfer const-ness of array into that of type pointed to. */ /* Transfer const-ness of array into that of type pointed to. */
type = build_pointer_type type = build_pointer_type
(c_build_type_variant (TREE_TYPE (type), constp, volatilep)); (cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
volatilep = constp = 0; volatilep = constp = 0;
} }
else if (TREE_CODE (type) == FUNCTION_TYPE) else if (TREE_CODE (type) == FUNCTION_TYPE)
@ -8961,14 +8987,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type)); TREE_TYPE (type), TYPE_ARG_TYPES (type));
/* Record presence of `static'. In C++, `inline' is like `static'. /* Record presence of `static'. In C++, `inline' is like `static'. */
Methods of classes should be public, unless we're dropping them
into some other file, so we don't clear TREE_PUBLIC for them. */
publicp publicp
= ((ctype = !(RIDBIT_SETP (RID_STATIC, specbits)
&& CLASSTYPE_INTERFACE_KNOWN (ctype)) || RIDBIT_SETP (RID_INLINE, specbits));
|| !(RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name, decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals, virtualp, flags, quals,
@ -8989,7 +9011,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
declaring main to be static. */ declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE) if (TREE_CODE (type) == METHOD_TYPE)
{ {
cp_error_at ("cannot declare member function `%D' to have static linkage", decl); cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1; illegal_static = 1;
} }
else if (! ctype else if (! ctype
@ -9791,6 +9813,7 @@ xref_defn_tag (code_type_node, name, binfo)
if (! ANON_AGGRNAME_P (name)) if (! ANON_AGGRNAME_P (name))
{ {
register tree type_decl = build_decl (TYPE_DECL, ncp, rv); register tree type_decl = build_decl (TYPE_DECL, ncp, rv);
SET_DECL_ARTIFICIAL (type_decl);
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
/* Mark the TYPE_DECL node created just above as a gratuitous one /* Mark the TYPE_DECL node created just above as a gratuitous one
so that dwarfout.c will know not to generate a TAG_typedef DIE so that dwarfout.c will know not to generate a TAG_typedef DIE
@ -9939,48 +9962,21 @@ xref_tag (code_type_node, name, binfo, globalize)
} }
else else
{ {
extern tree pending_vtables;
struct binding_level *old_b = class_binding_level; struct binding_level *old_b = class_binding_level;
int needs_writing;
ref = make_lang_type (code); ref = make_lang_type (code);
/* A signature type will contain the fields of the signature
table. Therefore, it's not only an interface. */
if (tag_code == signature_type) if (tag_code == signature_type)
{ {
SET_SIGNATURE (ref); SET_SIGNATURE (ref);
/* Since a signature type will be turned into the type
of signature tables, it's not only an interface. */
CLASSTYPE_INTERFACE_ONLY (ref) = 0; CLASSTYPE_INTERFACE_ONLY (ref) = 0;
CLASSTYPE_INTERFACE_UNKNOWN (ref) = 0; SET_CLASSTYPE_INTERFACE_KNOWN (ref);
/* A signature doesn't have a vtable. */
CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0;
} }
/* Record how to set the access of this class's
virtual functions. If write_virtuals == 2 or 3, then
inline virtuals are ``extern inline''. */
switch (write_virtuals)
{
case 0:
case 1:
needs_writing = 1;
break;
case 2:
needs_writing = !! value_member (name, pending_vtables);
break;
case 3:
needs_writing = ! CLASSTYPE_INTERFACE_ONLY (ref)
&& CLASSTYPE_INTERFACE_KNOWN (ref);
break;
default:
needs_writing = 0;
}
/* Signatures don't have a vtable. As long as we don't have default
implementations, they behave as if `write_virtuals' were 3. */
if (tag_code == signature_type)
CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0;
else
CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = needs_writing;
#ifdef NONNESTED_CLASSES #ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */ /* Class types don't nest the way enums do. */
class_binding_level = (struct binding_level *)0; class_binding_level = (struct binding_level *)0;
@ -10108,6 +10104,7 @@ xref_tag (code_type_node, name, binfo, globalize)
TREE_VIA_PUBLIC (base_binfo) = via_public; TREE_VIA_PUBLIC (base_binfo) = via_public;
TREE_VIA_PROTECTED (base_binfo) = via_protected; TREE_VIA_PROTECTED (base_binfo) = via_protected;
TREE_VIA_VIRTUAL (base_binfo) = via_virtual; TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
SET_CLASSTYPE_MARKED (basetype); SET_CLASSTYPE_MARKED (basetype);
#if 0 #if 0
@ -10209,6 +10206,7 @@ start_enum (name)
TREE_ADDRESSABLE (b->tags) = 1; TREE_ADDRESSABLE (b->tags) = 1;
current_local_enum = NULL_TREE; current_local_enum = NULL_TREE;
#if 0 /* This stuff gets cleared in finish_enum anyway. */
if (TYPE_VALUES (enumtype) != NULL_TREE) if (TYPE_VALUES (enumtype) != NULL_TREE)
/* Completely replace its old definition. /* Completely replace its old definition.
The old enumerators remain defined, however. */ The old enumerators remain defined, however. */
@ -10221,7 +10219,8 @@ start_enum (name)
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
TYPE_SIZE (enumtype) = NULL_TREE; TYPE_SIZE (enumtype) = NULL_TREE;
fixup_unsigned_type (enumtype); fixup_signed_type (enumtype);
#endif
/* We copy this value because enumerated type constants /* We copy this value because enumerated type constants
are really of the type of the enumerator, not integer_type_node. */ are really of the type of the enumerator, not integer_type_node. */
@ -10241,84 +10240,89 @@ tree
finish_enum (enumtype, values) finish_enum (enumtype, values)
register tree enumtype, values; register tree enumtype, values;
{ {
register tree pair, tem; register tree minnode, maxnode;
register HOST_WIDE_INT maxvalue = 0;
register HOST_WIDE_INT minvalue = 0;
register HOST_WIDE_INT i;
/* Calculate the maximum value of any enumerator in this type. */ /* Calculate the maximum value of any enumerator in this type. */
if (values) if (values)
{ {
register tree pair;
register tree value = DECL_INITIAL (TREE_VALUE (values));
/* Speed up the main loop by performing some precalculations */ /* Speed up the main loop by performing some precalculations */
HOST_WIDE_INT value;
TREE_TYPE (TREE_VALUE (values)) = enumtype; TREE_TYPE (TREE_VALUE (values)) = enumtype;
TREE_TYPE (DECL_INITIAL (TREE_VALUE (values))) = enumtype; TREE_TYPE (value) = enumtype;
TREE_VALUE (values) = DECL_INITIAL (TREE_VALUE (values)); TREE_VALUE (values) = value;
value = TREE_INT_CST_LOW (TREE_VALUE (values)); minnode = maxnode = value;
minvalue = maxvalue = value;
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{ {
value = DECL_INITIAL (TREE_VALUE (pair));
TREE_TYPE (TREE_VALUE (pair)) = enumtype; TREE_TYPE (TREE_VALUE (pair)) = enumtype;
TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype; TREE_TYPE (value) = enumtype;
TREE_VALUE (pair) = DECL_INITIAL (TREE_VALUE (pair)); TREE_VALUE (pair) = value;
value = TREE_INT_CST_LOW (TREE_VALUE (pair)); if (tree_int_cst_lt (maxnode, value))
if (value > maxvalue) maxnode = value;
maxvalue = value; else if (tree_int_cst_lt (value, minnode))
else if (value < minvalue) minnode = value;
minvalue = value;
} }
} }
else
maxnode = minnode = integer_zero_node;
TYPE_VALUES (enumtype) = values; TYPE_VALUES (enumtype) = values;
if (flag_short_enums) {
{ int unsignedp = tree_int_cst_sgn (minnode) >= 0;
/* Determine the precision this type needs, lay it out, and define int lowprec = min_precision (minnode, unsignedp);
it. */ int highprec = min_precision (maxnode, unsignedp);
int precision = MAX (lowprec, highprec);
/* First reset precision */ if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node))
TYPE_PRECISION (enumtype) = 0; precision = TYPE_PRECISION (integer_type_node);
for (i = maxvalue; i; i >>= 1)
TYPE_PRECISION (enumtype)++;
if (!TYPE_PRECISION (enumtype)) /*
TYPE_PRECISION (enumtype) = 1; * The following code is unnecessary since the function
* type_promotes_to deals correctly with promotion of enums of
/* Cancel the laying out previously done for the enum type, * underlying unsigned types to signed integer types.
so that fixup_unsigned_type will do it over. */ * Moreover, it causes an enum bitfield to require one more bit of
TYPE_SIZE (enumtype) = NULL_TREE; * storage than defined by the ANSI/ISO C++ resolution section r.7.2
* which defines the range of an enum.
*/
#if 0
/* Unlike the C frontend, we prefer signed types. */
if (unsignedp && int_fits_type_p (maxnode, type_for_size (precision, 0)))
unsignedp = 0;
#endif
TYPE_PRECISION (enumtype) = precision;
TYPE_SIZE (enumtype) = NULL_TREE;
if (unsignedp)
fixup_unsigned_type (enumtype); fixup_unsigned_type (enumtype);
} else
fixup_signed_type (enumtype);
}
TREE_INT_CST_LOW (TYPE_MAX_VALUE (enumtype)) = maxvalue;
/* An enum can have some negative values; then it is signed. */
if (minvalue < 0)
{
TREE_INT_CST_LOW (TYPE_MIN_VALUE (enumtype)) = minvalue;
TREE_INT_CST_HIGH (TYPE_MIN_VALUE (enumtype)) = -1;
TREE_UNSIGNED (enumtype) = 0;
}
if (flag_cadillac) if (flag_cadillac)
cadillac_finish_enum (enumtype); cadillac_finish_enum (enumtype);
/* Fix up all variant types of this enum type. */ {
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem)) register tree tem;
{
TYPE_VALUES (tem) = TYPE_VALUES (enumtype); /* Fix up all variant types of this enum type. */
TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); tem = TYPE_NEXT_VARIANT (tem))
TYPE_SIZE (tem) = TYPE_SIZE (enumtype); {
TYPE_MODE (tem) = TYPE_MODE (enumtype); TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
} TYPE_MODE (tem) = TYPE_MODE (enumtype);
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
}
}
/* Finish debugging output for this type. */ /* Finish debugging output for this type. */
#if 0 #if 0
@ -10678,15 +10682,14 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
/* If this function belongs to an interface, it is public. /* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external. If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */ It doesn't matter whether it's inline or not. */
if (interface_unknown == 0) if (interface_unknown == 0
&& ! TREE_PUBLIC (decl1))
{ {
TREE_PUBLIC (decl1) = 1; TREE_PUBLIC (decl1) = 1;
DECL_EXTERNAL (decl1) DECL_EXTERNAL (decl1)
= (interface_only = (interface_only
|| (DECL_INLINE (decl1) && ! flag_implement_inlines)); || (DECL_INLINE (decl1) && ! flag_implement_inlines));
} }
else if (DECL_EXPLICIT_INSTANTIATION (decl1))
/* PUBLIC and EXTERNAL set by do_*_instantiation */;
else else
{ {
/* This is a definition, not a reference. /* This is a definition, not a reference.
@ -10695,7 +10698,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
defining how to inline. So set DECL_EXTERNAL in that case. */ defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline; DECL_EXTERNAL (decl1) = current_extern_inline;
DECL_DEFER_OUTPUT (decl1) = DECL_INLINE (decl1); DECL_DEFER_OUTPUT (decl1)
= DECL_INLINE (decl1) && ! TREE_PUBLIC (decl1)
&& (DECL_FUNCTION_MEMBER_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1));
} }
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
@ -11023,59 +11029,6 @@ store_return_init (return_id, init)
} }
} }
#if 0
/* Generate code for default X() constructor. */
static void
build_default_constructor (fndecl)
tree fndecl;
{
int i = CLASSTYPE_N_BASECLASSES (current_class_type);
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree fields = TYPE_FIELDS (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm);
parm = DECL_REFERENCE_SLOT (parm);
while (--i >= 0)
{
tree basetype = TREE_VEC_ELT (binfos, i);
if (TYPE_HAS_INIT_REF (basetype))
{
tree name = TYPE_NAME (basetype);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
current_base_init_list = tree_cons (name, parm, current_base_init_list);
}
}
for (; fields; fields = TREE_CHAIN (fields))
{
tree name, init;
if (TREE_STATIC (fields))
continue;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
{
if (VFIELD_NAME_P (DECL_NAME (fields)))
continue;
if (VBASE_NAME_P (DECL_NAME (fields)))
continue;
/* True for duplicate members. */
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
init = build_tree_list (NULL_TREE, init);
current_member_init_list
= tree_cons (DECL_NAME (fields), init, current_member_init_list);
}
}
#endif
/* Finish up a function declaration and compile that function /* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage all the way to assembler language output. The free the storage
@ -11529,20 +11482,19 @@ finish_function (lineno, call_poplevel)
/* So we can tell if jump_optimize sets it to 1. */ /* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0; can_reach_end = 0;
/* ??? Compensate for Sun brain damage in dealing with data segments
of PIC code. */
if (flag_pic
&& (DECL_CONSTRUCTOR_P (fndecl)
|| DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
&& CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))
DECL_INLINE (fndecl) = 0;
if (DECL_EXTERNAL (fndecl) if (DECL_EXTERNAL (fndecl)
/* This function is just along for the ride. If we can make /* This function is just along for the ride. If we can make
it inline, that's great. Otherwise, just punt it. */ it inline, that's great. Otherwise, just punt it. */
&& (DECL_INLINE (fndecl) == 0 && (DECL_INLINE (fndecl) == 0
|| flag_no_inline || flag_no_inline
|| function_cannot_inline_p (fndecl))) || function_cannot_inline_p (fndecl)
/* ??? Compensate for Sun brain damage in dealing with
data segments of PIC code. */
|| (flag_pic
&& (DECL_CONSTRUCTOR_P (fndecl)
|| DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
&& CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))))
{ {
extern int rtl_dump_and_exit; extern int rtl_dump_and_exit;
int old_rtl_dump_and_exit = rtl_dump_and_exit; int old_rtl_dump_and_exit = rtl_dump_and_exit;
@ -11564,8 +11516,8 @@ finish_function (lineno, call_poplevel)
rest_of_compilation (fndecl); rest_of_compilation (fndecl);
} }
if (DECL_INLINE (fndecl) if (DECL_INLINE (fndecl) && !TREE_ASM_WRITTEN (fndecl)
&& !TREE_ASM_WRITTEN (fndecl) && DECL_FUNCTION_MEMBER_P (fndecl)) && DECL_DEFER_OUTPUT (fndecl))
{ {
mark_inline_for_output (fndecl); mark_inline_for_output (fndecl);
} }

View file

@ -84,6 +84,11 @@ int flag_no_asm;
int flag_no_builtin; int flag_no_builtin;
/* Nonzero means don't recognize the non-ANSI builtin functions.
-ansi sets this. */
int flag_no_nonansi_builtin;
/* Nonzero means do some things the same way PCC does. */ /* Nonzero means do some things the same way PCC does. */
int flag_traditional; int flag_traditional;
@ -207,6 +212,12 @@ int warn_nonvdtor;
/* Non-zero means warn when a function is declared extern and later inline. */ /* Non-zero means warn when a function is declared extern and later inline. */
int warn_extern_inline; int warn_extern_inline;
/* Non-zero means warn when the compiler will reorder code. */
int warn_reorder;
/* Non-zero means warn when sysnthesis behavior differs from Cfront's. */
int warn_synth;
/* Nonzero means `$' can be in an identifier. /* Nonzero means `$' can be in an identifier.
See cccp.c for reasons why this breaks some obscure ANSI C programs. */ See cccp.c for reasons why this breaks some obscure ANSI C programs. */
@ -320,6 +331,9 @@ int flag_huge_objects;
definitions. */ definitions. */
int flag_conserve_space; int flag_conserve_space;
/* Nonzero if we want to obey access control semantics. */
int flag_access_control = 1;
/* Table of language-dependent -f options. /* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable. STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE ON_VALUE is the value to store in VARIABLE
@ -361,6 +375,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"conserve-space", &flag_conserve_space, 1}, {"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1}, {"vtable-thunks", &flag_vtable_thunks, 1},
{"short-temps", &flag_short_temps, 1}, {"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0}
}; };
/* Decode the string P as a language-specific option. /* Decode the string P as a language-specific option.
@ -447,6 +463,10 @@ lang_decode_option (p)
flag_alt_external_templates = 0; flag_alt_external_templates = 0;
found = 1; found = 1;
} }
else if (!strcmp (p, "ansi-overloading"))
{
warning ("-fansi-overloading is no longer meaningful");
}
else for (j = 0; else for (j = 0;
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]); !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
j++) j++)
@ -511,6 +531,10 @@ lang_decode_option (p)
warn_nonvdtor = setting; warn_nonvdtor = setting;
else if (!strcmp (p, "extern-inline")) else if (!strcmp (p, "extern-inline"))
warn_extern_inline = setting; warn_extern_inline = setting;
else if (!strcmp (p, "reorder"))
warn_reorder = setting;
else if (!strcmp (p, "synth"))
warn_synth = setting;
else if (!strcmp (p, "comment")) else if (!strcmp (p, "comment"))
; /* cpp handles this one. */ ; /* cpp handles this one. */
else if (!strcmp (p, "comments")) else if (!strcmp (p, "comments"))
@ -537,6 +561,7 @@ lang_decode_option (p)
if (warn_uninitialized != 1) if (warn_uninitialized != 1)
warn_uninitialized = (setting ? 2 : 0); warn_uninitialized = (setting ? 2 : 0);
warn_template_debugging = setting; warn_template_debugging = setting;
warn_reorder = setting;
} }
else if (!strcmp (p, "overloaded-virtual")) else if (!strcmp (p, "overloaded-virtual"))
@ -544,7 +569,8 @@ lang_decode_option (p)
else return 0; else return 0;
} }
else if (!strcmp (p, "-ansi")) else if (!strcmp (p, "-ansi"))
flag_no_asm = 1, dollars_in_ident = 0, flag_ansi = 1; flag_no_asm = 1, dollars_in_ident = 0, flag_no_nonansi_builtin = 1,
flag_ansi = 1;
#ifdef SPEW_DEBUG #ifdef SPEW_DEBUG
/* Undocumented, only ever used when you're invoking cc1plus by hand, since /* Undocumented, only ever used when you're invoking cc1plus by hand, since
it's probably safe to assume no sane person would ever want to use this it's probably safe to assume no sane person would ever want to use this
@ -983,7 +1009,7 @@ grok_array_decl (array_expr, index_exp)
if (TYPE_LANG_SPECIFIC (type) if (TYPE_LANG_SPECIFIC (type)
&& TYPE_OVERLOADS_ARRAY_REF (type)) && TYPE_OVERLOADS_ARRAY_REF (type))
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE); array_expr, index_exp, NULL_TREE);
/* Otherwise, create an ARRAY_REF for a pointer or array type. */ /* Otherwise, create an ARRAY_REF for a pointer or array type. */
if (TREE_CODE (type) == POINTER_TYPE if (TREE_CODE (type) == POINTER_TYPE
@ -1000,17 +1026,14 @@ grok_array_decl (array_expr, index_exp)
|| TREE_CODE (type) == REFERENCE_TYPE) || TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) if (TREE_CODE (type) == POINTER_TYPE
&& TYPE_OVERLOADS_ARRAY_REF (type)) || TREE_CODE (type) == ARRAY_TYPE)
error ("array expression backwards");
else if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE)
return build_array_ref (index_exp, array_expr); return build_array_ref (index_exp, array_expr);
else
error("`[]' applied to non-pointer type");
/* We gave an error, so give an error. Huh? */ /* The expression E1[E2] is identical (by definition) to *((E1)+(E2)). */
return error_mark_node; return build_indirect_ref (build_binary_op (PLUS_EXPR, array_expr,
index_exp, 1),
"array indexing");
} }
/* Given the cast expression EXP, checking out its validity. Either return /* Given the cast expression EXP, checking out its validity. Either return
@ -1057,11 +1080,20 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return build1 (NOP_EXPR, void_type_node, t); return build1 (NOP_EXPR, void_type_node, t);
} }
/* You can't delete a pointer to constant. */ if (code == POINTER_TYPE)
if (code == POINTER_TYPE && TREE_READONLY (TREE_TYPE (type)))
{ {
error ("`const *' cannot be deleted"); /* You can't delete a pointer to constant. */
return error_mark_node; if (TREE_READONLY (TREE_TYPE (type)))
{
error ("`const *' cannot be deleted");
return error_mark_node;
}
/* You also can't delete functions. */
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
error ("cannot delete a function");
return error_mark_node;
}
} }
#if 0 #if 0
@ -1128,13 +1160,13 @@ check_classfn (ctype, cname, function)
} }
if (methods != end) if (methods != end)
cp_error ("argument list for `%D' does not match any in class `%T'", cp_error ("argument list for `%#D' does not match any in class `%T'",
fn_name, ctype); function, ctype);
else else
{ {
methods = 0; methods = 0;
cp_error ("no `%D' member function declared in class `%T'", cp_error ("no `%#D' member function declared in class `%T'",
fn_name, ctype); function, ctype);
} }
/* If we did not find the method in the class, add it to /* If we did not find the method in the class, add it to
@ -1301,19 +1333,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
/* current_class_type can be NULL_TREE in case of error. */ /* current_class_type can be NULL_TREE in case of error. */
if (asmspec == 0 && current_class_type) if (asmspec == 0 && current_class_type)
{ {
tree name;
char *buf, *buf2;
buf2 = build_overload_name (current_class_type, 1, 1);
buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (value))
+ sizeof (STATIC_NAME_FORMAT)
+ strlen (buf2));
sprintf (buf, STATIC_NAME_FORMAT, buf2,
IDENTIFIER_POINTER (DECL_NAME (value)));
name = get_identifier (buf);
TREE_PUBLIC (value) = 1; TREE_PUBLIC (value) = 1;
DECL_INITIAL (value) = error_mark_node; DECL_INITIAL (value) = error_mark_node;
DECL_ASSEMBLER_NAME (value) = name; DECL_ASSEMBLER_NAME (value)
= build_static_name (current_class_type, DECL_NAME (value));
} }
pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
@ -1366,9 +1389,11 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value)) if (DECL_FRIEND_P (value))
return void_type_node; return void_type_node;
#if 0 /* Just because a fn is declared doesn't mean we'll try to define it. */
if (current_function_decl && ! IS_SIGNATURE (current_class_type)) if (current_function_decl && ! IS_SIGNATURE (current_class_type))
cp_error ("method `%#D' of local class must be defined in class body", cp_error ("method `%#D' of local class must be defined in class body",
value); value);
#endif
DECL_IN_AGGR_P (value) = 1; DECL_IN_AGGR_P (value) = 1;
return value; return value;
@ -2067,9 +2092,13 @@ finish_anon_union (anon_union_decl)
return; return;
} }
while (field) for (; field; field = TREE_CHAIN (field))
{ {
tree decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); tree decl;
if (TREE_CODE (field) != FIELD_DECL)
continue;
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
/* tell `pushdecl' that this is not tentative. */ /* tell `pushdecl' that this is not tentative. */
DECL_INITIAL (decl) = error_mark_node; DECL_INITIAL (decl) = error_mark_node;
TREE_PUBLIC (decl) = public_p; TREE_PUBLIC (decl) = public_p;
@ -2096,12 +2125,19 @@ finish_anon_union (anon_union_decl)
TREE_PURPOSE of the following TREE_LIST. */ TREE_PURPOSE of the following TREE_LIST. */
elems = tree_cons (NULL_TREE, decl, elems); elems = tree_cons (NULL_TREE, decl, elems);
TREE_TYPE (elems) = type; TREE_TYPE (elems) = type;
field = TREE_CHAIN (field);
} }
if (static_p) if (static_p)
{ {
make_decl_rtl (main_decl, 0, global_bindings_p ()); if (main_decl)
DECL_RTL (anon_union_decl) = DECL_RTL (main_decl); {
make_decl_rtl (main_decl, 0, global_bindings_p ());
DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
}
else
{
warning ("anonymous union with no members");
return;
}
} }
/* The following call assumes that there are never any cleanups /* The following call assumes that there are never any cleanups
@ -2522,6 +2558,37 @@ walk_sigtables (typedecl_fn, vardecl_fn)
} }
} }
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
inline function at end-of-file. */
void
import_export_inline (decl)
tree decl;
{
if (TREE_PUBLIC (decl))
return;
/* If an explicit instantiation doesn't have TREE_PUBLIC set, it was with
'extern'. */
if (DECL_EXPLICIT_INSTANTIATION (decl)
|| (DECL_IMPLICIT_INSTANTIATION (decl) && ! flag_implicit_templates))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
}
}
}
extern int parse_time, varconst_time; extern int parse_time, varconst_time;
#define TIMEVAR(VAR, BODY) \ #define TIMEVAR(VAR, BODY) \
@ -2541,8 +2608,7 @@ finish_file ()
tree fnname; tree fnname;
tree vars = static_aggregates; tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0; int needs_cleaning = 0, needs_messing_up = 0;
int have_exception_handlers = build_exception_table ();
build_exception_table ();
if (flag_detailed_statistics) if (flag_detailed_statistics)
dump_tree_statistics (); dump_tree_statistics ();
@ -2636,7 +2702,7 @@ finish_file ()
mess_up: mess_up:
/* Must do this while we think we are at the top level. */ /* Must do this while we think we are at the top level. */
vars = nreverse (static_aggregates); vars = nreverse (static_aggregates);
if (vars != NULL_TREE) if (vars != NULL_TREE || have_exception_handlers)
{ {
fnname = get_file_function_name ('I'); fnname = get_file_function_name ('I');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
@ -2648,6 +2714,9 @@ finish_file ()
push_momentary (); push_momentary ();
expand_start_bindings (0); expand_start_bindings (0);
if (have_exception_handlers)
register_exception_table ();
while (vars) while (vars)
{ {
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
@ -2712,7 +2781,6 @@ finish_file ()
} }
} }
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| init == 0
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0); expand_aggr_init (decl, init, 0);
else if (TREE_CODE (init) == TREE_VEC) else if (TREE_CODE (init) == TREE_VEC)
@ -2828,24 +2896,12 @@ finish_file ()
0; don't crash. */ 0; don't crash. */
if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0) if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
continue; continue;
if (DECL_FUNCTION_MEMBER_P (decl) && !TREE_PUBLIC (decl)) import_export_inline (decl);
{
tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
}
}
if (TREE_PUBLIC (decl) if (TREE_PUBLIC (decl)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|| flag_keep_inline_functions) || flag_keep_inline_functions)
{ {
if (DECL_EXTERNAL (decl) if (DECL_EXTERNAL (decl))
|| (DECL_IMPLICIT_INSTANTIATION (decl)
&& ! flag_implicit_templates))
assemble_external (decl); assemble_external (decl);
else else
{ {
@ -2872,9 +2928,7 @@ finish_file ()
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& ! TREE_ASM_WRITTEN (decl)) && ! TREE_ASM_WRITTEN (decl))
{ {
if (DECL_EXTERNAL (decl) if (DECL_EXTERNAL (decl))
|| (DECL_IMPLICIT_INSTANTIATION (decl)
&& ! flag_implicit_templates))
assemble_external (decl); assemble_external (decl);
else else
{ {

View file

@ -30,6 +30,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
typedef char* cp_printer PROTO((HOST_WIDE_INT, int)); typedef char* cp_printer PROTO((HOST_WIDE_INT, int));
extern cp_printer * cp_printers[256]; extern cp_printer * cp_printers[256];
/* Whether or not we should try to be quiet for errors and warnings; this is
used to avoid being too talkative about problems with tentative choices
when we're computing the conversion costs for a method call. */
int cp_silent = 0;
typedef void errorfn (); /* deliberately vague */ typedef void errorfn (); /* deliberately vague */
extern char* cp_file_of PROTO((tree)); extern char* cp_file_of PROTO((tree));
@ -150,7 +155,8 @@ cp_error (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn error; extern errorfn error;
cp_thing (error, 0, format, arglist); if (! cp_silent)
cp_thing (error, 0, format, arglist);
} }
void void
@ -159,7 +165,8 @@ cp_warning (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn warning; extern errorfn warning;
cp_thing (warning, 0, format, arglist); if (! cp_silent)
cp_thing (warning, 0, format, arglist);
} }
void void
@ -168,7 +175,8 @@ cp_pedwarn (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn pedwarn; extern errorfn pedwarn;
cp_thing (pedwarn, 0, format, arglist); if (! cp_silent)
cp_thing (pedwarn, 0, format, arglist);
} }
void void
@ -177,7 +185,8 @@ cp_compiler_error (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn compiler_error; extern errorfn compiler_error;
cp_thing (compiler_error, 0, format, arglist); if (! cp_silent)
cp_thing (compiler_error, 0, format, arglist);
} }
void void
@ -195,7 +204,8 @@ cp_error_at (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn error_with_file_and_line; extern errorfn error_with_file_and_line;
cp_thing (error_with_file_and_line, 1, format, arglist); if (! cp_silent)
cp_thing (error_with_file_and_line, 1, format, arglist);
} }
void void
@ -204,7 +214,8 @@ cp_warning_at (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn warning_with_file_and_line; extern errorfn warning_with_file_and_line;
cp_thing (warning_with_file_and_line, 1, format, arglist); if (! cp_silent)
cp_thing (warning_with_file_and_line, 1, format, arglist);
} }
void void
@ -213,5 +224,6 @@ cp_pedwarn_at (format, arglist)
arglist_dcl arglist_dcl
{ {
extern errorfn pedwarn_with_file_and_line; extern errorfn pedwarn_with_file_and_line;
cp_thing (pedwarn_with_file_and_line, 1, format, arglist); if (! cp_silent)
cp_thing (pedwarn_with_file_and_line, 1, format, arglist);
} }

View file

@ -104,6 +104,8 @@ dump_readonly_or_volatile (t, p)
if (p == before) OB_PUTC (' '); if (p == before) OB_PUTC (' ');
if (TYPE_READONLY (t)) if (TYPE_READONLY (t))
OB_PUTS ("const"); OB_PUTS ("const");
if (TYPE_READONLY (t) && TYPE_VOLATILE (t))
OB_PUTC (' ');
if (TYPE_VOLATILE (t)) if (TYPE_VOLATILE (t))
OB_PUTS ("volatile"); OB_PUTS ("volatile");
if (p == after) OB_PUTC (' '); if (p == after) OB_PUTC (' ');
@ -569,7 +571,8 @@ dump_decl (t, v)
{ {
/* Don't say 'typedef class A' */ /* Don't say 'typedef class A' */
tree type = TREE_TYPE (t); tree type = TREE_TYPE (t);
if (IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type) if (((IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type))
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& type == TYPE_MAIN_VARIANT (type)) && type == TYPE_MAIN_VARIANT (type))
{ {
dump_type (type, v); dump_type (type, v);
@ -666,21 +669,31 @@ dump_decl (t, v)
case TEMPLATE_DECL: case TEMPLATE_DECL:
{ {
tree args = DECL_TEMPLATE_PARMS (t); tree args = DECL_TEMPLATE_PARMS (t);
int i, len = TREE_VEC_LENGTH (args); int i, len = args ? TREE_VEC_LENGTH (args) : 0;
OB_PUTS ("template <"); OB_PUTS ("template <");
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
tree arg = TREE_VEC_ELT (args, i); tree arg = TREE_VEC_ELT (args, i);
if (TREE_CODE (arg) == IDENTIFIER_NODE) tree defval = TREE_PURPOSE (arg);
arg = TREE_VALUE (arg);
if (TREE_CODE (arg) == TYPE_DECL)
{ {
OB_PUTS ("class "); OB_PUTS ("class ");
OB_PUTID (arg); OB_PUTID (DECL_NAME (arg));
} }
else else
dump_decl (arg, 1); dump_decl (arg, 1);
if (defval)
{
OB_PUTS (" = ");
dump_decl (defval, 1);
}
OB_PUTC2 (',', ' '); OB_PUTC2 (',', ' ');
} }
OB_UNPUT (2); if (len != 0)
OB_UNPUT (2);
OB_PUTC2 ('>', ' '); OB_PUTC2 ('>', ' ');
if (DECL_TEMPLATE_IS_CLASS (t)) if (DECL_TEMPLATE_IS_CLASS (t))
@ -1219,6 +1232,14 @@ dump_expr (t, nop)
break; break;
} }
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
OB_PUTID (DECL_NAME (TREE_VALUE (t)));
break;
}
/* else fall through */
/* This list is incomplete, but should suffice for now. /* This list is incomplete, but should suffice for now.
It is very important that `sorry' does not call It is very important that `sorry' does not call
`report_error_function'. That could cause an infinite loop. */ `report_error_function'. That could cause an infinite loop. */
@ -1331,12 +1352,26 @@ int
cp_line_of (t) cp_line_of (t)
tree t; tree t;
{ {
int line = 0;
if (TREE_CODE (t) == PARM_DECL) if (TREE_CODE (t) == PARM_DECL)
return DECL_SOURCE_LINE (DECL_CONTEXT (t)); line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
return DECL_SOURCE_LINE (TYPE_NAME (t)); t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
if (IS_AGGR_TYPE (t))
line = CLASSTYPE_SOURCE_LINE (t);
else
line = DECL_SOURCE_LINE (TYPE_NAME (t));
}
else else
return DECL_SOURCE_LINE (t); line = DECL_SOURCE_LINE (t);
if (line == 0)
return lineno;
return line;
} }
char * char *

View file

@ -58,11 +58,6 @@ sorry_no_eh ()
} }
} }
void
build_exception_table ()
{
}
void void
expand_exception_blocks () expand_exception_blocks ()
{ {
@ -180,29 +175,9 @@ output_exception_table_entry (file, start_label, end_label, eh_label)
{ {
char label[100]; char label[100];
fprintf (file, "\t%s\t ", ASM_LONG); assemble_integer (start_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
if (GET_CODE (start_label) == CODE_LABEL) assemble_integer (end_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
{ assemble_integer (eh_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (start_label));
assemble_name (file, label);
}
else if (GET_CODE (start_label) == SYMBOL_REF)
{
fprintf (stderr, "YYYYYYYYYEEEEEEEESSSSSSSSSSSS!!!!!!!!!!\n");
assemble_name (file, XSTR (start_label, 0));
}
putc ('\n', file);
fprintf (file, "\t%s\t ", ASM_LONG);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (end_label));
assemble_name (file, label);
putc ('\n', file);
fprintf (file, "\t%s\t ", ASM_LONG);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (eh_label));
assemble_name (file, label);
putc ('\n', file);
putc ('\n', file); /* blank line */ putc ('\n', file); /* blank line */
} }
@ -1161,13 +1136,12 @@ expand_start_catch_block (declspecs, declarator)
else else
type = NULL_TREE; type = NULL_TREE;
false_label_rtx = gen_label_rtx (); /* These are saved for the exception table. */
push_label_entry (&false_label_stack, false_label_rtx);
/* This is saved for the exception table. */
push_rtl_perm (); push_rtl_perm ();
false_label_rtx = gen_label_rtx ();
protect_label_rtx = gen_label_rtx (); protect_label_rtx = gen_label_rtx ();
pop_rtl_from_perm (); pop_rtl_from_perm ();
push_label_entry (&false_label_stack, false_label_rtx);
push_label_entry (&false_label_stack, protect_label_rtx); push_label_entry (&false_label_stack, protect_label_rtx);
if (type) if (type)
@ -1436,40 +1410,63 @@ expand_throw (exp)
emit_jump (throw_label); emit_jump (throw_label);
} }
/* output the exception table */
void
build_exception_table ()
{
extern FILE *asm_out_file;
struct ehEntry *entry;
if (! doing_eh (0))
return;
exception_section ();
/* Beginning marker for table. */
fprintf (asm_out_file, " .global ___EXCEPTION_TABLE__\n");
fprintf (asm_out_file, " .align 4\n");
fprintf (asm_out_file, "___EXCEPTION_TABLE__:\n");
fprintf (asm_out_file, " .word 0, 0, 0\n");
while (entry = dequeue_eh_entry (&eh_table_output_queue)) {
output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label, entry->exception_handler_label);
}
/* Ending marker for table. */
fprintf (asm_out_file, " .global ___EXCEPTION_END__\n");
fprintf (asm_out_file, "___EXCEPTION_END__:\n");
fprintf (asm_out_file, " .word -1, -1, -1\n");
}
/* end of: my-cp-except.c */ /* end of: my-cp-except.c */
#endif #endif
/* Output the exception table.
Return the number of handlers. */
int
build_exception_table ()
{
int count = 0;
#ifdef TRY_NEW_EH
extern FILE *asm_out_file;
struct ehEntry *entry;
tree eh_node_decl;
if (! doing_eh (0))
return 0;
while (entry = dequeue_eh_entry (&eh_table_output_queue))
{
if (count == 0)
{
exception_section ();
/* Beginning marker for table. */
ASM_OUTPUT_ALIGN (asm_out_file, 2);
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
fprintf (asm_out_file, " .word 0, 0, 0\n");
}
count++;
output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label,
entry->exception_handler_label);
}
if (count)
{
/* Ending marker for table. */
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
fprintf (asm_out_file, " .word -1, -1, -1\n");
}
#endif /* TRY_NEW_EH */
return count;
}
void
register_exception_table ()
{
#ifdef TRY_NEW_EH
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
VOIDmode, 1,
gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
Pmode);
#endif /* TRY_NEW_EH */
}
/* Build a throw expression. */ /* Build a throw expression. */
tree tree
build_throw (e) build_throw (e)

View file

@ -148,9 +148,16 @@ cplus_expand_expr (exp, target, tmode, modifier)
{ {
if (pcc_struct_return) if (pcc_struct_return)
{ {
extern int flag_access_control;
int old_ac = flag_access_control;
tree init = build (RTL_EXPR, type, 0, return_target); tree init = build (RTL_EXPR, type, 0, return_target);
TREE_ADDRESSABLE (init) = 1; TREE_ADDRESSABLE (init) = 1;
flag_access_control = 0;
expand_aggr_init (slot, init, 0); expand_aggr_init (slot, init, 0);
flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
{ {
init = build (RTL_EXPR, build_reference_type (type), 0, init = build (RTL_EXPR, build_reference_type (type), 0,

View file

@ -217,6 +217,7 @@ perform_member_init (member, name, init, explicit)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
} }
expand_cleanups_to (NULL_TREE);
if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type)) if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member); cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member);
} }
@ -226,15 +227,19 @@ static tree
sort_member_init (t) sort_member_init (t)
tree t; tree t;
{ {
extern int warn_reorder;
tree x, member, name, field, init; tree x, member, name, field, init;
tree init_list = NULL_TREE; tree init_list = NULL_TREE;
tree fields_to_unmark = NULL_TREE; tree fields_to_unmark = NULL_TREE;
int found; int found;
int last_pos = 0;
tree last_field;
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member)) for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
{ {
int pos;
found = 0; found = 0;
for (x = current_member_init_list ; x ; x = TREE_CHAIN (x)) for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
{ {
/* If we cleared this out, then pay no attention to it. */ /* If we cleared this out, then pay no attention to it. */
if (TREE_PURPOSE (x) == NULL_TREE) if (TREE_PURPOSE (x) == NULL_TREE)
@ -264,6 +269,17 @@ sort_member_init (t)
field); field);
continue; continue;
} }
else
{
if (pos < last_pos && warn_reorder)
{
cp_warning_at ("member initializers for `%#D'", last_field);
cp_warning_at (" and `%#D'", field);
warning (" will be re-ordered to match declaration order");
}
last_pos = pos;
last_field = field;
}
init_list = chainon (init_list, init_list = chainon (init_list,
build_tree_list (name, TREE_VALUE (x))); build_tree_list (name, TREE_VALUE (x)));
@ -500,9 +516,10 @@ emit_base_init (t, immediately)
continue; continue;
member = convert_pointer_to (binfo, current_class_decl); member = convert_pointer_to (binfo, current_class_decl);
expand_aggr_init_1 (t_binfo, 0, expand_aggr_init_1 (binfo, 0,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (binfo), LOOKUP_COMPLAIN); BINFO_OFFSET_ZEROP (binfo), LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE);
} }
if (pass == 0) if (pass == 0)
@ -568,9 +585,10 @@ emit_base_init (t, immediately)
current_class_decl, BINFO_OFFSET (base_binfo)); current_class_decl, BINFO_OFFSET (base_binfo));
ref = build_indirect_ref (base, NULL_PTR); ref = build_indirect_ref (base, NULL_PTR);
expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE, expand_aggr_init_1 (base_binfo, 0, ref, NULL_TREE,
BINFO_OFFSET_ZEROP (base_binfo), BINFO_OFFSET_ZEROP (base_binfo),
LOOKUP_COMPLAIN); LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE);
} }
} }
CLEAR_BINFO_BASEINIT_MARKED (base_binfo); CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
@ -655,11 +673,6 @@ emit_base_init (t, immediately)
current_member_init_list = NULL_TREE; current_member_init_list = NULL_TREE;
/* It is possible for the initializers to need cleanups.
Expand those cleanups now that all the initialization
has been done. */
expand_cleanups_to (NULL_TREE);
if (! immediately) if (! immediately)
{ {
extern rtx base_init_insns; extern rtx base_init_insns;
@ -734,6 +747,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, expand_aggr_init_1 (binfo, exp, ref, init, 0,
LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY); LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY);
expand_cleanups_to (NULL_TREE);
CLEAR_BINFO_VBASE_INIT_MARKED (binfo); CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
} }
@ -1117,7 +1131,11 @@ expand_aggr_init (exp, init, alias_this)
int was_const_elts = TYPE_READONLY (TREE_TYPE (type)); int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
tree itype = init ? TREE_TYPE (init) : NULL_TREE; tree itype = init ? TREE_TYPE (init) : NULL_TREE;
if (was_const_elts) if (was_const_elts)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); {
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
}
if (init && TREE_TYPE (init) == NULL_TREE) if (init && TREE_TYPE (init) == NULL_TREE)
{ {
/* Handle bad initializers like: /* Handle bad initializers like:
@ -1139,7 +1157,8 @@ expand_aggr_init (exp, init, alias_this)
init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1)); init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_TYPE (exp) = type; TREE_TYPE (exp) = type;
if (init) TREE_TYPE (init) = itype; if (init)
TREE_TYPE (init) = itype;
return; return;
} }
@ -1187,6 +1206,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
{ {
rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0); rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
TREE_USED (rval) = 1;
expand_expr_stmt (rval); expand_expr_stmt (rval);
return; return;
} }
@ -1392,7 +1412,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
separately from the object being initialized. */ separately from the object being initialized. */
if (TREE_CODE (init) == TARGET_EXPR) if (TREE_CODE (init) == TARGET_EXPR)
{ {
if (init_type == type) if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
{ {
if (TREE_CODE (exp) == VAR_DECL if (TREE_CODE (exp) == VAR_DECL
|| TREE_CODE (exp) == RESULT_DECL) || TREE_CODE (exp) == RESULT_DECL)
@ -1966,12 +1986,6 @@ build_offset_ref (cname, name)
name, NULL_TREE, 1); name, NULL_TREE, 1);
#endif #endif
fnfields = lookup_fnfields (TYPE_BINFO (type), name, 1);
fields = lookup_field (type, name, 0, 0);
if (fields == error_mark_node || fnfields == error_mark_node)
return error_mark_node;
if (current_class_type == 0 if (current_class_type == 0
|| get_base_distance (type, current_class_type, 0, &basetypes) == -1) || get_base_distance (type, current_class_type, 0, &basetypes) == -1)
{ {
@ -1986,6 +2000,12 @@ build_offset_ref (cname, name)
else else
decl = C_C_D; decl = C_C_D;
fnfields = lookup_fnfields (basetypes, name, 1);
fields = lookup_field (basetypes, name, 0, 0);
if (fields == error_mark_node || fnfields == error_mark_node)
return error_mark_node;
/* A lot of this logic is now handled in lookup_field and /* A lot of this logic is now handled in lookup_field and
lookup_fnfield. */ lookup_fnfield. */
if (fnfields) if (fnfields)
@ -2018,7 +2038,6 @@ build_offset_ref (cname, name)
{ {
extern int flag_save_memoized_contexts; extern int flag_save_memoized_contexts;
/* This does not handle access checking yet. */
if (DECL_CHAIN (t) == NULL_TREE || dtor) if (DECL_CHAIN (t) == NULL_TREE || dtor)
{ {
enum access_type access; enum access_type access;
@ -2287,9 +2306,11 @@ resolve_offset_ref (exp)
{ {
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member)); basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
addr = convert_pointer_to (basetype, addr); addr = convert_pointer_to (basetype, addr);
member = convert (ptr_type_node, build_unary_op (ADDR_EXPR, member, 0)); member = convert (ptrdiff_type_node,
build_unary_op (ADDR_EXPR, member, 0));
return build1 (INDIRECT_REF, type, return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, ptr_type_node, addr, member)); build (PLUS_EXPR, build_pointer_type (type),
addr, member));
} }
else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
{ {
@ -3261,7 +3282,7 @@ build_new (placement, decl, init, use_global_new)
build_tree_list (NULL_TREE, rval)))); build_tree_list (NULL_TREE, rval))));
} }
return save_expr (rval); return rval;
} }
/* `expand_vec_init' performs initialization of a vector of aggregate /* `expand_vec_init' performs initialization of a vector of aggregate

View file

@ -75,6 +75,12 @@ void yyerror ();
struct obstack inline_text_obstack; struct obstack inline_text_obstack;
static char *inline_text_firstobj; static char *inline_text_firstobj;
/* This obstack is used to hold information about methods to be
synthesized. It should go away when synthesized methods are handled
properly (i.e. only when needed). */
struct obstack synth_obstack;
static char *synth_firstobj;
int end_of_file; int end_of_file;
/* Pending language change. /* Pending language change.
@ -564,6 +570,8 @@ init_lex ()
init_error (); init_error ();
gcc_obstack_init (&inline_text_obstack); gcc_obstack_init (&inline_text_obstack);
inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
gcc_obstack_init (&synth_obstack);
synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
/* Start it at 0, because check_newline is called at the very beginning /* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */ and will increment it to 1. */
@ -960,15 +968,6 @@ set_yydebug (value)
#endif #endif
} }
#ifdef SPEW_DEBUG
const char *
debug_yytranslate (value)
int value;
{
return yytname[YYTRANSLATE (value)];
}
#endif
/* Functions and data structures for #pragma interface. /* Functions and data structures for #pragma interface.
@ -1095,30 +1094,72 @@ set_vardecl_interface_info (prev, vars)
void void
do_pending_inlines () do_pending_inlines ()
{ {
struct pending_inline *prev = 0, *tail;
struct pending_inline *t; struct pending_inline *t;
/* Oops, we're still dealing with the last batch. */ /* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL) if (yychar == PRE_PARSED_FUNCTION_DECL)
return; return;
/* Reverse the pending inline functions, since /* Reverse the pending inline functions, since
they were cons'd instead of appended. */ they were cons'd instead of appended. */
{
for (t = pending_inlines; t; t = tail) struct pending_inline *prev = 0, *tail, *bottom = 0;
{ t = pending_inlines;
t->deja_vu = 1; pending_inlines = 0;
tail = t->next;
t->next = prev; for (; t; t = tail)
prev = t; {
} tail = t->next;
/* Reset to zero so that if the inline functions we are currently t->next = prev;
processing define inline functions of their own, that is handled t->deja_vu = 1;
correctly. ??? This hasn't been checked in a while. */ prev = t;
pending_inlines = 0; }
/* This kludge should go away when synthesized methods are handled
properly, i.e. only when needed. */
for (t = prev; t; t = t->next)
{
if (t->lineno <= 0)
{
tree f = t->fndecl;
DECL_PENDING_INLINE_INFO (f) = 0;
interface_unknown = t->interface == 1;
interface_only = t->interface == 0;
switch (- t->lineno)
{
case 0: case 1:
build_dtor (f); break;
case 2:
build_default_constructor (f); break;
case 3: case 4:
build_copy_constructor (f); break;
case 5: case 6:
build_assign_ref (f); break;
default:
;
}
if (tail)
tail->next = t->next;
else
prev = t->next;
if (! bottom)
bottom = t;
}
else
tail = t;
}
if (bottom)
{
obstack_free (&synth_obstack, bottom);
extract_interface_info ();
}
t = prev;
}
if (t == 0)
return;
/* Now start processing the first inline function. */ /* Now start processing the first inline function. */
t = prev;
my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE), my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
226); 226);
if (t->parm_vec) if (t->parm_vec)
@ -1660,8 +1701,8 @@ reinit_parse_for_block (yychar, obstackp, is_template)
When KIND == 6, build default operator = (X&). */ When KIND == 6, build default operator = (X&). */
tree tree
cons_up_default_function (type, name, fields, kind) cons_up_default_function (type, name, kind)
tree type, name, fields; tree type, name;
int kind; int kind;
{ {
extern tree void_list_node; extern tree void_list_node;
@ -1685,14 +1726,6 @@ cons_up_default_function (type, name, fields, kind)
case 2: case 2:
/* Default constructor. */ /* Default constructor. */
args = void_list_node; args = void_list_node;
{
if (declspecs)
declspecs = decl_tree_cons (NULL_TREE,
ridpointers [(int) RID_INLINE],
declspecs);
else
declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_INLINE]);
}
break; break;
case 3: case 3:
@ -1700,16 +1733,12 @@ cons_up_default_function (type, name, fields, kind)
/* Fall through... */ /* Fall through... */
case 4: case 4:
/* According to ARM $12.8, the default copy ctor will be declared, but /* According to ARM $12.8, the default copy ctor will be declared, but
not defined, unless it's needed. So we mark this as `inline'; that not defined, unless it's needed. */
way, if it's never used it won't be emitted. */
declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_INLINE]);
argtype = build_reference_type (type); argtype = build_reference_type (type);
args = tree_cons (NULL_TREE, args = tree_cons (NULL_TREE,
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
default_copy_constructor_body (&func_buf, &func_len, type, fields);
break; break;
case 5: case 5:
@ -1717,11 +1746,7 @@ cons_up_default_function (type, name, fields, kind)
/* Fall through... */ /* Fall through... */
case 6: case 6:
retref = 1; retref = 1;
declspecs = declspecs = build_decl_list (NULL_TREE, name);
decl_tree_cons (NULL_TREE, name,
decl_tree_cons (NULL_TREE,
ridpointers [(int) RID_INLINE],
NULL_TREE));
name = ansi_opname [(int) MODIFY_EXPR]; name = ansi_opname [(int) MODIFY_EXPR];
@ -1730,19 +1755,14 @@ cons_up_default_function (type, name, fields, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
default_assign_ref_body (&func_buf, &func_len, type, fields);
break; break;
default: default:
my_friendly_abort (59); my_friendly_abort (59);
} }
if (!func_buf) declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE],
{ declspecs);
func_len = 2;
func_buf = obstack_alloc (&inline_text_obstack, func_len);
strcpy (func_buf, "{}");
}
TREE_PARMLIST (args) = 1; TREE_PARMLIST (args) = 1;
@ -1751,52 +1771,27 @@ cons_up_default_function (type, name, fields, kind)
if (retref) if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator); declarator = build_parse_node (ADDR_EXPR, declarator);
fn = start_method (declspecs, declarator, NULL_TREE); fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
} }
if (fn == void_type_node) if (fn == void_type_node)
return fn; return fn;
current_base_init_list = NULL_TREE; if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
current_member_init_list = NULL_TREE; SET_DECL_IMPLICIT_INSTANTIATION (fn);
/* This kludge should go away when synthesized methods are handled
properly, i.e. only when needed. */
{ {
struct pending_inline *t; struct pending_inline *t;
t = (struct pending_inline *)
t = (struct pending_inline *) obstack_alloc (&inline_text_obstack, obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
sizeof (struct pending_inline)); t->lineno = -kind;
t->lineno = lineno; t->can_free = 0;
#if 1
t->filename = input_filename;
#else /* This breaks; why? */
#define MGMSG "(synthetic code at) "
t->filename = obstack_alloc (&inline_text_obstack,
strlen (input_filename) + sizeof (MGMSG) + 1);
strcpy (t->filename, MGMSG);
strcat (t->filename, input_filename);
#endif
t->token = YYEMPTY;
t->token_value = 0;
t->buf = func_buf;
t->len = func_len;
t->can_free = 1;
t->deja_vu = 0;
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (fn))
warn_if_unknown_interface ();
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (fn, t); store_pending_inline (fn, t);
if (interface_unknown)
TREE_PUBLIC (fn) = 0;
else
{
TREE_PUBLIC (fn) = 1;
DECL_EXTERNAL (fn) = interface_only;
}
} }
finish_method (fn);
#ifdef DEBUG_DEFAULT_FUNCTIONS #ifdef DEBUG_DEFAULT_FUNCTIONS
{ char *fn_type = NULL; { char *fn_type = NULL;
tree t = name; tree t = name;
@ -1818,14 +1813,13 @@ cons_up_default_function (type, name, fields, kind)
} }
#endif /* DEBUG_DEFAULT_FUNCTIONS */ #endif /* DEBUG_DEFAULT_FUNCTIONS */
DECL_CLASS_CONTEXT (fn) = TYPE_MAIN_VARIANT (type);
/* Show that this function was generated by the compiler. */ /* Show that this function was generated by the compiler. */
SET_DECL_ARTIFICIAL (fn); SET_DECL_ARTIFICIAL (fn);
return fn; return fn;
} }
#if 0
/* Used by default_copy_constructor_body. For the anonymous union /* Used by default_copy_constructor_body. For the anonymous union
in TYPE, return the member that is at least as large as the rest in TYPE, return the member that is at least as large as the rest
of the members, so we can copy it. */ of the members, so we can copy it. */
@ -2171,6 +2165,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
strcpy (*bufp, prologue.object_base); strcpy (*bufp, prologue.object_base);
strcat (*bufp, "{}"); strcat (*bufp, "{}");
} }
#endif
/* Heuristic to tell whether the user is missing a semicolon /* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message after a struct or enum declaration. Emit an error message
@ -2182,17 +2177,17 @@ check_for_missing_semicolon (type)
if (yychar < 0) if (yychar < 0)
yychar = yylex (); yychar = yylex ();
if (yychar > 255 if ((yychar > 255
&& yychar != SCSPEC && yychar != SCSPEC
&& yychar != IDENTIFIER && yychar != IDENTIFIER
&& yychar != TYPENAME) && yychar != TYPENAME)
|| end_of_file)
{ {
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
error ("semicolon missing after %s declaration", error ("semicolon missing after %s declaration",
TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct"); TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
else else
error ("semicolon missing after declaration of `%s'", cp_error ("semicolon missing after declaration of `%T'", type);
TYPE_NAME_STRING (type));
shadow_tag (build_tree_list (0, type)); shadow_tag (build_tree_list (0, type));
} }
/* Could probably also hack cases where class { ... } f (); appears. */ /* Could probably also hack cases where class { ... } f (); appears. */
@ -2875,7 +2870,7 @@ check_newline ()
if (c_header_level && --c_header_level == 0) if (c_header_level && --c_header_level == 0)
{ {
if (entering_c_header) if (entering_c_header)
warning ("Badly nested C headers from preprocessor"); warning ("badly nested C headers from preprocessor");
--pending_lang_change; --pending_lang_change;
} }
if (flag_cadillac) if (flag_cadillac)
@ -4203,12 +4198,12 @@ real_yylex ()
|| ((result >> (num_bits - 1)) & 1) == 0) || ((result >> (num_bits - 1)) & 1) == 0)
yylval.ttype yylval.ttype
= build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0 = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
>> (HOST_BITS_PER_INT - num_bits)), >> (HOST_BITS_PER_WIDE_INT - num_bits)),
0); 0);
else else
yylval.ttype yylval.ttype
= build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0 = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
>> (HOST_BITS_PER_INT - num_bits)), >> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1); -1);
if (num_chars<=1) if (num_chars<=1)
TREE_TYPE (yylval.ttype) = char_type_node; TREE_TYPE (yylval.ttype) = char_type_node;

View file

@ -58,14 +58,16 @@ enum rid
RID_VOLATILE, RID_VOLATILE,
RID_FRIEND, RID_FRIEND,
RID_VIRTUAL, RID_VIRTUAL,
RID_SIGNED,
RID_AUTO,
RID_MUTABLE,
/* This is where grokdeclarator ends its search when setting the specbits. */
RID_PUBLIC, RID_PUBLIC,
RID_PRIVATE, RID_PRIVATE,
RID_PROTECTED, RID_PROTECTED,
RID_SIGNED,
RID_EXCEPTION, RID_EXCEPTION,
RID_RAISES,
RID_AUTO,
RID_MUTABLE,
RID_TEMPLATE, RID_TEMPLATE,
RID_SIGNATURE, RID_SIGNATURE,
/* Before adding enough to get up to 64, the RIDBIT_* macros /* Before adding enough to get up to 64, the RIDBIT_* macros
@ -76,6 +78,7 @@ enum rid
#define NORID RID_UNUSED #define NORID RID_UNUSED
#define RID_FIRST_MODIFIER RID_EXTERN #define RID_FIRST_MODIFIER RID_EXTERN
#define RID_LAST_MODIFIER RID_MUTABLE
/* The type that can represent all values of RIDBIT. */ /* The type that can represent all values of RIDBIT. */
/* We assume that we can stick in at least 32 bits into this. */ /* We assume that we can stick in at least 32 bits into this. */

View file

@ -313,6 +313,7 @@ flush_repeats (type)
OB_PUTC ('_'); OB_PUTC ('_');
} }
static int numeric_outputed_need_bar;
static void build_overload_identifier (); static void build_overload_identifier ();
static void static void
@ -463,9 +464,9 @@ build_overload_identifier (name)
icat (nparms); icat (nparms);
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
tree parm = TREE_VEC_ELT (parmlist, i); tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i); tree arg = TREE_VEC_ELT (arglist, i);
if (TREE_CODE (parm) == IDENTIFIER_NODE) if (TREE_CODE (parm) == TYPE_DECL)
{ {
/* This parameter is a type. */ /* This parameter is a type. */
OB_PUTC ('Z'); OB_PUTC ('Z');
@ -476,11 +477,17 @@ build_overload_identifier (name)
/* It's a PARM_DECL. */ /* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0); build_overload_name (TREE_TYPE (parm), 0, 0);
build_overload_value (parm, arg); build_overload_value (parm, arg);
numeric_outputed_need_bar = 1;
} }
} }
} }
else else
{ {
if (numeric_outputed_need_bar)
{
OB_PUTC ('_');
numeric_outputed_need_bar = 0;
}
icat (IDENTIFIER_LENGTH (name)); icat (IDENTIFIER_LENGTH (name));
OB_PUTID (name); OB_PUTID (name);
} }
@ -772,6 +779,7 @@ build_overload_name (parmtypes, begin, end)
icat (i); icat (i);
if (i > 9) if (i > 9)
OB_PUTC ('_'); OB_PUTC ('_');
numeric_outputed_need_bar = 0;
build_overload_nested_name (TYPE_NAME (parmtype)); build_overload_nested_name (TYPE_NAME (parmtype));
} }
else else
@ -817,6 +825,18 @@ build_overload_name (parmtypes, begin, end)
if (end) OB_FINISH (); if (end) OB_FINISH ();
return (char *)obstack_base (&scratch_obstack); return (char *)obstack_base (&scratch_obstack);
} }
tree
build_static_name (basetype, name)
tree basetype, name;
{
char *basename = build_overload_name (basetype, 1, 1);
char *buf = (char *) alloca (IDENTIFIER_LENGTH (name)
+ sizeof (STATIC_NAME_FORMAT)
+ strlen (basename));
sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name));
return get_identifier (buf);
}
/* Generate an identifier that encodes the (ANSI) exception TYPE. */ /* Generate an identifier that encodes the (ANSI) exception TYPE. */
@ -852,18 +872,17 @@ build_decl_overload (dname, parms, for_method)
/* member operators new and delete look like methods at this point. */ /* member operators new and delete look like methods at this point. */
if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST) if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST)
{ {
if (TREE_VALUE (parms) == sizetype if (dname == ansi_opname[(int) DELETE_EXPR])
&& TREE_CHAIN (parms) == void_list_node) return get_identifier ("__builtin_delete");
else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
return get_identifier ("__builtin_vec_delete");
else if (TREE_CHAIN (parms) == void_list_node)
{ {
if (dname == ansi_opname[(int) NEW_EXPR]) if (dname == ansi_opname[(int) NEW_EXPR])
return get_identifier ("__builtin_new"); return get_identifier ("__builtin_new");
else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
return get_identifier ("__builtin_vec_new"); return get_identifier ("__builtin_vec_new");
} }
else if (dname == ansi_opname[(int) DELETE_EXPR])
return get_identifier ("__builtin_delete");
else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
return get_identifier ("__builtin_vec_delete");
} }
OB_INIT (); OB_INIT ();
@ -901,6 +920,7 @@ build_decl_overload (dname, parms, for_method)
{ {
ALLOCATE_TYPEVEC (parms); ALLOCATE_TYPEVEC (parms);
nofold = 0; nofold = 0;
numeric_outputed_need_bar = 0;
if (for_method) if (for_method)
{ {
build_overload_name (TREE_VALUE (parms), 0, 0); build_overload_name (TREE_VALUE (parms), 0, 0);
@ -1461,11 +1481,13 @@ hack_identifier (value, name, yychar)
if (really_overloaded_fn (value)) if (really_overloaded_fn (value))
{ {
tree t = get_first_fn (value); tree t = get_first_fn (value);
while (t) for (; t; t = DECL_CHAIN (t))
{ {
if (TREE_CODE (t) == TEMPLATE_DECL)
continue;
assemble_external (t); assemble_external (t);
TREE_USED (t) = 1; TREE_USED (t) = 1;
t = DECL_CHAIN (t);
} }
} }
else if (TREE_CODE (value) == TREE_LIST) else if (TREE_CODE (value) == TREE_LIST)
@ -1946,3 +1968,204 @@ emit_thunk (thunk_fndecl)
decl_printable_name = save_decl_printable_name; decl_printable_name = save_decl_printable_name;
current_function_decl = 0; current_function_decl = 0;
} }
/* Code for synthesizing methods which have default semantics defined. */
void
build_default_constructor (fndecl)
tree fndecl;
{
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
setup_vtbl_ptr ();
finish_function (lineno, 0);
}
/* For the anonymous union in TYPE, return the member that is at least as
large as the rest of the members, so we can copy it. */
static tree
largest_union_member (type)
tree type;
{
tree f, type_size = TYPE_SIZE (type);
for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
if (simple_cst_equal (DECL_SIZE (f), type_size))
return f;
/* We should always find one. */
my_friendly_abort (323);
return NULL_TREE;
}
/* Generate code for default X(X&) constructor. */
void
build_copy_constructor (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree t;
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
clear_last_expr ();
push_momentary ();
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
if (! TYPE_HAS_COMPLEX_INIT_REF (current_class_type))
{
t = build (INIT_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
else
{
tree fields = TYPE_FIELDS (current_class_type);
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
t = TREE_CHAIN (t))
{
tree basetype = BINFO_TYPE (t);
tree p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
}
for (i = 0; i < n_bases; ++i)
{
tree p, basetype = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (basetype))
continue;
basetype = BINFO_TYPE (basetype);
p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
}
for (; fields; fields = TREE_CHAIN (fields))
{
tree name, init, t;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
{
if (VFIELD_NAME_P (DECL_NAME (fields)))
continue;
if (VBASE_NAME_P (DECL_NAME (fields)))
continue;
/* True for duplicate members. */
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
else if ((t = TREE_TYPE (fields)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& TYPE_FIELDS (t) != NULL_TREE)
fields = largest_union_member (t);
else
continue;
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
init = build_tree_list (NULL_TREE, init);
current_member_init_list
= tree_cons (DECL_NAME (fields), init, current_member_init_list);
}
current_member_init_list = nreverse (current_member_init_list);
setup_vtbl_ptr ();
}
pop_momentary ();
finish_function (lineno, 0);
}
void
build_assign_ref (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
push_momentary ();
parm = convert_from_reference (parm);
if (! TYPE_HAS_COMPLEX_ASSIGN_REF (current_class_type))
{
tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
else
{
tree fields = TYPE_FIELDS (current_class_type);
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
for (i = 0; i < n_bases; ++i)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (TYPE_HAS_ASSIGN_REF (basetype))
{
tree p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
p = build_member_call (TYPE_NESTED_NAME (basetype),
ansi_opname [MODIFY_EXPR],
build_tree_list (NULL_TREE, p));
expand_expr_stmt (p);
}
}
for (; fields; fields = TREE_CHAIN (fields))
{
tree comp, init, t;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
{
if (VFIELD_NAME_P (DECL_NAME (fields)))
continue;
if (VBASE_NAME_P (DECL_NAME (fields)))
continue;
/* True for duplicate members. */
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
else if ((t = TREE_TYPE (fields)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& TYPE_FIELDS (t) != NULL_TREE)
fields = largest_union_member (t);
else
continue;
comp = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields);
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
}
}
c_expand_return (C_C_D);
pop_momentary ();
finish_function (lineno, 0);
}
void
build_dtor (fndecl)
tree fndecl;
{
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
finish_function (lineno, 0);
}

File diff suppressed because it is too large Load diff

View file

@ -81,18 +81,19 @@ process_template_parm (list, next)
{ {
tree parm; tree parm;
tree decl = 0; tree decl = 0;
tree defval;
int is_type; int is_type;
parm = next; parm = next;
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259); my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE; defval = TREE_PURPOSE (parm);
parm = TREE_VALUE (parm);
is_type = TREE_PURPOSE (parm) == class_type_node;
if (!is_type) if (!is_type)
{ {
tree tinfo = 0; tree tinfo = 0;
parm = TREE_PURPOSE (parm); my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
parm = TREE_VALUE (parm);
/* is a const-param */ /* is a const-param */
parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next), parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE); PARM, 0, NULL_TREE);
/* A template parameter is not modifiable. */ /* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
@ -117,11 +118,19 @@ process_template_parm (list, next)
else else
{ {
tree t = make_node (TEMPLATE_TYPE_PARM); tree t = make_node (TEMPLATE_TYPE_PARM);
decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t); decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
TYPE_NAME (t) = decl; TYPE_MAIN_DECL (t) = decl;
TREE_VALUE (parm) = t; parm = decl;
if (defval)
{
if (IDENTIFIER_HAS_TYPE_VALUE (defval))
defval = IDENTIFIER_TYPE_VALUE (defval);
else
defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
}
} }
pushdecl (decl); pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm); return chainon (list, parm);
} }
@ -135,6 +144,7 @@ end_template_parm_list (parms)
tree parms; tree parms;
{ {
int nparms = 0; int nparms = 0;
int saw_default = 0;
tree saved_parmlist; tree saved_parmlist;
tree parm; tree parm;
for (parm = parms; parm; parm = TREE_CHAIN (parm)) for (parm = parms; parm; parm = TREE_CHAIN (parm))
@ -143,13 +153,19 @@ end_template_parm_list (parms)
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
{ {
tree p = parm; tree p = TREE_VALUE (parm);
if (TREE_CODE (p) == TREE_LIST) if (TREE_PURPOSE (parm))
saw_default = 1;
else if (saw_default)
{ {
tree t = TREE_VALUE (p); error ("if a default argument is given for one template parameter");
TREE_VALUE (p) = NULL_TREE; error ("default arguments must be given for all subsequent");
p = TREE_PURPOSE (p); error ("parameters as well");
my_friendly_assert (TREE_CODE (p) == IDENTIFIER_NODE, 261); }
if (TREE_CODE (p) == TYPE_DECL)
{
tree t = TREE_TYPE (p);
TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms); TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
} }
else else
@ -158,7 +174,7 @@ end_template_parm_list (parms)
DECL_INITIAL (p) = NULL_TREE; DECL_INITIAL (p) = NULL_TREE;
TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms); TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
} }
TREE_VEC_ELT (saved_parmlist, nparms) = p; TREE_VEC_ELT (saved_parmlist, nparms) = parm;
} }
set_current_level_tags_transparency (1); set_current_level_tags_transparency (1);
processing_template_decl++; processing_template_decl++;
@ -317,7 +333,7 @@ grok_template_type (tvec, type)
{ {
/* we are here for cases like const T* etc. */ /* we are here for cases like const T* etc. */
grok_template_type (tvec, &TYPE_MAIN_VARIANT (*type)); grok_template_type (tvec, &TYPE_MAIN_VARIANT (*type));
*type = c_build_type_variant (TYPE_MAIN_VARIANT (*type), *type = cp_build_type_variant (TYPE_MAIN_VARIANT (*type),
TYPE_READONLY (*type), TYPE_READONLY (*type),
TYPE_VOLATILE (*type)); TYPE_VOLATILE (*type));
} }
@ -354,51 +370,68 @@ coerce_template_parms (parms, arglist, in_decl)
tree parms, arglist; tree parms, arglist;
tree in_decl; tree in_decl;
{ {
int nparms, i, lost = 0; int nparms, nargs, i, lost = 0;
tree vec; tree vec;
if (TREE_CODE (arglist) == TREE_VEC) if (arglist == NULL_TREE)
nparms = TREE_VEC_LENGTH (arglist); nargs = 0;
else if (TREE_CODE (arglist) == TREE_VEC)
nargs = TREE_VEC_LENGTH (arglist);
else else
nparms = list_length (arglist); nargs = list_length (arglist);
if (nparms != TREE_VEC_LENGTH (parms))
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
|| (nargs < nparms
&& TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
{ {
error ("incorrect number of parameters (%d, should be %d)", error ("incorrect number of parameters (%d, should be %d)",
nparms, TREE_VEC_LENGTH (parms)); nargs, nparms);
if (in_decl) if (in_decl)
cp_error_at ("in template expansion for decl `%D'", in_decl); cp_error_at ("in template expansion for decl `%D'", in_decl);
return error_mark_node; return error_mark_node;
} }
if (TREE_CODE (arglist) == TREE_VEC) if (arglist && TREE_CODE (arglist) == TREE_VEC)
vec = copy_node (arglist); vec = copy_node (arglist);
else else
{ {
vec = make_tree_vec (nparms); vec = make_tree_vec (nparms);
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
tree arg = arglist; tree arg;
arglist = TREE_CHAIN (arglist);
if (arg == error_mark_node) if (arglist)
lost++; {
arg = arglist;
arglist = TREE_CHAIN (arglist);
if (arg == error_mark_node)
lost++;
else
arg = TREE_VALUE (arg);
}
else else
arg = TREE_VALUE (arg); arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
TREE_VEC_ELT (vec, i) = arg; TREE_VEC_ELT (vec, i) = arg;
} }
} }
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
tree arg = TREE_VEC_ELT (vec, i); tree arg = TREE_VEC_ELT (vec, i);
tree parm = TREE_VEC_ELT (parms, i); tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree val = 0; tree val = 0;
int is_type, requires_type; int is_type, requires_type;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; requires_type = TREE_CODE (parm) == TYPE_DECL;
if (is_type != requires_type) if (is_type != requires_type)
{ {
if (in_decl) if (in_decl)
cp_error_at ("type/value mismatch in template parameter list for `%D'", in_decl); cp_error ("type/value mismatch in template parameter list for `%D'",
in_decl);
lost++; lost++;
TREE_VEC_ELT (vec, i) = error_mark_node; TREE_VEC_ELT (vec, i) = error_mark_node;
continue; continue;
@ -415,7 +448,7 @@ coerce_template_parms (parms, arglist, in_decl)
{ {
grok_template_type (vec, &TREE_TYPE (parm)); grok_template_type (vec, &TREE_TYPE (parm));
val = digest_init (TREE_TYPE (parm), arg, (tree *) 0); val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
if (val == error_mark_node) if (val == error_mark_node)
; ;
@ -489,12 +522,13 @@ mangle_class_name_for_template (name, parms, arglist)
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i); tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree arg = TREE_VEC_ELT (arglist, i);
if (i) if (i)
ccat (','); ccat (',');
if (TREE_CODE (parm) == IDENTIFIER_NODE) if (TREE_CODE (parm) == TYPE_DECL)
{ {
cat (type_as_string (arg, 0)); cat (type_as_string (arg, 0));
continue; continue;
@ -573,7 +607,7 @@ lookup_template_class (d1, arglist, in_decl)
} }
parmlist = DECL_TEMPLATE_PARMS (template); parmlist = DECL_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, in_decl); arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node) if (arglist == error_mark_node)
return error_mark_node; return error_mark_node;
if (uses_template_parms (arglist)) if (uses_template_parms (arglist))
@ -619,11 +653,11 @@ push_template_decls (parmlist, arglist, class_level)
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
int requires_type, is_type; int requires_type, is_type;
tree parm = TREE_VEC_ELT (parmlist, i); tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i); tree arg = TREE_VEC_ELT (arglist, i);
tree decl = 0; tree decl = 0;
requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; requires_type = TREE_CODE (parm) == TYPE_DECL;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
if (is_type) if (is_type)
{ {
@ -635,7 +669,7 @@ push_template_decls (parmlist, arglist, class_level)
} }
decl = arg; decl = arg;
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273); my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
decl = build_decl (TYPE_DECL, parm, decl); decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
} }
else else
{ {
@ -864,23 +898,25 @@ instantiate_member_templates (classname)
&TREE_VEC_ELT (parmvec, 0)); &TREE_VEC_ELT (parmvec, 0));
type = IDENTIFIER_TYPE_VALUE (id); type = IDENTIFIER_TYPE_VALUE (id);
my_friendly_assert (type != 0, 277); my_friendly_assert (type != 0, 277);
if (CLASSTYPE_INTERFACE_UNKNOWN (type)) if (flag_external_templates)
{ {
DECL_EXTERNAL (t2) = 0; if (CLASSTYPE_INTERFACE_UNKNOWN (type))
TREE_PUBLIC (t2) = 0; {
} DECL_EXTERNAL (t2) = 0;
else TREE_PUBLIC (t2) = 0;
{ }
DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type); else
TREE_PUBLIC (t2) = 1; {
DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type);
TREE_PUBLIC (t2) = 1;
}
} }
break; break;
case 1: case 1:
/* Failure. */ /* Failure. */
failure: failure:
cp_error ("type unification error instantiating %T::%D", cp_error_at ("type unification error instantiating `%D'", tdecl);
classname, tdecl); cp_error ("while instantiating members of `%T'", classname);
cp_error_at ("for template declaration `%D'", tdecl);
continue /* loop of members */; continue /* loop of members */;
default: default:
@ -1125,7 +1161,7 @@ tsubst (t, args, nargs, in_decl)
&& type != integer_type_node && type != integer_type_node
&& type != void_type_node && type != void_type_node
&& type != char_type_node) && type != char_type_node)
type = c_build_type_variant (tsubst (type, args, nargs, in_decl), type = cp_build_type_variant (tsubst (type, args, nargs, in_decl),
TYPE_READONLY (type), TYPE_READONLY (type),
TYPE_VOLATILE (type)); TYPE_VOLATILE (type));
switch (TREE_CODE (t)) switch (TREE_CODE (t))
@ -1162,7 +1198,7 @@ tsubst (t, args, nargs, in_decl)
tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl)); tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
return c_build_type_variant (args[TEMPLATE_TYPE_IDX (t)], return cp_build_type_variant (args[TEMPLATE_TYPE_IDX (t)],
TYPE_READONLY (t), TYPE_READONLY (t),
TYPE_VOLATILE (t)); TYPE_VOLATILE (t));
@ -1356,9 +1392,10 @@ tsubst (t, args, nargs, in_decl)
if (!got_it) if (!got_it)
{ {
r = build_decl_overload (r, TYPE_VALUES (type), tree a = build_decl_overload (r, TYPE_VALUES (type),
DECL_CONTEXT (t) != NULL_TREE); DECL_CONTEXT (t) != NULL_TREE);
r = build_lang_decl (FUNCTION_DECL, r, type); r = build_lang_decl (FUNCTION_DECL, r, type);
DECL_ASSEMBLER_NAME (r) = a;
} }
else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r)) else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r))
{ {
@ -1392,9 +1429,11 @@ tsubst (t, args, nargs, in_decl)
make_decl_rtl (r, NULL_PTR, 1); make_decl_rtl (r, NULL_PTR, 1);
DECL_ARGUMENTS (r) = fnargs; DECL_ARGUMENTS (r) = fnargs;
DECL_RESULT (r) = result; DECL_RESULT (r) = result;
#if 0
if (DECL_CONTEXT (t) == NULL_TREE if (DECL_CONTEXT (t) == NULL_TREE
|| TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't') || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
push_overloaded_decl_top_level (r, 0); push_overloaded_decl_top_level (r, 0);
#endif
return r; return r;
} }
@ -1442,7 +1481,7 @@ tsubst (t, args, nargs, in_decl)
{ {
int len = TREE_VEC_LENGTH (t), need_new = 0, i; int len = TREE_VEC_LENGTH (t), need_new = 0, i;
tree *elts = (tree *) alloca (len * sizeof (tree)); tree *elts = (tree *) alloca (len * sizeof (tree));
bzero (elts, len * sizeof (tree)); bzero ((char *) elts, len * sizeof (tree));
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
@ -1472,7 +1511,7 @@ tsubst (t, args, nargs, in_decl)
r = build_pointer_type (type); r = build_pointer_type (type);
else else
r = build_reference_type (type); r = build_reference_type (type);
r = c_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t)); r = cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));
/* Will this ever be needed for TYPE_..._TO values? */ /* Will this ever be needed for TYPE_..._TO values? */
layout_type (r); layout_type (r);
return r; return r;
@ -1781,6 +1820,7 @@ overload_template_name (id, classlevel)
|| TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286); || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
decl = build_decl (TYPE_DECL, template, t); decl = build_decl (TYPE_DECL, template, t);
SET_DECL_ARTIFICIAL (decl);
#if 0 /* fix this later */ #if 0 /* fix this later */
/* We don't want to call here if the work has already been done. */ /* We don't want to call here if the work has already been done. */
@ -1890,7 +1930,7 @@ reinit_parse_for_template (yychar, d1, d2)
if (!template_info) if (!template_info)
{ {
template_info = (struct template_info *) permalloc (sizeof (struct template_info)); template_info = (struct template_info *) permalloc (sizeof (struct template_info));
bzero (template_info, sizeof (struct template_info)); bzero ((char *) template_info, sizeof (struct template_info));
DECL_TEMPLATE_INFO (d2) = template_info; DECL_TEMPLATE_INFO (d2) = template_info;
} }
template_info->filename = input_filename; template_info->filename = input_filename;
@ -1940,7 +1980,7 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
my_friendly_assert (ntparms > 0, 292); my_friendly_assert (ntparms > 0, 292);
if (!subr) if (!subr)
bzero (targs, sizeof (tree) * ntparms); bzero ((char *) targs, sizeof (tree) * ntparms);
while (parms while (parms
&& parms != void_list_node && parms != void_list_node
@ -1968,9 +2008,16 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
arg = TREE_TYPE (arg); arg = TREE_TYPE (arg);
} }
#endif #endif
if (TREE_CODE (arg) == FUNCTION_TYPE if (TREE_CODE (parm) != REFERENCE_TYPE)
|| TREE_CODE (arg) == METHOD_TYPE) {
arg = build_pointer_type (arg); if (TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
arg = build_pointer_type (arg);
else if (TREE_CODE (arg) == ARRAY_TYPE)
arg = build_pointer_type (TREE_TYPE (arg));
else
arg = TYPE_MAIN_VARIANT (arg);
}
switch (unify (tparms, targs, ntparms, parm, arg, nsubsts)) switch (unify (tparms, targs, ntparms, parm, arg, nsubsts))
{ {
@ -2035,22 +2082,20 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1; return 1;
} }
idx = TEMPLATE_TYPE_IDX (parm); idx = TEMPLATE_TYPE_IDX (parm);
/* Template type parameters cannot contain cv-quals; i.e.
template <class T> void f (T& a, T& b) will not generate
void f (const int& a, const int& b). */
if (TYPE_READONLY (arg) > TYPE_READONLY (parm)
|| TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
return 1;
arg = TYPE_MAIN_VARIANT (arg);
/* Simple cases: Value already set, does match or doesn't. */ /* Simple cases: Value already set, does match or doesn't. */
if (targs[idx] == arg) if (targs[idx] == arg)
return 0; return 0;
else if (targs[idx]) else if (targs[idx])
{
if (TYPE_MAIN_VARIANT (targs[idx]) == TYPE_MAIN_VARIANT (arg))
/* allow different parms to have different cv-qualifiers */;
else
return 1;
}
/* Check for mixed types and values. */
if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE)
return 1; return 1;
/* Allow trivial conversions. */ /* Check for mixed types and values. */
if (TYPE_READONLY (parm) < TYPE_READONLY (arg) if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
|| TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
return 1; return 1;
targs[idx] = arg; targs[idx] = arg;
return 0; return 0;
@ -2106,7 +2151,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
case REAL_TYPE: case REAL_TYPE:
case INTEGER_TYPE: case INTEGER_TYPE:
if (TREE_CODE (parm) == INTEGER_TYPE && TREE_CODE (arg) == INTEGER_TYPE) if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (TREE_CODE (parm) == INTEGER_TYPE)
{ {
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, ntparms, && unify (tparms, targs, ntparms,
@ -2377,16 +2425,20 @@ do_function_instantiation (declspecs, declarator, storage)
if (flag_external_templates) if (flag_external_templates)
return; return;
if (DECL_EXPLICIT_INSTANTIATION (result) && ! DECL_EXTERNAL (result)) if (DECL_EXPLICIT_INSTANTIATION (result) && TREE_PUBLIC (result))
return; return;
SET_DECL_EXPLICIT_INSTANTIATION (result); SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE) if (storage == NULL_TREE)
DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines; {
TREE_PUBLIC (result) = 1;
DECL_EXTERNAL (result) = (DECL_INLINE (result)
&& ! flag_implement_inlines);
TREE_STATIC (result) = ! DECL_EXTERNAL (result);
}
else if (storage == ridpointers[(int) RID_EXTERN]) else if (storage == ridpointers[(int) RID_EXTERN])
DECL_EXTERNAL (result) = 1; ;
else else
cp_error ("storage class `%D' applied to template instantiation", cp_error ("storage class `%D' applied to template instantiation",
storage); storage);
@ -2399,12 +2451,11 @@ do_type_instantiation (name, storage)
tree t = TREE_TYPE (name); tree t = TREE_TYPE (name);
int extern_p; int extern_p;
/* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */
if (flag_external_templates) if (flag_external_templates)
return; return;
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
return;
if (TYPE_SIZE (t) == NULL_TREE) if (TYPE_SIZE (t) == NULL_TREE)
{ {
cp_error ("explicit instantiation of `%#T' before definition of template", cp_error ("explicit instantiation of `%#T' before definition of template",
@ -2423,30 +2474,62 @@ do_type_instantiation (name, storage)
extern_p = 0; extern_p = 0;
} }
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); /* We've already instantiated this. */
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p; if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && CLASSTYPE_INTERFACE_KNOWN (t))
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
if (! extern_p)
{ {
CLASSTYPE_DEBUG_REQUESTED (t) = 1; if (! extern_p)
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0; cp_pedwarn ("multiple explicit instantiation of `%#T'", t);
rest_of_type_compilation (t, 1); return;
} }
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
if (! extern_p)
{
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = 0;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
rest_of_type_compilation (t, 1);
}
}
instantiate_member_templates (TYPE_IDENTIFIER (t));
/* this should really be done by instantiate_member_templates */ /* this should really be done by instantiate_member_templates */
{ {
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; method; method = TREE_CHAIN (method)) for (; tmp; tmp = TREE_CHAIN (tmp))
{ {
SET_DECL_EXPLICIT_INSTANTIATION (method); if (DECL_TEMPLATE_SPECIALIZATION (tmp)
TREE_PUBLIC (method) = 1; || (DECL_USE_TEMPLATE (tmp) == 0
DECL_EXTERNAL (method) && CLASSTYPE_TEMPLATE_SPECIALIZATION (t)))
= (extern_p || (DECL_INLINE (method) && ! flag_implement_inlines)); continue;
}
}
/* and data member templates, too */ SET_DECL_EXPLICIT_INSTANTIATION (tmp);
if (! extern_p)
{
TREE_PUBLIC (tmp) = 1;
DECL_EXTERNAL (tmp) = (DECL_INLINE (tmp)
&& ! flag_implement_inlines);
TREE_STATIC (tmp) = ! DECL_EXTERNAL (tmp);
}
}
#if 0
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
{
if (TREE_CODE (tmp) == VAR_DECL)
/* eventually do something */;
}
#endif
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
}
} }
tree tree

View file

@ -236,7 +236,7 @@ my_new_memoized_entry (chain)
struct memoized_entry *p = struct memoized_entry *p =
(struct memoized_entry *)obstack_alloc (&type_obstack_entries, (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
sizeof (struct memoized_entry)); sizeof (struct memoized_entry));
bzero (p, sizeof (struct memoized_entry)); bzero ((char *) p, sizeof (struct memoized_entry));
MEMOIZED_CHAIN (p) = chain; MEMOIZED_CHAIN (p) = chain;
MEMOIZED_UID (p) = ++my_memoized_entry_counter; MEMOIZED_UID (p) = ++my_memoized_entry_counter;
return p; return p;
@ -768,6 +768,7 @@ compute_access (basetype_path, field)
tree types; tree types;
tree context; tree context;
int protected_ok, via_protected; int protected_ok, via_protected;
extern int flag_access_control;
#if 1 #if 1
/* Replaces static decl above. */ /* Replaces static decl above. */
tree previous_scope; tree previous_scope;
@ -776,6 +777,9 @@ compute_access (basetype_path, field)
((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field)) ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
|| (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field))); || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
if (! flag_access_control)
return access_public;
/* The field lives in the current class. */ /* The field lives in the current class. */
if (BINFO_TYPE (basetype_path) == current_class_type) if (BINFO_TYPE (basetype_path) == current_class_type)
return access_public; return access_public;
@ -1913,6 +1917,10 @@ get_matching_virtual (binfo, fndecl, dtorp)
if (IDENTIFIER_VIRTUAL_P (declarator) == 0) if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE; return NULL_TREE;
baselink = get_virtuals_named_this (binfo);
if (baselink == NULL_TREE)
return NULL_TREE;
drettype = TREE_TYPE (TREE_TYPE (fndecl)); drettype = TREE_TYPE (TREE_TYPE (fndecl));
dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
if (DECL_STATIC_FUNCTION_P (fndecl)) if (DECL_STATIC_FUNCTION_P (fndecl))
@ -1920,8 +1928,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
else else
instptr_type = TREE_TYPE (TREE_VALUE (dtypes)); instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
for (baselink = get_virtuals_named_this (binfo); for (; baselink; baselink = next_baselink (baselink))
baselink; baselink = next_baselink (baselink))
{ {
for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp)) for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
{ {
@ -1945,7 +1952,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1)) && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
{ {
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl); cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error ("overriding definition as `%#D'", tmp); cp_error_at ("overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype); SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
} }
break; break;
@ -2697,13 +2704,22 @@ free_mi_matrix ()
/* If we want debug info for a type TYPE, make sure all its base types /* If we want debug info for a type TYPE, make sure all its base types
are also marked as being potentially interesting. This avoids are also marked as being potentially interesting. This avoids
the problem of not writing any debug info for intermediate basetypes the problem of not writing any debug info for intermediate basetypes
that have abstract virtual functions. */ that have abstract virtual functions. Also mark member types. */
void void
note_debug_info_needed (type) note_debug_info_needed (type)
tree type; tree type;
{ {
tree field;
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp); dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
tree ttype;
if (TREE_CODE (field) == FIELD_DECL
&& IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field)))
&& dfs_debug_unmarkedp (TYPE_BINFO (ttype)))
note_debug_info_needed (ttype);
}
} }
/* Subroutines of push_class_decls (). */ /* Subroutines of push_class_decls (). */

View file

@ -177,7 +177,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
} }
else else
{ {
tree sig_tbl_type = c_build_type_variant (to_type, 1, 0); tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0);
sptr = build_lang_field_decl (FIELD_DECL, sptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_SPTR_NAME), get_identifier (SIGNATURE_SPTR_NAME),

View file

@ -202,8 +202,10 @@ shift_tokens (n)
* sizeof (struct token)); * sizeof (struct token));
/* This move does not rely on the system being able to handle /* This move does not rely on the system being able to handle
overlapping moves. */ overlapping moves. */
bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token)); bcopy ((char *) nth_token (0), tmp,
bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token)); old_token_count * sizeof (struct token));
bcopy (tmp, (char *) nth_token (n),
old_token_count * sizeof (struct token));
} }
first_token = 0; first_token = 0;
} }

View file

@ -35,66 +35,75 @@ int
lvalue_p (ref) lvalue_p (ref)
tree ref; tree ref;
{ {
register enum tree_code code = TREE_CODE (ref); if (! language_lvalue_valid (ref))
return 0;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
if (language_lvalue_valid (ref)) if (ref == current_class_decl && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{ {
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) /* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
return 1;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1; return 1;
break;
switch (code)
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST: case WITH_CLEANUP_EXPR:
return 1; return lvalue_p (TREE_OPERAND (ref, 0));
case VAR_DECL: case TARGET_EXPR:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref) return 1;
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
case TARGET_EXPR: case CALL_EXPR:
case WITH_CLEANUP_EXPR: if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
return 1; return 1;
break;
/* A currently unresolved scope ref. */ /* A currently unresolved scope ref. */
case SCOPE_REF: case SCOPE_REF:
my_friendly_abort (103); my_friendly_abort (103);
case OFFSET_REF: case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1; return 1;
return lvalue_p (TREE_OPERAND (ref, 0)) return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)); && lvalue_p (TREE_OPERAND (ref, 1));
break; break;
case COND_EXPR: case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1)) return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2))); && lvalue_p (TREE_OPERAND (ref, 2)));
case MODIFY_EXPR: case MODIFY_EXPR:
return 1; return 1;
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1)); return lvalue_p (TREE_OPERAND (ref, 1));
}
} }
return 0; return 0;
} }
@ -221,12 +230,15 @@ break_out_calls (exp)
return exp; return exp;
case 'd': /* A decl node */ case 'd': /* A decl node */
#if 0 /* This is bogus. jason 9/21/94 */
t1 = break_out_calls (DECL_INITIAL (exp)); t1 = break_out_calls (DECL_INITIAL (exp));
if (t1 != DECL_INITIAL (exp)) if (t1 != DECL_INITIAL (exp))
{ {
exp = copy_node (exp); exp = copy_node (exp);
DECL_INITIAL (exp) = t1; DECL_INITIAL (exp) = t1;
} }
#endif
return exp; return exp;
case 'b': /* A block node */ case 'b': /* A block node */
@ -379,6 +391,40 @@ build_cplus_array_type (elt_type, index_type)
return t; return t;
} }
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
tree
cp_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
constp, volatilep),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
REAL_MAIN_VARIANT might be in some function's obstack.) */
if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant))
{
type = copy_node (type);
TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0;
}
TYPE_MAIN_VARIANT (type) = real_main_variant;
pop_obstacks ();
}
return build_type_variant (type, constp, volatilep);
}
/* Add OFFSET to all base types of T. /* Add OFFSET to all base types of T.
OFFSET, which is a type offset, is number of bytes. OFFSET, which is a type offset, is number of bytes.
@ -1184,50 +1230,6 @@ virtual_member (elem, list)
return rval; return rval;
} }
/* Return the offset (as an INTEGER_CST) for ELEM in LIST.
INITIAL_OFFSET is the value to add to the offset that ELEM's
binfo entry in LIST provides.
Returns NULL if ELEM does not have an binfo value in LIST. */
tree
virtual_offset (elem, list, initial_offset)
tree elem;
tree list;
tree initial_offset;
{
tree vb, offset;
tree rval, nval;
for (vb = list; vb; vb = TREE_CHAIN (vb))
if (elem == BINFO_TYPE (vb))
return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb));
rval = 0;
for (vb = list; vb; vb = TREE_CHAIN (vb))
{
tree binfos = BINFO_BASETYPES (vb);
int i;
if (binfos == NULL_TREE)
continue;
for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
{
nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
if (nval)
{
if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
my_friendly_abort (105);
offset = BINFO_OFFSET (vb);
rval = nval;
}
}
}
if (rval == NULL_TREE)
return rval;
return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));
}
void void
debug_binfo (elem) debug_binfo (elem)
tree elem; tree elem;
@ -1661,6 +1663,31 @@ make_deep_copy (t)
TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
return t; return t;
case POINTER_TYPE:
return build_pointer_type (make_deep_copy (TREE_TYPE (t)));
case REFERENCE_TYPE:
return build_reference_type (make_deep_copy (TREE_TYPE (t)));
case FUNCTION_TYPE:
return build_function_type (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TYPE_ARG_TYPES (t)));
case ARRAY_TYPE:
return build_array_type (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TYPE_DOMAIN (t)));
case OFFSET_TYPE:
return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)),
make_deep_copy (TREE_TYPE (t)));
case METHOD_TYPE:
return build_method_type
(make_deep_copy (TYPE_METHOD_BASETYPE (t)),
build_function_type
(make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t)))));
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
(make_deep_copy (TYPE_PTRMEMFUNC_FN_TYPE (t)));
/* else fall through */
/* This list is incomplete, but should suffice for now. /* This list is incomplete, but should suffice for now.
It is very important that `sorry' does not call It is very important that `sorry' does not call
`report_error_function'. That could cause an infinite loop. */ `report_error_function'. That could cause an infinite loop. */
@ -1738,7 +1765,7 @@ tree
array_type_nelts_top (type) array_type_nelts_top (type)
tree type; tree type;
{ {
return fold (build (PLUS_EXPR, integer_type_node, return fold (build (PLUS_EXPR, sizetype,
array_type_nelts (type), array_type_nelts (type),
integer_one_node)); integer_one_node));
} }
@ -1756,7 +1783,7 @@ array_type_nelts_total (type)
while (TREE_CODE (type) == ARRAY_TYPE) while (TREE_CODE (type) == ARRAY_TYPE)
{ {
tree n = array_type_nelts_top (type); tree n = array_type_nelts_top (type);
sz = fold (build (MULT_EXPR, integer_type_node, sz, n)); sz = fold (build (MULT_EXPR, sizetype, sz, n));
type = TREE_TYPE (type); type = TREE_TYPE (type);
} }
return sz; return sz;

View file

@ -161,7 +161,7 @@ qualify_type (type, like)
int constflag = TYPE_READONLY (type) || TYPE_READONLY (like); int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like); int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
/* @@ Must do member pointers here. */ /* @@ Must do member pointers here. */
return c_build_type_variant (type, constflag, volflag); return cp_build_type_variant (type, constflag, volflag);
} }
/* Return the common type of two parameter lists. /* Return the common type of two parameter lists.
@ -372,7 +372,7 @@ common_type (t1, t2)
= TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2)); = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
int volatilep int volatilep
= TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2)); = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
target = c_build_type_variant (target, constp, volatilep); target = cp_build_type_variant (target, constp, volatilep);
if (code1 == POINTER_TYPE) if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target); t1 = build_pointer_type (target);
else else
@ -734,8 +734,6 @@ comp_target_types (ttl, ttr, nptrs)
ttr = TYPE_MAIN_VARIANT (ttr); ttr = TYPE_MAIN_VARIANT (ttr);
if (ttl == ttr) if (ttl == ttr)
return 1; return 1;
if (TREE_CODE (ttr) == TEMPLATE_TYPE_PARM)
return 1;
if (TREE_CODE (ttr) != TREE_CODE (ttl)) if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0; return 0;
@ -813,12 +811,14 @@ common_base_type (tt1, tt2)
if (UNIQUELY_DERIVED_FROM_P (tt2, tt1)) if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))
return tt2; return tt2;
#if 0
/* If they share a virtual baseclass, that's good enough. */ /* If they share a virtual baseclass, that's good enough. */
for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp)) for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp))
{ {
if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2))) if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2)))
return BINFO_TYPE (tmp); return BINFO_TYPE (tmp);
} }
#endif
/* Otherwise, try to find a unique baseclass of TT1 /* Otherwise, try to find a unique baseclass of TT1
that is shared by TT2, and follow that down. */ that is shared by TT2, and follow that down. */
@ -904,6 +904,8 @@ compparms (parms1, parms2, strict)
return t2 == void_list_node && TREE_PURPOSE (t1); return t2 == void_list_node && TREE_PURPOSE (t1);
return TREE_PURPOSE (t1) || TREE_PURPOSE (t2); return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
} }
#if 0
/* Default parms are not part of the type of a function. */
if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
{ {
int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
@ -912,6 +914,7 @@ compparms (parms1, parms2, strict)
if (cmp == 0) if (cmp == 0)
return 0; return 0;
} }
#endif
t1 = TREE_CHAIN (t1); t1 = TREE_CHAIN (t1);
t2 = TREE_CHAIN (t2); t2 = TREE_CHAIN (t2);
@ -959,8 +962,6 @@ comp_target_parms (parms1, parms2, strict)
p2 = TREE_VALUE (t2); p2 = TREE_VALUE (t2);
if (p1 == p2) if (p1 == p2)
continue; continue;
if (TREE_CODE (p2) == TEMPLATE_TYPE_PARM)
continue;
if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE) if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
|| (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE)) || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
@ -970,9 +971,6 @@ comp_target_parms (parms1, parms2, strict)
== TYPE_MAIN_VARIANT (TREE_TYPE (p2)))) == TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
continue; continue;
if (TREE_CODE (TREE_TYPE (p2)) == TEMPLATE_TYPE_PARM)
continue;
/* The following is wrong for contravariance, /* The following is wrong for contravariance,
but many programs depend on it. */ but many programs depend on it. */
if (TREE_TYPE (p1) == void_type_node) if (TREE_TYPE (p1) == void_type_node)
@ -1308,7 +1306,7 @@ default_conversion (exp)
if (INTEGRAL_CODE_P (code)) if (INTEGRAL_CODE_P (code))
{ {
tree t = type_promotes_to (type); tree t = type_promotes_to (type);
if (t != TYPE_MAIN_VARIANT (type)) if (t != type)
return convert (t, exp); return convert (t, exp);
} }
if (flag_traditional if (flag_traditional
@ -1380,7 +1378,7 @@ default_conversion (exp)
restype = TREE_TYPE (type); restype = TREE_TYPE (type);
if (TYPE_READONLY (type) || TYPE_VOLATILE (type) if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
|| constp || volatilep) || constp || volatilep)
restype = c_build_type_variant (restype, restype = cp_build_type_variant (restype,
TYPE_READONLY (type) || constp, TYPE_READONLY (type) || constp,
TYPE_VOLATILE (type) || volatilep); TYPE_VOLATILE (type) || volatilep);
ptrtype = build_pointer_type (restype); ptrtype = build_pointer_type (restype);
@ -1410,8 +1408,19 @@ tree
build_object_ref (datum, basetype, field) build_object_ref (datum, basetype, field)
tree datum, basetype, field; tree datum, basetype, field;
{ {
tree dtype;
if (datum == error_mark_node) if (datum == error_mark_node)
return error_mark_node; return error_mark_node;
dtype = TREE_TYPE (datum);
if (TREE_CODE (dtype) == REFERENCE_TYPE)
dtype = TREE_TYPE (dtype);
if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
{
cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
basetype, field, dtype);
return error_mark_node;
}
else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype))) else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype)))
{ {
warning ("signature name in scope resolution ignored"); warning ("signature name in scope resolution ignored");
@ -1524,8 +1533,7 @@ build_component_ref (datum, component, basetype_path, protect)
register tree field = NULL; register tree field = NULL;
register tree ref; register tree ref;
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */
unless we are not to support things not strictly ANSI. */
switch (TREE_CODE (datum)) switch (TREE_CODE (datum))
{ {
case COMPOUND_EXPR: case COMPOUND_EXPR:
@ -1697,7 +1705,8 @@ build_component_ref (datum, component, basetype_path, protect)
datum = build_indirect_ref (addr, NULL_PTR); datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 311); my_friendly_assert (datum != error_mark_node, 311);
} }
ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field); ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
if (TREE_READONLY (datum) || TREE_READONLY (field)) if (TREE_READONLY (datum) || TREE_READONLY (field))
TREE_READONLY (ref) = 1; TREE_READONLY (ref) = 1;
@ -2519,13 +2528,15 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
&& (type == 0 || TREE_CODE (type) != REFERENCE_TYPE)) && (type == 0 || TREE_CODE (type) != REFERENCE_TYPE))
val = TREE_OPERAND (val, 0); val = TREE_OPERAND (val, 0);
if ((type == 0 || TREE_CODE (type) != REFERENCE_TYPE) if (type == 0 || TREE_CODE (type) != REFERENCE_TYPE)
&& (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE {
if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)) || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
val = default_conversion (val); val = default_conversion (val);
val = require_complete_type (val); val = require_complete_type (val);
}
if (val == error_mark_node) if (val == error_mark_node)
continue; continue;
@ -2544,7 +2555,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
} }
else else
{ {
#ifdef PROMOTE_PROTOTYPES #if 0 && defined (PROMOTE_PROTOTYPES)
/* This breaks user-defined conversions. */
/* Rather than truncating and then reextending, /* Rather than truncating and then reextending,
convert directly to int, if that's the type we will want. */ convert directly to int, if that's the type we will want. */
if (! flag_traditional if (! flag_traditional
@ -2607,7 +2619,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* See if there are default arguments that can be used */ /* See if there are default arguments that can be used */
if (TREE_PURPOSE (typetail)) if (TREE_PURPOSE (typetail))
{ {
while (typetail != void_list_node) for (; typetail != void_list_node; ++i)
{ {
tree type = TREE_VALUE (typetail); tree type = TREE_VALUE (typetail);
tree val = TREE_PURPOSE (typetail); tree val = TREE_PURPOSE (typetail);
@ -3247,6 +3259,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case GE_EXPR: case GE_EXPR:
case LT_EXPR: case LT_EXPR:
case GT_EXPR: case GT_EXPR:
result_type = bool_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1; short_compare = 1;
@ -3295,7 +3308,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
warning ("comparison between pointer and integer"); warning ("comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0); op0 = convert (TREE_TYPE (op1), op0);
} }
result_type = bool_type_node; else
result_type = 0;
converted = 1; converted = 1;
break; break;
} }
@ -3717,7 +3731,7 @@ build_component_addr (arg, argtype, msg)
} }
else else
/* This conversion is harmless. */ /* This conversion is harmless. */
rval = convert (argtype, rval); rval = convert_force (argtype, rval);
if (! integer_zerop (DECL_FIELD_BITPOS (field))) if (! integer_zerop (DECL_FIELD_BITPOS (field)))
{ {
@ -4088,42 +4102,16 @@ build_unary_op (code, xarg, noconvert)
if (TREE_CODE (arg) == TREE_LIST) if (TREE_CODE (arg) == TREE_LIST)
{ {
/* Look at methods with only this name. */ if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL
if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL) && DECL_CHAIN (TREE_VALUE (arg)) == NULL_TREE)
{ /* Unique overloaded non-member function. */
tree targ = TREE_VALUE (arg); return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
/* If this function is unique, or it is a unique
constructor, we can take its address easily. */
if (DECL_CHAIN (targ) == NULL_TREE
|| (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (targ))
&& DECL_CHAIN (DECL_CHAIN (targ)) == NULL_TREE))
{
if (DECL_CHAIN (targ))
targ = DECL_CHAIN (targ);
if (DECL_CLASS_CONTEXT (targ))
targ = build (OFFSET_REF, TREE_TYPE (targ), C_C_D, targ);
val = unary_complex_lvalue (ADDR_EXPR, targ);
if (val)
return val;
}
/* This possible setting of TREE_CONSTANT is what makes it possible
with an initializer list to emit the entire thing in the data
section, rather than a run-time initialization. */
arg = build1 (ADDR_EXPR, unknown_type_node, arg);
if (staticp (targ))
TREE_CONSTANT (arg) = 1;
return arg;
}
if (TREE_CHAIN (arg) == NULL_TREE if (TREE_CHAIN (arg) == NULL_TREE
&& TREE_CODE (TREE_VALUE (arg)) == TREE_LIST && TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
&& DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE) && DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE)
{ /* Unique overloaded member function. */
/* Unique overloaded member function. */ return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)), 0); 0);
}
return build1 (ADDR_EXPR, unknown_type_node, arg); return build1 (ADDR_EXPR, unknown_type_node, arg);
} }
@ -4165,7 +4153,7 @@ build_unary_op (code, xarg, noconvert)
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{ {
if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)) if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
argtype = c_build_type_variant (argtype, argtype = cp_build_type_variant (argtype,
TREE_READONLY (arg), TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg)); TREE_THIS_VOLATILE (arg));
} }
@ -4573,7 +4561,7 @@ build_conditional_expr (ifexp, op1, op2)
else if (TREE_READONLY_DECL_P (op2)) else if (TREE_READONLY_DECL_P (op2))
op2 = decl_constant_value (op2); op2 = decl_constant_value (op2);
if (type1 != type2) if (type1 != type2)
type1 = c_build_type_variant type1 = cp_build_type_variant
(type1, (type1,
TREE_READONLY (op1) || TREE_READONLY (op2), TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
@ -4622,7 +4610,7 @@ build_conditional_expr (ifexp, op1, op2)
if (type1 == type2) if (type1 == type2)
result_type = type1; result_type = type1;
else else
result_type = c_build_type_variant result_type = cp_build_type_variant
(type1, (type1,
TREE_READONLY (op1) || TREE_READONLY (op2), TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
@ -4669,11 +4657,20 @@ build_conditional_expr (ifexp, op1, op2)
{ {
if (result_type == error_mark_node) if (result_type == error_mark_node)
{ {
message_2_types (error, "common base type of types `%s' and `%s' is ambiguous", cp_error ("common base type of types `%T' and `%T' is ambiguous",
TREE_TYPE (type1), TREE_TYPE (type2)); TREE_TYPE (type1), TREE_TYPE (type2));
result_type = ptr_type_node; result_type = ptr_type_node;
} }
else result_type = TYPE_POINTER_TO (result_type); else
{
if (pedantic
&& result_type != TREE_TYPE (type1)
&& result_type != TREE_TYPE (type2))
cp_pedwarn ("`%T' and `%T' converted to `%T *' in conditional expression",
type1, type2, result_type);
result_type = TYPE_POINTER_TO (result_type);
}
} }
else else
{ {
@ -4939,7 +4936,7 @@ build_c_cast (type, expr)
value = TREE_VALUE (value); value = TREE_VALUE (value);
if (TREE_CODE (type) == VOID_TYPE) if (TREE_CODE (type) == VOID_TYPE)
value = build1 (NOP_EXPR, type, value); value = build1 (CONVERT_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE else if (TREE_TYPE (value) == NULL_TREE
|| type_unknown_p (value)) || type_unknown_p (value))
{ {
@ -5002,6 +4999,9 @@ build_c_cast (type, expr)
warning ("cast to pointer from integer of different size"); warning ("cast to pointer from integer of different size");
#endif #endif
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
ovalue = value; ovalue = value;
value = convert_force (type, value); value = convert_force (type, value);
@ -5326,13 +5326,13 @@ build_modify_expr (lhs, modifycode, rhs)
tree olhstype = lhstype; tree olhstype = lhstype;
tree olhs = lhs; tree olhs = lhs;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
/* Avoid duplicate error messages from operands that had errors. */ /* Avoid duplicate error messages from operands that had errors. */
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node; return error_mark_node;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
/* Decide early if we are going to protect RHS from GC /* Decide early if we are going to protect RHS from GC
before assigning it to LHS. */ before assigning it to LHS. */
if (type_needs_gc_entry (TREE_TYPE (rhs)) if (type_needs_gc_entry (TREE_TYPE (rhs))
@ -5388,9 +5388,9 @@ build_modify_expr (lhs, modifycode, rhs)
so the code to compute it is only emitted once. */ so the code to compute it is only emitted once. */
tree cond tree cond
= build_conditional_expr (TREE_OPERAND (lhs, 0), = build_conditional_expr (TREE_OPERAND (lhs, 0),
build_modify_expr (TREE_OPERAND (lhs, 1), build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
modifycode, rhs), modifycode, rhs),
build_modify_expr (TREE_OPERAND (lhs, 2), build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
modifycode, rhs)); modifycode, rhs));
if (TREE_CODE (cond) == ERROR_MARK) if (TREE_CODE (cond) == ERROR_MARK)
return cond; return cond;
@ -5763,10 +5763,12 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (lhstype) == ARRAY_TYPE) if (TREE_CODE (lhstype) == ARRAY_TYPE)
{ {
int from_array;
/* Allow array assignment in compiler-generated code. */ /* Allow array assignment in compiler-generated code. */
if ((pedantic || flag_ansi) if ((pedantic || flag_ansi)
&& ! DECL_ARTIFICIAL (current_function_decl)) && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment between arrays"); pedwarn ("ANSI C++ forbids assignment of arrays");
/* Have to wrap this in RTL_EXPR for two cases: /* Have to wrap this in RTL_EXPR for two cases:
in base or member initialization and if we in base or member initialization and if we
@ -5782,8 +5784,10 @@ build_modify_expr (lhs, modifycode, rhs)
/* As a matter of principle, `start_sequence' should do this. */ /* As a matter of principle, `start_sequence' should do this. */
emit_note (0, -1); emit_note (0, -1);
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs, expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs,
1 + (modifycode != INIT_EXPR)); from_array);
do_pending_stack_adjust (); do_pending_stack_adjust ();
@ -6101,12 +6105,15 @@ build_ptrmemfunc (type, pfn, force)
return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
} }
if (TREE_CODE (pfn) == TREE_LIST) if (TREE_CODE (pfn) == TREE_LIST
|| (TREE_CODE (pfn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
{ {
pfn = instantiate_type (type, pfn, 1); pfn = instantiate_type (type, pfn, 1);
if (pfn == error_mark_node) if (pfn == error_mark_node)
return error_mark_node; return error_mark_node;
pfn = build_unary_op (ADDR_EXPR, pfn, 0); if (TREE_CODE (pfn) != ADDR_EXPR)
pfn = build_unary_op (ADDR_EXPR, pfn, 0);
} }
/* Allow pointer to member conversions here. */ /* Allow pointer to member conversions here. */
@ -6445,7 +6452,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
add_quals = 1; add_quals = 1;
left_const &= TYPE_READONLY (ttl); left_const &= TYPE_READONLY (ttl);
if (TREE_CODE (ttl) != POINTER_TYPE) if (TREE_CODE (ttl) != POINTER_TYPE
|| TREE_CODE (ttr) != POINTER_TYPE)
break; break;
} }
unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr); unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
@ -6561,10 +6569,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
} }
return null_pointer_node; return null_pointer_node;
} }
else if (codel == INTEGER_TYPE else if ((codel == INTEGER_TYPE || codel == BOOLEAN_TYPE)
&& (coder == POINTER_TYPE && (coder == POINTER_TYPE
|| (coder == RECORD_TYPE || (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype) && (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype))))) || IS_SIGNATURE_REFERENCE (rhstype)))))
{ {
if (fndecl) if (fndecl)
@ -6717,7 +6726,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))) && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
return build_signature_pointer_constructor (type, rhs); return build_signature_pointer_constructor (type, rhs);
if (IS_AGGR_TYPE (type) && TYPE_NEEDS_CONSTRUCTING (type)) if (IS_AGGR_TYPE (type)
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
{ {
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{ {
@ -6973,8 +6983,11 @@ c_expand_return (retval)
while (TREE_CODE (whats_returned) == NEW_EXPR while (TREE_CODE (whats_returned) == NEW_EXPR
|| TREE_CODE (whats_returned) == TARGET_EXPR || TREE_CODE (whats_returned) == TARGET_EXPR
|| TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR) || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
/* Get the target. */ {
whats_returned = TREE_OPERAND (whats_returned, 0); /* Get the target. */
whats_returned = TREE_OPERAND (whats_returned, 0);
warning ("returning reference to temporary");
}
} }
if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned)) if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
@ -7028,6 +7041,7 @@ c_expand_return (retval)
&& TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR) && TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
retval = TREE_OPERAND (retval, 0); retval = TREE_OPERAND (retval, 0);
expand_aggr_init (result, retval, 0); expand_aggr_init (result, retval, 0);
expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE; DECL_INITIAL (result) = NULL_TREE;
retval = 0; retval = 0;
} }
@ -7046,6 +7060,7 @@ c_expand_return (retval)
&& any_pending_cleanups (1)) && any_pending_cleanups (1))
{ {
retval = get_temp_regvar (valtype, retval); retval = get_temp_regvar (valtype, retval);
expand_cleanups_to (NULL_TREE);
use_temp = obey_regdecls; use_temp = obey_regdecls;
result = 0; result = 0;
} }
@ -7071,7 +7086,10 @@ c_expand_return (retval)
{ {
/* Everything's great--RETVAL is in RESULT. */ /* Everything's great--RETVAL is in RESULT. */
if (original_result_rtx) if (original_result_rtx)
store_expr (result, original_result_rtx, 0); {
store_expr (result, original_result_rtx, 0);
expand_cleanups_to (NULL_TREE);
}
else if (retval && retval != result) else if (retval && retval != result)
{ {
/* Clear this out so the later call to decl_function_context /* Clear this out so the later call to decl_function_context
@ -7081,6 +7099,9 @@ c_expand_return (retval)
/* Here is where we finally get RETVAL into RESULT. /* Here is where we finally get RETVAL into RESULT.
`expand_return' does the magic of protecting `expand_return' does the magic of protecting
RESULT from cleanups. */ RESULT from cleanups. */
retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval);
/* This part _must_ come second, because expand_return looks for
the INIT_EXPR as the toplevel node only. :-( */
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
TREE_SIDE_EFFECTS (retval) = 1; TREE_SIDE_EFFECTS (retval) = 1;
expand_return (retval); expand_return (retval);
@ -7190,7 +7211,8 @@ c_expand_start_case (exp)
exp = index; exp = index;
} }
expand_start_case (1, exp, type, "switch statement"); expand_start_case (1, build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp),
type, "switch statement");
return exp; return exp;
} }

View file

@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */ same situation (call exit). */
/* First used: 0 (reserved), Last used: 360. Free: */ /* First used: 0 (reserved), Last used: 360. Free: 261. */
static int abortcount = 0; static int abortcount = 0;
@ -599,6 +599,7 @@ store_init_value (decl, init)
)) ))
return value; return value;
#if 0 /* No, that's C. jason 9/19/94 */
else else
{ {
if (pedantic && TREE_CODE (value) == CONSTRUCTOR if (pedantic && TREE_CODE (value) == CONSTRUCTOR
@ -613,6 +614,7 @@ store_init_value (decl, init)
pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions"); pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");
} }
} }
#endif
DECL_INITIAL (decl) = value; DECL_INITIAL (decl) = value;
return NULL_TREE; return NULL_TREE;
} }
@ -631,7 +633,7 @@ digest_init (type, init, tail)
tree type, init, *tail; tree type, init, *tail;
{ {
enum tree_code code = TREE_CODE (type); enum tree_code code = TREE_CODE (type);
tree element = 0; tree element = NULL_TREE;
tree old_tail_contents; tree old_tail_contents;
/* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
tree node which has no TREE_TYPE. */ tree node which has no TREE_TYPE. */
@ -659,8 +661,9 @@ digest_init (type, init, tail)
if (init && TYPE_PTRMEMFUNC_P (type) if (init && TYPE_PTRMEMFUNC_P (type)
&& ((TREE_CODE (init) == ADDR_EXPR && ((TREE_CODE (init) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE && ((TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE) && TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
|| TREE_CODE (TREE_OPERAND (init, 0)) == TREE_LIST))
|| TREE_CODE (init) == TREE_LIST || TREE_CODE (init) == TREE_LIST
|| integer_zerop (init) || integer_zerop (init)
|| (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init))))) || (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
@ -903,7 +906,7 @@ process_init_constructor (type, init, elts)
{ {
error ("non-empty initializer for array of empty elements"); error ("non-empty initializer for array of empty elements");
/* Just ignore what we were supposed to use. */ /* Just ignore what we were supposed to use. */
tail1 = 0; tail1 = NULL_TREE;
} }
tail = tail1; tail = tail1;
} }
@ -1151,7 +1154,9 @@ build_scoped_ref (datum, types)
if (TREE_CODE (types) == SCOPE_REF) if (TREE_CODE (types) == SCOPE_REF)
{ {
/* We have some work to do. */ /* We have some work to do. */
struct type_chain { tree type; struct type_chain *next; } *chain = 0, *head = 0, scratch; struct type_chain
{ tree type; struct type_chain *next; }
*chain = NULL, *head = NULL, scratch;
ref = build_unary_op (ADDR_EXPR, datum, 0); ref = build_unary_op (ADDR_EXPR, datum, 0);
while (TREE_CODE (types) == SCOPE_REF) while (TREE_CODE (types) == SCOPE_REF)
{ {

File diff suppressed because it is too large Load diff

View file

@ -145,14 +145,14 @@ bc_sym_write (file)
{ {
fprintf (file, "\n\t.comm "); fprintf (file, "\n\t.comm ");
prsym (file, s->name); prsym (file, s->name);
fprintf (file, ", %d\n", s->val); fprintf (file, ", %lu\n", s->val);
} }
} }
else if (s->common) else if (s->common)
{ {
fprintf (file, "\n\t.lcomm "); fprintf (file, "\n\t.lcomm ");
prsym (file, s->name); prsym (file, s->name);
fprintf (file, ", %d\n", s->val); fprintf (file, ", %lu\n", s->val);
} }
} }
} }

View file

@ -253,6 +253,19 @@ decl_attributes (decl, attributes)
else else
warning_with_decl (decl, "`const' attribute ignored"); warning_with_decl (decl, "`const' attribute ignored");
} }
else if (TREE_VALUE (a) == get_identifier ("transparent_union"))
{
if (TREE_CODE (decl) == PARM_DECL
&& TREE_CODE (type) == UNION_TYPE
&& TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
DECL_TRANSPARENT_UNION (decl) = 1;
else if (TREE_CODE (decl) == TYPE_DECL
&& TREE_CODE (type) == UNION_TYPE
&& TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
TYPE_TRANSPARENT_UNION (type) = 1;
else
warning_with_decl (decl, "`transparent_union' attribute ignored");
}
else if (TREE_CODE (name) != TREE_LIST) else if (TREE_CODE (name) != TREE_LIST)
{ {
#ifdef VALID_MACHINE_ATTRIBUTE #ifdef VALID_MACHINE_ATTRIBUTE
@ -518,7 +531,7 @@ static format_char_info print_char_table[] = {
{ "s", 1, T_C, NULL, T_W, NULL, NULL, "-wp" }, { "s", 1, T_C, NULL, T_W, NULL, NULL, "-wp" },
{ "S", 1, T_W, NULL, NULL, NULL, NULL, "-wp" }, { "S", 1, T_W, NULL, NULL, NULL, NULL, "-wp" },
{ "p", 1, T_V, NULL, NULL, NULL, NULL, "-w" }, { "p", 1, T_V, NULL, NULL, NULL, NULL, "-w" },
{ "n", 1, T_I, T_S, T_L, NULL, NULL, "" }, { "n", 1, T_I, T_S, T_L, T_LL, NULL, "" },
{ NULL } { NULL }
}; };
@ -531,7 +544,7 @@ static format_char_info scan_char_table[] = {
{ "C", 1, T_W, NULL, NULL, NULL, NULL, "*" }, { "C", 1, T_W, NULL, NULL, NULL, NULL, "*" },
{ "S", 1, T_W, NULL, NULL, NULL, NULL, "*" }, { "S", 1, T_W, NULL, NULL, NULL, NULL, "*" },
{ "p", 2, T_V, NULL, NULL, NULL, NULL, "*" }, { "p", 2, T_V, NULL, NULL, NULL, NULL, "*" },
{ "n", 1, T_I, T_S, T_L, NULL, NULL, "" }, { "n", 1, T_I, T_S, T_L, T_LL, NULL, "" },
{ NULL } { NULL }
}; };
@ -1340,6 +1353,37 @@ type_for_mode (mode, unsignedp)
return 0; return 0;
} }
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
int
min_precision (value, unsignedp)
tree value;
int unsignedp;
{
int log;
/* If the value is negative, compute its negative minus 1. The latter
adjustment is because the absolute value of the largest negative value
is one larger than the largest positive value. This is equivalent to
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
value = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (value), value));
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
if (integer_zerop (value))
log = 0;
else if (TREE_INT_CST_HIGH (value) != 0)
log = HOST_BITS_PER_WIDE_INT + floor_log2 (TREE_INT_CST_HIGH (value));
else
log = floor_log2 (TREE_INT_CST_LOW (value));
return log + 1 + ! unsignedp;
}
/* Print an error message for invalid operands to arith operation CODE. /* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */ NOP_EXPR is used as a special case (see truthvalue_conversion). */
@ -1451,9 +1495,11 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
real2 = TREE_CODE (TREE_TYPE (primop1)) == REAL_TYPE; real2 = TREE_CODE (TREE_TYPE (primop1)) == REAL_TYPE;
/* If first arg is constant, swap the args (changing operation /* If first arg is constant, swap the args (changing operation
so value is preserved), for canonicalization. */ so value is preserved), for canonicalization. Don't do this if
the second arg is 0. */
if (TREE_CONSTANT (primop0)) if (TREE_CONSTANT (primop0)
&& ! integer_zerop (primop1) && ! real_zerop (primop1))
{ {
register tree tem = primop0; register tree tem = primop0;
register int temi = unsignedp0; register int temi = unsignedp0;
@ -1692,13 +1738,23 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
switch (code) switch (code)
{ {
case GE_EXPR: case GE_EXPR:
if (extra_warnings) /* All unsigned values are >= 0, so we warn if extra warnings
are requested. However, if OP0 is a constant that is
>= 0, the signedness of the comparison isn't an issue,
so suppress the warning. */
if (extra_warnings
&& ! (TREE_CODE (primop0) == INTEGER_CST
&& ! TREE_OVERFLOW (convert (signed_type (type),
primop0))))
warning ("unsigned value >= 0 is always 1"); warning ("unsigned value >= 0 is always 1");
value = integer_one_node; value = integer_one_node;
break; break;
case LT_EXPR: case LT_EXPR:
if (extra_warnings) if (extra_warnings
&& ! (TREE_CODE (primop0) == INTEGER_CST
&& ! TREE_OVERFLOW (convert (signed_type (type),
primop0))))
warning ("unsigned value < 0 is always 0"); warning ("unsigned value < 0 is always 0");
value = integer_zero_node; value = integer_zero_node;
} }

View file

@ -443,7 +443,8 @@ emit_call_1 (funexp, funtype, stack_size, struct_value_size, next_arg_reg,
{ {
if (!already_popped) if (!already_popped)
CALL_INSN_FUNCTION_USAGE (call_insn) = CALL_INSN_FUNCTION_USAGE (call_insn) =
gen_rtx (EXPR_LIST, CLOBBER, stack_pointer_rtx, gen_rtx (EXPR_LIST, VOIDmode,
gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx),
CALL_INSN_FUNCTION_USAGE (call_insn)); CALL_INSN_FUNCTION_USAGE (call_insn));
stack_size -= RETURN_POPS_ARGS (funtype, stack_size); stack_size -= RETURN_POPS_ARGS (funtype, stack_size);
stack_size_rtx = GEN_INT (stack_size); stack_size_rtx = GEN_INT (stack_size);
@ -667,9 +668,6 @@ expand_call (exp, target, ignore)
{ {
struct_value_size = int_size_in_bytes (TREE_TYPE (exp)); struct_value_size = int_size_in_bytes (TREE_TYPE (exp));
if (struct_value_size < 0)
abort ();
if (target && GET_CODE (target) == MEM) if (target && GET_CODE (target) == MEM)
structure_value_addr = XEXP (target, 0); structure_value_addr = XEXP (target, 0);
else else
@ -680,6 +678,9 @@ expand_call (exp, target, ignore)
specified. If we were to allocate space on the stack here, specified. If we were to allocate space on the stack here,
we would have no way of knowing when to free it. */ we would have no way of knowing when to free it. */
if (struct_value_size < 0)
abort ();
structure_value_addr structure_value_addr
= XEXP (assign_stack_temp (BLKmode, struct_value_size, 1), 0); = XEXP (assign_stack_temp (BLKmode, struct_value_size, 1), 0);
target = 0; target = 0;
@ -901,15 +902,18 @@ expand_call (exp, target, ignore)
as if it were an extra parameter. */ as if it were an extra parameter. */
if (structure_value_addr && struct_value_rtx == 0) if (structure_value_addr && struct_value_rtx == 0)
{ {
/* If structure_value_addr is a REG other than
virtual_outgoing_args_rtx, we can use always use it. If it
is not a REG, we must always copy it into a register.
If it is virtual_outgoing_args_rtx, we must copy it to another
register in some cases. */
rtx temp = (GET_CODE (structure_value_addr) != REG
#ifdef ACCUMULATE_OUTGOING_ARGS #ifdef ACCUMULATE_OUTGOING_ARGS
/* If the stack will be adjusted, make sure the structure address || (stack_arg_under_construction
does not refer to virtual_outgoing_args_rtx. */ && structure_value_addr == virtual_outgoing_args_rtx)
rtx temp = (stack_arg_under_construction
? copy_addr_to_reg (structure_value_addr)
: force_reg (Pmode, structure_value_addr));
#else
rtx temp = force_reg (Pmode, structure_value_addr);
#endif #endif
? copy_addr_to_reg (structure_value_addr)
: structure_value_addr);
actparms actparms
= tree_cons (error_mark_node, = tree_cons (error_mark_node,
@ -979,6 +983,12 @@ expand_call (exp, target, ignore)
if (type == error_mark_node || TYPE_SIZE (type) == 0) if (type == error_mark_node || TYPE_SIZE (type) == 0)
args[i].tree_value = integer_zero_node, type = integer_type_node; args[i].tree_value = integer_zero_node, type = integer_type_node;
/* If TYPE is a transparent union, pass things the way we would
pass the first field of the union. We have already verified that
the modes are the same. */
if (TYPE_TRANSPARENT_UNION (type))
type = TREE_TYPE (TYPE_FIELDS (type));
/* Decide where to pass this arg. /* Decide where to pass this arg.
args[i].reg is nonzero if all or part is passed in registers. args[i].reg is nonzero if all or part is passed in registers.
@ -1343,98 +1353,103 @@ expand_call (exp, target, ignore)
} }
argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0); argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0);
} }
else if (must_preallocate) else
{ {
/* Note that we must go through the motions of allocating an argument /* Note that we must go through the motions of allocating an argument
block even if the size is zero because we may be storing args block even if the size is zero because we may be storing args
in the area reserved for register arguments, which may be part of in the area reserved for register arguments, which may be part of
the stack frame. */ the stack frame. */
int needed = args_size.constant; int needed = args_size.constant;
#ifdef ACCUMULATE_OUTGOING_ARGS
/* Store the maximum argument space used. It will be pushed by the /* Store the maximum argument space used. It will be pushed by the
prologue. prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow checking). */
Since the stack pointer will never be pushed, it is possible for
the evaluation of a parm to clobber something we have already
written to the stack. Since most function calls on RISC machines
do not use the stack, this is uncommon, but must work correctly.
Therefore, we save any area of the stack that was already written
and that we are using. Here we set up to do this by making a new
stack usage map from the old one. The actual save will be done
by store_one_arg.
Another approach might be to try to reorder the argument
evaluations to avoid this conflicting stack usage. */
if (needed > current_function_outgoing_args_size) if (needed > current_function_outgoing_args_size)
current_function_outgoing_args_size = needed; current_function_outgoing_args_size = needed;
if (must_preallocate)
{
#ifdef ACCUMULATE_OUTGOING_ARGS
/* Since the stack pointer will never be pushed, it is possible for
the evaluation of a parm to clobber something we have already
written to the stack. Since most function calls on RISC machines
do not use the stack, this is uncommon, but must work correctly.
Therefore, we save any area of the stack that was already written
and that we are using. Here we set up to do this by making a new
stack usage map from the old one. The actual save will be done
by store_one_arg.
Another approach might be to try to reorder the argument
evaluations to avoid this conflicting stack usage. */
#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
/* Since we will be writing into the entire argument area, the /* Since we will be writing into the entire argument area, the
map must be allocated for its entire size, not just the part that map must be allocated for its entire size, not just the part that
is the responsibility of the caller. */ is the responsibility of the caller. */
needed += reg_parm_stack_space; needed += reg_parm_stack_space;
#endif #endif
#ifdef ARGS_GROW_DOWNWARD #ifdef ARGS_GROW_DOWNWARD
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
needed + 1); needed + 1);
#else #else
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, needed); highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
needed);
#endif #endif
stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use);
if (initial_highest_arg_in_use) if (initial_highest_arg_in_use)
bcopy (initial_stack_usage_map, stack_usage_map, bcopy (initial_stack_usage_map, stack_usage_map,
initial_highest_arg_in_use); initial_highest_arg_in_use);
if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
bzero (&stack_usage_map[initial_highest_arg_in_use], bzero (&stack_usage_map[initial_highest_arg_in_use],
highest_outgoing_arg_in_use - initial_highest_arg_in_use); highest_outgoing_arg_in_use - initial_highest_arg_in_use);
needed = 0; needed = 0;
/* The address of the outgoing argument list must not be copied to a /* The address of the outgoing argument list must not be copied to a
register here, because argblock would be left pointing to the register here, because argblock would be left pointing to the
wrong place after the call to allocate_dynamic_stack_space below. */ wrong place after the call to allocate_dynamic_stack_space below.
*/
argblock = virtual_outgoing_args_rtx; argblock = virtual_outgoing_args_rtx;
#else /* not ACCUMULATE_OUTGOING_ARGS */ #else /* not ACCUMULATE_OUTGOING_ARGS */
if (inhibit_defer_pop == 0) if (inhibit_defer_pop == 0)
{
/* Try to reuse some or all of the pending_stack_adjust
to get this space. Maybe we can avoid any pushing. */
if (needed > pending_stack_adjust)
{ {
needed -= pending_stack_adjust; /* Try to reuse some or all of the pending_stack_adjust
pending_stack_adjust = 0; to get this space. Maybe we can avoid any pushing. */
if (needed > pending_stack_adjust)
{
needed -= pending_stack_adjust;
pending_stack_adjust = 0;
}
else
{
pending_stack_adjust -= needed;
needed = 0;
}
} }
/* Special case this because overhead of `push_block' in this
case is non-trivial. */
if (needed == 0)
argblock = virtual_outgoing_args_rtx;
else else
{ argblock = push_block (GEN_INT (needed), 0, 0);
pending_stack_adjust -= needed;
needed = 0;
}
}
/* Special case this because overhead of `push_block' in this
case is non-trivial. */
if (needed == 0)
argblock = virtual_outgoing_args_rtx;
else
argblock = push_block (GEN_INT (needed), 0, 0);
/* We only really need to call `copy_to_reg' in the case where push /* We only really need to call `copy_to_reg' in the case where push
insns are going to be used to pass ARGBLOCK to a function insns are going to be used to pass ARGBLOCK to a function
call in ARGS. In that case, the stack pointer changes value call in ARGS. In that case, the stack pointer changes value
from the allocation point to the call point, and hence from the allocation point to the call point, and hence
the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well. the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well.
But might as well always do it. */ But might as well always do it. */
argblock = copy_to_reg (argblock); argblock = copy_to_reg (argblock);
#endif /* not ACCUMULATE_OUTGOING_ARGS */ #endif /* not ACCUMULATE_OUTGOING_ARGS */
}
} }
#ifdef ACCUMULATE_OUTGOING_ARGS #ifdef ACCUMULATE_OUTGOING_ARGS
/* The save/restore code in store_one_arg handles all cases except one: /* The save/restore code in store_one_arg handles all cases except one:
a constructor call (including a C function returning a BLKmode struct) a constructor call (including a C function returning a BLKmode struct)
@ -2193,7 +2208,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
be viewed as just an efficiency improvement. */ be viewed as just an efficiency improvement. */
rtx slot = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0); rtx slot = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
emit_move_insn (slot, val); emit_move_insn (slot, val);
val = XEXP (slot, 0); val = force_operand (XEXP (slot, 0), NULL_RTX);
mode = Pmode; mode = Pmode;
} }
#endif #endif
@ -2266,9 +2281,10 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
#endif #endif
#endif #endif
#ifdef ACCUMULATE_OUTGOING_ARGS
if (args_size.constant > current_function_outgoing_args_size) if (args_size.constant > current_function_outgoing_args_size)
current_function_outgoing_args_size = args_size.constant; current_function_outgoing_args_size = args_size.constant;
#ifdef ACCUMULATE_OUTGOING_ARGS
args_size.constant = 0; args_size.constant = 0;
#endif #endif
@ -2613,9 +2629,10 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
#endif #endif
#endif #endif
#ifdef ACCUMULATE_OUTGOING_ARGS
if (args_size.constant > current_function_outgoing_args_size) if (args_size.constant > current_function_outgoing_args_size)
current_function_outgoing_args_size = args_size.constant; current_function_outgoing_args_size = args_size.constant;
#ifdef ACCUMULATE_OUTGOING_ARGS
args_size.constant = 0; args_size.constant = 0;
#endif #endif

View file

@ -170,11 +170,6 @@ static int last_call_cuid;
static rtx subst_insn; static rtx subst_insn;
/* If nonzero, this is the insn that should be presumed to be
immediately in front of `subst_insn'. */
static rtx subst_prev_insn;
/* This is the lowest CUID that `subst' is currently dealing with. /* This is the lowest CUID that `subst' is currently dealing with.
get_last_value will not return a value if the register was set at or get_last_value will not return a value if the register was set at or
after this CUID. If not for this mechanism, we could get confused if after this CUID. If not for this mechanism, we could get confused if
@ -880,7 +875,11 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
/* Can't merge a function call. */ /* Can't merge a function call. */
|| GET_CODE (src) == CALL || GET_CODE (src) == CALL
/* Don't eliminate a function call argument. */ /* Don't eliminate a function call argument. */
|| (GET_CODE (i3) == CALL_INSN && find_reg_fusage (i3, USE, dest)) || (GET_CODE (i3) == CALL_INSN
&& (find_reg_fusage (i3, USE, dest)
|| (GET_CODE (dest) == REG
&& REGNO (dest) < FIRST_PSEUDO_REGISTER
&& global_regs[REGNO (dest)])))
/* Don't substitute into an incremented register. */ /* Don't substitute into an incremented register. */
|| FIND_REG_INC_NOTE (i3, dest) || FIND_REG_INC_NOTE (i3, dest)
|| (succ && FIND_REG_INC_NOTE (succ, dest)) || (succ && FIND_REG_INC_NOTE (succ, dest))
@ -1203,6 +1202,8 @@ try_combine (i3, i2, i1)
rtx new_i3_notes, new_i2_notes; rtx new_i3_notes, new_i2_notes;
/* Notes that we substituted I3 into I2 instead of the normal case. */ /* Notes that we substituted I3 into I2 instead of the normal case. */
int i3_subst_into_i2 = 0; int i3_subst_into_i2 = 0;
/* Notes that I1, I2 or I3 is a MULT operation. */
int have_mult = 0;
int maxreg; int maxreg;
rtx temp; rtx temp;
@ -1238,7 +1239,6 @@ try_combine (i3, i2, i1)
if (i1 && INSN_CUID (i1) > INSN_CUID (i2)) if (i1 && INSN_CUID (i1) > INSN_CUID (i2))
temp = i1, i1 = i2, i2 = temp; temp = i1, i1 = i2, i2 = temp;
subst_prev_insn = 0;
added_links_insn = 0; added_links_insn = 0;
/* First check for one important special-case that the code below will /* First check for one important special-case that the code below will
@ -1354,9 +1354,8 @@ try_combine (i3, i2, i1)
never appear in the insn stream so giving it the same INSN_UID never appear in the insn stream so giving it the same INSN_UID
as I2 will not cause a problem. */ as I2 will not cause a problem. */
subst_prev_insn = i1 i1 = gen_rtx (INSN, VOIDmode, INSN_UID (i2), 0, i2,
= gen_rtx (INSN, VOIDmode, INSN_UID (i2), 0, i2, XVECEXP (PATTERN (i2), 0, 1), -1, 0, 0);
XVECEXP (PATTERN (i2), 0, 1), -1, 0, 0);
SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0)); SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
SUBST (XEXP (SET_SRC (PATTERN (i2)), 0), SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
@ -1392,6 +1391,15 @@ try_combine (i3, i2, i1)
return 0; return 0;
} }
/* See if any of the insns is a MULT operation. Unless one is, we will
reject a combination that is, since it must be slower. Be conservative
here. */
if (GET_CODE (i2src) == MULT
|| (i1 != 0 && GET_CODE (i1src) == MULT)
|| (GET_CODE (PATTERN (i3)) == SET
&& GET_CODE (SET_SRC (PATTERN (i3))) == MULT))
have_mult = 1;
/* If I3 has an inc, then give up if I1 or I2 uses the reg that is inc'd. /* If I3 has an inc, then give up if I1 or I2 uses the reg that is inc'd.
We used to do this EXCEPT in one case: I3 has a post-inc in an We used to do this EXCEPT in one case: I3 has a post-inc in an
output operand. However, that exception can give rise to insns like output operand. However, that exception can give rise to insns like
@ -1601,7 +1609,11 @@ try_combine (i3, i2, i1)
really no reason to). */ really no reason to). */
|| max_reg_num () != maxreg || max_reg_num () != maxreg
/* Fail if we couldn't do something and have a CLOBBER. */ /* Fail if we couldn't do something and have a CLOBBER. */
|| GET_CODE (newpat) == CLOBBER) || GET_CODE (newpat) == CLOBBER
/* Fail if this new pattern is a MULT and we didn't have one before
at the outer level. */
|| (GET_CODE (newpat) == SET && GET_CODE (SET_SRC (newpat)) == MULT
&& ! have_mult))
{ {
undo_all (); undo_all ();
return 0; return 0;
@ -1804,13 +1816,14 @@ try_combine (i3, i2, i1)
&& ! reg_referenced_p (i2dest, newpat)) && ! reg_referenced_p (i2dest, newpat))
{ {
rtx newdest = i2dest; rtx newdest = i2dest;
enum rtx_code split_code = GET_CODE (*split);
enum machine_mode split_mode = GET_MODE (*split);
/* Get NEWDEST as a register in the proper mode. We have already /* Get NEWDEST as a register in the proper mode. We have already
validated that we can do this. */ validated that we can do this. */
if (GET_MODE (i2dest) != GET_MODE (*split) if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode)
&& GET_MODE (*split) != VOIDmode)
{ {
newdest = gen_rtx (REG, GET_MODE (*split), REGNO (i2dest)); newdest = gen_rtx (REG, split_mode, REGNO (i2dest));
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER) if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[REGNO (i2dest)], newdest); SUBST (regno_reg_rtx[REGNO (i2dest)], newdest);
@ -1819,25 +1832,27 @@ try_combine (i3, i2, i1)
/* If *SPLIT is a (mult FOO (const_int pow2)), convert it to /* If *SPLIT is a (mult FOO (const_int pow2)), convert it to
an ASHIFT. This can occur if it was inside a PLUS and hence an ASHIFT. This can occur if it was inside a PLUS and hence
appeared to be a memory address. This is a kludge. */ appeared to be a memory address. This is a kludge. */
if (GET_CODE (*split) == MULT if (split_code == MULT
&& GET_CODE (XEXP (*split, 1)) == CONST_INT && GET_CODE (XEXP (*split, 1)) == CONST_INT
&& (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0) && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0)
SUBST (*split, gen_rtx_combine (ASHIFT, GET_MODE (*split), SUBST (*split, gen_rtx_combine (ASHIFT, split_mode,
XEXP (*split, 0), GEN_INT (i))); XEXP (*split, 0), GEN_INT (i)));
#ifdef INSN_SCHEDULING #ifdef INSN_SCHEDULING
/* If *SPLIT is a paradoxical SUBREG, when we split it, it should /* If *SPLIT is a paradoxical SUBREG, when we split it, it should
be written as a ZERO_EXTEND. */ be written as a ZERO_EXTEND. */
if (GET_CODE (*split) == SUBREG if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
&& GET_CODE (SUBREG_REG (*split)) == MEM) SUBST (*split, gen_rtx_combine (ZERO_EXTEND, split_mode,
SUBST (*split, gen_rtx_combine (ZERO_EXTEND, GET_MODE (*split),
XEXP (*split, 0))); XEXP (*split, 0)));
#endif #endif
newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split); newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
SUBST (*split, newdest); SUBST (*split, newdest);
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
if (i2_code_number >= 0)
/* If the split point was a MULT and we didn't have one before,
don't use one now. */
if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
} }
} }
@ -3261,10 +3276,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
&& (temp = simplify_unary_operation (NOT, mode, && (temp = simplify_unary_operation (NOT, mode,
XEXP (XEXP (x, 0), 1), XEXP (XEXP (x, 0), 1),
mode)) != 0) mode)) != 0)
{ return gen_binary (XOR, mode, XEXP (XEXP (x, 0), 0), temp);
SUBST (XEXP (XEXP (x, 0), 1), temp);
return XEXP (x, 0);
}
/* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for operands /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for operands
other than 1, but that is not valid. We could do a similar other than 1, but that is not valid. We could do a similar
@ -3436,6 +3448,13 @@ simplify_rtx (x, op0_mode, last, in_dest)
&& GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode) && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode, return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode,
XEXP (XEXP (XEXP (x, 0), 0), 0)); XEXP (XEXP (XEXP (x, 0), 0), 0));
/* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0))
is (float_truncate:SF x). */
if (GET_CODE (XEXP (x, 0)) == SUBREG
&& subreg_lowpart_p (XEXP (x, 0))
&& GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
return SUBREG_REG (XEXP (x, 0));
break; break;
#ifdef HAVE_cc0 #ifdef HAVE_cc0
@ -4354,6 +4373,7 @@ simplify_set (x)
&& GET_MODE_CLASS (GET_MODE (src)) == MODE_INT && GET_MODE_CLASS (GET_MODE (src)) == MODE_INT
&& (GET_CODE (XEXP (src, 0)) == EQ || GET_CODE (XEXP (src, 0)) == NE) && (GET_CODE (XEXP (src, 0)) == EQ || GET_CODE (XEXP (src, 0)) == NE)
&& XEXP (XEXP (src, 0), 1) == const0_rtx && XEXP (XEXP (src, 0), 1) == const0_rtx
&& GET_MODE (src) == GET_MODE (XEXP (XEXP (src, 0), 0))
&& (num_sign_bit_copies (XEXP (XEXP (src, 0), 0), && (num_sign_bit_copies (XEXP (XEXP (src, 0), 0),
GET_MODE (XEXP (XEXP (src, 0), 0))) GET_MODE (XEXP (XEXP (src, 0), 0)))
== GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (src, 0), 0)))) == GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (src, 0), 0))))
@ -6874,8 +6894,10 @@ nonzero_bits (x, mode)
int width1 = floor_log2 (nz1) + 1; int width1 = floor_log2 (nz1) + 1;
int low0 = floor_log2 (nz0 & -nz0); int low0 = floor_log2 (nz0 & -nz0);
int low1 = floor_log2 (nz1 & -nz1); int low1 = floor_log2 (nz1 & -nz1);
int op0_maybe_minusp = (nz0 & ((HOST_WIDE_INT) 1 << (mode_width - 1))); HOST_WIDE_INT op0_maybe_minusp
int op1_maybe_minusp = (nz1 & ((HOST_WIDE_INT) 1 << (mode_width - 1))); = (nz0 & ((HOST_WIDE_INT) 1 << (mode_width - 1)));
HOST_WIDE_INT op1_maybe_minusp
= (nz1 & ((HOST_WIDE_INT) 1 << (mode_width - 1)));
int result_width = mode_width; int result_width = mode_width;
int result_low = 0; int result_low = 0;
@ -8618,6 +8640,7 @@ simplify_comparison (code, pop0, pop1)
{ {
op0 = gen_lowpart_for_combine (tmode, inner_op0); op0 = gen_lowpart_for_combine (tmode, inner_op0);
op1 = gen_lowpart_for_combine (tmode, inner_op1); op1 = gen_lowpart_for_combine (tmode, inner_op1);
code = unsigned_condition (code);
changed = 1; changed = 1;
break; break;
} }
@ -8819,6 +8842,7 @@ simplify_comparison (code, pop0, pop1)
{ {
const_op = 0, op1 = const0_rtx; const_op = 0, op1 = const0_rtx;
code = LT; code = LT;
break;
} }
else else
break; break;
@ -9811,15 +9835,10 @@ get_last_value (x)
{ {
rtx insn, set; rtx insn, set;
/* If there is an insn that is supposed to be immediately for (insn = prev_nonnote_insn (subst_insn);
in front of subst_insn, use it. */ insn && INSN_CUID (insn) >= subst_low_cuid;
if (subst_prev_insn != 0) insn = prev_nonnote_insn (insn))
insn = subst_prev_insn; ;
else
for (insn = prev_nonnote_insn (subst_insn);
insn && INSN_CUID (insn) >= subst_low_cuid;
insn = prev_nonnote_insn (insn))
;
if (insn if (insn
&& (set = single_set (insn)) != 0 && (set = single_set (insn)) != 0
@ -10332,10 +10351,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
switch (REG_NOTE_KIND (note)) switch (REG_NOTE_KIND (note))
{ {
case REG_UNUSED: case REG_UNUSED:
/* If this note is from any insn other than i3, then we have no /* Any clobbers for i3 may still exist, and so we must process
use for it, and must ignore it.
Any clobbers for i3 may still exist, and so we must process
REG_UNUSED notes from that insn. REG_UNUSED notes from that insn.
Any clobbers from i2 or i1 can only exist if they were added by Any clobbers from i2 or i1 can only exist if they were added by
@ -10345,14 +10361,18 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
if it is for the same register as the original i3 dest. if it is for the same register as the original i3 dest.
In that case, we will notice that the register is set in i3, In that case, we will notice that the register is set in i3,
and then add a REG_UNUSED note for the destination of i3, which and then add a REG_UNUSED note for the destination of i3, which
is wrong. */ is wrong. However, it is possible to have REG_UNUSED notes from
if (from_insn != i3) i2 or i1 for register which were both used and clobbered, so
break; we keep notes from i2 or i1 if they will turn into REG_DEAD
notes. */
/* If this register is set or clobbered in I3, put the note there /* If this register is set or clobbered in I3, put the note there
unless there is one already. */ unless there is one already. */
else if (reg_set_p (XEXP (note, 0), PATTERN (i3))) if (reg_set_p (XEXP (note, 0), PATTERN (i3)))
{ {
if (from_insn != i3)
break;
if (! (GET_CODE (XEXP (note, 0)) == REG if (! (GET_CODE (XEXP (note, 0)) == REG
? find_regno_note (i3, REG_UNUSED, REGNO (XEXP (note, 0))) ? find_regno_note (i3, REG_UNUSED, REGNO (XEXP (note, 0)))
: find_reg_note (i3, REG_UNUSED, XEXP (note, 0)))) : find_reg_note (i3, REG_UNUSED, XEXP (note, 0))))
@ -10633,7 +10653,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
{ {
rtx piece = gen_rtx (REG, reg_raw_mode[i], i); rtx piece = gen_rtx (REG, reg_raw_mode[i], i);
if (reg_referenced_p (piece, PATTERN (place)) if ((reg_referenced_p (piece, PATTERN (place))
|| (GET_CODE (place) == CALL_INSN
&& find_reg_fusage (place, USE, piece)))
&& ! dead_or_set_p (place, piece) && ! dead_or_set_p (place, piece)
&& ! reg_bitfield_target_p (piece, && ! reg_bitfield_target_p (piece,
PATTERN (place))) PATTERN (place)))

View file

@ -618,7 +618,7 @@ static struct table_elt *insert PROTO((rtx, struct table_elt *, unsigned,
enum machine_mode)); enum machine_mode));
static void merge_equiv_classes PROTO((struct table_elt *, static void merge_equiv_classes PROTO((struct table_elt *,
struct table_elt *)); struct table_elt *));
static void invalidate PROTO((rtx)); static void invalidate PROTO((rtx, enum machine_mode));
static void remove_invalid_refs PROTO((int)); static void remove_invalid_refs PROTO((int));
static void rehash_using_reg PROTO((rtx)); static void rehash_using_reg PROTO((rtx));
static void invalidate_memory PROTO((struct write_data *)); static void invalidate_memory PROTO((struct write_data *));
@ -1466,7 +1466,10 @@ merge_equiv_classes (class1, class2)
remove_from_table (elt, hash); remove_from_table (elt, hash);
if (insert_regs (exp, class1, 0)) if (insert_regs (exp, class1, 0))
hash = HASH (exp, mode); {
rehash_using_reg (exp);
hash = HASH (exp, mode);
}
new = insert (exp, class1, hash, mode); new = insert (exp, class1, hash, mode);
new->in_memory = hash_arg_in_memory; new->in_memory = hash_arg_in_memory;
new->in_struct = hash_arg_in_struct; new->in_struct = hash_arg_in_struct;
@ -1480,14 +1483,18 @@ merge_equiv_classes (class1, class2)
(because, when a memory reference with a varying address is stored in, (because, when a memory reference with a varying address is stored in,
all memory references are removed by invalidate_memory all memory references are removed by invalidate_memory
so specific invalidation is superfluous). so specific invalidation is superfluous).
FULL_MODE, if not VOIDmode, indicates that this much should be invalidated
instead of just the amount indicated by the mode of X. This is only used
for bitfield stores into memory.
A nonvarying address may be just a register or just A nonvarying address may be just a register or just
a symbol reference, or it may be either of those plus a symbol reference, or it may be either of those plus
a numeric offset. */ a numeric offset. */
static void static void
invalidate (x) invalidate (x, full_mode)
rtx x; rtx x;
enum machine_mode full_mode;
{ {
register int i; register int i;
register struct table_elt *p; register struct table_elt *p;
@ -1562,7 +1569,7 @@ invalidate (x)
{ {
if (GET_CODE (SUBREG_REG (x)) != REG) if (GET_CODE (SUBREG_REG (x)) != REG)
abort (); abort ();
invalidate (SUBREG_REG (x)); invalidate (SUBREG_REG (x), VOIDmode);
return; return;
} }
@ -1573,7 +1580,10 @@ invalidate (x)
if (GET_CODE (x) != MEM) if (GET_CODE (x) != MEM)
abort (); abort ();
set_nonvarying_address_components (XEXP (x, 0), GET_MODE_SIZE (GET_MODE (x)), if (full_mode == VOIDmode)
full_mode = GET_MODE (x);
set_nonvarying_address_components (XEXP (x, 0), GET_MODE_SIZE (full_mode),
&base, &start, &end); &base, &start, &end);
for (i = 0; i < NBUCKETS; i++) for (i = 0; i < NBUCKETS; i++)
@ -1711,7 +1721,7 @@ invalidate_for_call ()
if (reg_tick[regno] >= 0) if (reg_tick[regno] >= 0)
reg_tick[regno]++; reg_tick[regno]++;
in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, regno); in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
} }
/* In the case where we have no call-clobbered hard registers in the /* In the case where we have no call-clobbered hard registers in the
@ -1948,17 +1958,6 @@ canon_hash (x, mode)
if (fmt[i] == 'e') if (fmt[i] == 'e')
{ {
rtx tem = XEXP (x, i); rtx tem = XEXP (x, i);
rtx tem1;
/* If the operand is a REG that is equivalent to a constant, hash
as if we were hashing the constant, since we will be comparing
that way. */
if (tem != 0 && GET_CODE (tem) == REG
&& REGNO_QTY_VALID_P (REGNO (tem))
&& qty_mode[reg_qty[REGNO (tem)]] == GET_MODE (tem)
&& (tem1 = qty_const[reg_qty[REGNO (tem)]]) != 0
&& CONSTANT_P (tem1))
tem = tem1;
/* If we are about to do the last recursive call /* If we are about to do the last recursive call
needed at this level, change it into iteration. needed at this level, change it into iteration.
@ -2230,9 +2229,10 @@ refers_to_p (x, y)
set PBASE, PSTART, and PEND which correspond to the base of the address, set PBASE, PSTART, and PEND which correspond to the base of the address,
the starting offset, and ending offset respectively. the starting offset, and ending offset respectively.
ADDR is known to be a nonvarying address. ADDR is known to be a nonvarying address. */
cse_address_varies_p returns zero for nonvarying addresses. */ /* ??? Despite what the comments say, this function is in fact frequently
passed varying addresses. This does not appear to cause any problems. */
static void static void
set_nonvarying_address_components (addr, size, pbase, pstart, pend) set_nonvarying_address_components (addr, size, pbase, pstart, pend)
@ -2323,6 +2323,12 @@ set_nonvarying_address_components (addr, size, pbase, pstart, pend)
break; break;
} }
if (GET_CODE (base) == CONST_INT)
{
start += INTVAL (base);
base = const0_rtx;
}
end = start + size; end = start + size;
/* Set the return values. */ /* Set the return values. */
@ -2353,13 +2359,6 @@ refers_to_mem_p (x, base, start, end)
register enum rtx_code code; register enum rtx_code code;
register char *fmt; register char *fmt;
if (GET_CODE (base) == CONST_INT)
{
start += INTVAL (base);
end += INTVAL (base);
base = const0_rtx;
}
repeat: repeat:
if (x == 0) if (x == 0)
return 0; return 0;
@ -3086,7 +3085,7 @@ simplify_unary_operation (code, mode, op, op_mode)
/* We can do some operations on integer CONST_DOUBLEs. Also allow /* We can do some operations on integer CONST_DOUBLEs. Also allow
for a DImode operation on a CONST_INT. */ for a DImode operation on a CONST_INT. */
else if (GET_MODE (op) == VOIDmode && width == HOST_BITS_PER_INT * 2 else if (GET_MODE (op) == VOIDmode && width <= HOST_BITS_PER_INT * 2
&& (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)) && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
{ {
HOST_WIDE_INT l1, h1, lv, hv; HOST_WIDE_INT l1, h1, lv, hv;
@ -3123,10 +3122,8 @@ simplify_unary_operation (code, mode, op, op_mode)
break; break;
case TRUNCATE: case TRUNCATE:
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) /* This is just a change-of-mode, so do nothing. */
return GEN_INT (l1 & GET_MODE_MASK (mode)); lv = l1, hv = h1;
else
return 0;
break; break;
case ZERO_EXTEND: case ZERO_EXTEND:
@ -3220,7 +3217,10 @@ simplify_unary_operation (code, mode, op, op_mode)
set_float_handler (NULL_PTR); set_float_handler (NULL_PTR);
return x; return x;
} }
else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE_CLASS (mode) == MODE_INT
else if (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
&& GET_MODE_CLASS (mode) == MODE_INT
&& width <= HOST_BITS_PER_WIDE_INT && width > 0) && width <= HOST_BITS_PER_WIDE_INT && width > 0)
{ {
REAL_VALUE_TYPE d; REAL_VALUE_TYPE d;
@ -5001,7 +5001,11 @@ fold_rtx (x, insn)
if (GET_MODE (table) != Pmode) if (GET_MODE (table) != Pmode)
new = gen_rtx (TRUNCATE, GET_MODE (table), new); new = gen_rtx (TRUNCATE, GET_MODE (table), new);
return new; /* Indicate this is a constant. This isn't a
valid form of CONST, but it will only be used
to fold the next insns and then discarded, so
it should be safe. */
return gen_rtx (CONST, GET_MODE (new), new);
} }
} }
} }
@ -5174,13 +5178,26 @@ fold_rtx (x, insn)
switch (GET_RTX_CLASS (code)) switch (GET_RTX_CLASS (code))
{ {
case '1': case '1':
/* We can't simplify extension ops unless we know the original mode. */ {
if ((code == ZERO_EXTEND || code == SIGN_EXTEND) int is_const = 0;
&& mode_arg0 == VOIDmode)
break; /* We can't simplify extension ops unless we know the
new = simplify_unary_operation (code, mode, original mode. */
const_arg0 ? const_arg0 : folded_arg0, if ((code == ZERO_EXTEND || code == SIGN_EXTEND)
mode_arg0); && mode_arg0 == VOIDmode)
break;
/* If we had a CONST, strip it off and put it back later if we
fold. */
if (const_arg0 != 0 && GET_CODE (const_arg0) == CONST)
is_const = 1, const_arg0 = XEXP (const_arg0, 0);
new = simplify_unary_operation (code, mode,
const_arg0 ? const_arg0 : folded_arg0,
mode_arg0);
if (new != 0 && is_const)
new = gen_rtx (CONST, mode, new);
}
break; break;
case '<': case '<':
@ -5353,11 +5370,41 @@ fold_rtx (x, insn)
ADDR_DIFF_VEC table. */ ADDR_DIFF_VEC table. */
if (const_arg1 && GET_CODE (const_arg1) == LABEL_REF) if (const_arg1 && GET_CODE (const_arg1) == LABEL_REF)
{ {
rtx y = lookup_as_function (folded_arg0, MINUS); rtx y
= GET_CODE (folded_arg0) == MINUS ? folded_arg0
: lookup_as_function (folded_arg0, MINUS);
if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
&& XEXP (XEXP (y, 1), 0) == XEXP (const_arg1, 0)) && XEXP (XEXP (y, 1), 0) == XEXP (const_arg1, 0))
return XEXP (y, 0); return XEXP (y, 0);
/* Now try for a CONST of a MINUS like the above. */
if ((y = (GET_CODE (folded_arg0) == CONST ? folded_arg0
: lookup_as_function (folded_arg0, CONST))) != 0
&& GET_CODE (XEXP (y, 0)) == MINUS
&& GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
&& XEXP (XEXP (XEXP (y, 0),1), 0) == XEXP (const_arg1, 0))
return XEXP (XEXP (y, 0), 0);
}
/* Likewise if the operands are in the other order. */
if (const_arg0 && GET_CODE (const_arg0) == LABEL_REF)
{
rtx y
= GET_CODE (folded_arg1) == MINUS ? folded_arg1
: lookup_as_function (folded_arg1, MINUS);
if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
&& XEXP (XEXP (y, 1), 0) == XEXP (const_arg0, 0))
return XEXP (y, 0);
/* Now try for a CONST of a MINUS like the above. */
if ((y = (GET_CODE (folded_arg1) == CONST ? folded_arg1
: lookup_as_function (folded_arg1, CONST))) != 0
&& GET_CODE (XEXP (y, 0)) == MINUS
&& GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
&& XEXP (XEXP (XEXP (y, 0),1), 0) == XEXP (const_arg0, 0))
return XEXP (XEXP (y, 0), 0);
} }
/* If second operand is a register equivalent to a negative /* If second operand is a register equivalent to a negative
@ -5759,6 +5806,13 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
op0_elt = lookup (op0, op0_hash, mode); op0_elt = lookup (op0, op0_hash, mode);
op1_elt = lookup (op1, op1_hash, mode); op1_elt = lookup (op1, op1_hash, mode);
/* If both operands are already equivalent or if they are not in the
table but are identical, do nothing. */
if ((op0_elt != 0 && op1_elt != 0
&& op0_elt->first_same_value == op1_elt->first_same_value)
|| op0 == op1 || rtx_equal_p (op0, op1))
return;
/* If we aren't setting two things equal all we can do is save this /* If we aren't setting two things equal all we can do is save this
comparison. Similarly if this is floating-point. In the latter comparison. Similarly if this is floating-point. In the latter
case, OP1 might be zero and both -0.0 and 0.0 are equal to it. case, OP1 might be zero and both -0.0 and 0.0 are equal to it.
@ -5945,7 +5999,7 @@ cse_insn (insn, in_libcall_block)
{ {
for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1)) for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
if (GET_CODE (XEXP (tem, 0)) == CLOBBER) if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
invalidate (SET_DEST (XEXP (tem, 0))); invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
} }
if (GET_CODE (x) == SET) if (GET_CODE (x) == SET)
@ -5976,7 +6030,7 @@ cse_insn (insn, in_libcall_block)
canon_reg (SET_SRC (x), insn); canon_reg (SET_SRC (x), insn);
apply_change_group (); apply_change_group ();
fold_rtx (SET_SRC (x), insn); fold_rtx (SET_SRC (x), insn);
invalidate (SET_DEST (x)); invalidate (SET_DEST (x), VOIDmode);
} }
else else
n_sets = 1; n_sets = 1;
@ -6007,10 +6061,10 @@ cse_insn (insn, in_libcall_block)
if (GET_CODE (clobbered) == REG if (GET_CODE (clobbered) == REG
|| GET_CODE (clobbered) == SUBREG) || GET_CODE (clobbered) == SUBREG)
invalidate (clobbered); invalidate (clobbered, VOIDmode);
else if (GET_CODE (clobbered) == STRICT_LOW_PART else if (GET_CODE (clobbered) == STRICT_LOW_PART
|| GET_CODE (clobbered) == ZERO_EXTRACT) || GET_CODE (clobbered) == ZERO_EXTRACT)
invalidate (XEXP (clobbered, 0)); invalidate (XEXP (clobbered, 0), GET_MODE (clobbered));
} }
} }
@ -6026,7 +6080,7 @@ cse_insn (insn, in_libcall_block)
canon_reg (SET_SRC (y), insn); canon_reg (SET_SRC (y), insn);
apply_change_group (); apply_change_group ();
fold_rtx (SET_SRC (y), insn); fold_rtx (SET_SRC (y), insn);
invalidate (SET_DEST (y)); invalidate (SET_DEST (y), VOIDmode);
} }
else if (SET_DEST (y) == pc_rtx else if (SET_DEST (y) == pc_rtx
&& GET_CODE (SET_SRC (y)) == LABEL_REF) && GET_CODE (SET_SRC (y)) == LABEL_REF)
@ -6663,7 +6717,11 @@ cse_insn (insn, in_libcall_block)
else if (constant_pool_entries_cost else if (constant_pool_entries_cost
&& CONSTANT_P (trial) && CONSTANT_P (trial)
&& (src_folded == 0 || GET_CODE (src_folded) != MEM) && ! (GET_CODE (trial) == CONST
&& GET_CODE (XEXP (trial, 0)) == TRUNCATE)
&& (src_folded == 0
|| (GET_CODE (src_folded) != MEM
&& ! src_folded_force_flag))
&& GET_MODE_CLASS (mode) != MODE_CC) && GET_MODE_CLASS (mode) != MODE_CC)
{ {
src_folded_force_flag = 1; src_folded_force_flag = 1;
@ -6916,10 +6974,10 @@ cse_insn (insn, in_libcall_block)
{ {
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == MEM) || GET_CODE (dest) == MEM)
invalidate (dest); invalidate (dest, VOIDmode);
else if (GET_CODE (dest) == STRICT_LOW_PART else if (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == ZERO_EXTRACT) || GET_CODE (dest) == ZERO_EXTRACT)
invalidate (XEXP (dest, 0)); invalidate (XEXP (dest, 0), GET_MODE (dest));
sets[i].rtl = 0; sets[i].rtl = 0;
} }
@ -6965,7 +7023,10 @@ cse_insn (insn, in_libcall_block)
classp = 0; classp = 0;
} }
if (insert_regs (src_eqv, classp, 0)) if (insert_regs (src_eqv, classp, 0))
src_eqv_hash = HASH (src_eqv, eqvmode); {
rehash_using_reg (src_eqv);
src_eqv_hash = HASH (src_eqv, eqvmode);
}
elt = insert (src_eqv, classp, src_eqv_hash, eqvmode); elt = insert (src_eqv, classp, src_eqv_hash, eqvmode);
elt->in_memory = src_eqv_in_memory; elt->in_memory = src_eqv_in_memory;
elt->in_struct = src_eqv_in_struct; elt->in_struct = src_eqv_in_struct;
@ -7012,7 +7073,10 @@ cse_insn (insn, in_libcall_block)
any of the src_elt's, because they would have failed to any of the src_elt's, because they would have failed to
match if not still valid. */ match if not still valid. */
if (insert_regs (src, classp, 0)) if (insert_regs (src, classp, 0))
sets[i].src_hash = HASH (src, mode); {
rehash_using_reg (src);
sets[i].src_hash = HASH (src, mode);
}
elt = insert (src, classp, sets[i].src_hash, mode); elt = insert (src, classp, sets[i].src_hash, mode);
elt->in_memory = sets[i].src_in_memory; elt->in_memory = sets[i].src_in_memory;
elt->in_struct = sets[i].src_in_struct; elt->in_struct = sets[i].src_in_struct;
@ -7054,18 +7118,21 @@ cse_insn (insn, in_libcall_block)
for (i = 0; i < n_sets; i++) for (i = 0; i < n_sets; i++)
if (sets[i].rtl) if (sets[i].rtl)
{ {
register rtx dest = sets[i].inner_dest; /* We can't use the inner dest, because the mode associated with
a ZERO_EXTRACT is significant. */
register rtx dest = SET_DEST (sets[i].rtl);
/* Needed for registers to remove the register from its /* Needed for registers to remove the register from its
previous quantity's chain. previous quantity's chain.
Needed for memory if this is a nonvarying address, unless Needed for memory if this is a nonvarying address, unless
we have just done an invalidate_memory that covers even those. */ we have just done an invalidate_memory that covers even those. */
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
|| (! writes_memory.all && ! cse_rtx_addr_varies_p (dest))) || (GET_CODE (dest) == MEM && ! writes_memory.all
invalidate (dest); && ! cse_rtx_addr_varies_p (dest)))
invalidate (dest, VOIDmode);
else if (GET_CODE (dest) == STRICT_LOW_PART else if (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == ZERO_EXTRACT) || GET_CODE (dest) == ZERO_EXTRACT)
invalidate (XEXP (dest, 0)); invalidate (XEXP (dest, 0), GET_MODE (dest));
} }
/* Make sure registers mentioned in destinations /* Make sure registers mentioned in destinations
@ -7122,7 +7189,17 @@ cse_insn (insn, in_libcall_block)
|| in_libcall_block || in_libcall_block
/* If we didn't put a REG_EQUAL value or a source into the hash /* If we didn't put a REG_EQUAL value or a source into the hash
table, there is no point is recording DEST. */ table, there is no point is recording DEST. */
|| sets[i].src_elt == 0) || sets[i].src_elt == 0
/* If DEST is a paradoxical SUBREG and SRC is a ZERO_EXTEND
or SIGN_EXTEND, don't record DEST since it can cause
some tracking to be wrong.
??? Think about this more later. */
|| (GET_CODE (dest) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (dest))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
&& (GET_CODE (sets[i].src) == SIGN_EXTEND
|| GET_CODE (sets[i].src) == ZERO_EXTEND)))
continue; continue;
/* STRICT_LOW_PART isn't part of the value BEING set, /* STRICT_LOW_PART isn't part of the value BEING set,
@ -7134,9 +7211,12 @@ cse_insn (insn, in_libcall_block)
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG) if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG)
/* Registers must also be inserted into chains for quantities. */ /* Registers must also be inserted into chains for quantities. */
if (insert_regs (dest, sets[i].src_elt, 1)) if (insert_regs (dest, sets[i].src_elt, 1))
/* If `insert_regs' changes something, the hash code must be {
recalculated. */ /* If `insert_regs' changes something, the hash code must be
sets[i].dest_hash = HASH (dest, GET_MODE (dest)); recalculated. */
rehash_using_reg (dest);
sets[i].dest_hash = HASH (dest, GET_MODE (dest));
}
elt = insert (dest, sets[i].src_elt, elt = insert (dest, sets[i].src_elt,
sets[i].dest_hash, GET_MODE (dest)); sets[i].dest_hash, GET_MODE (dest));
@ -7200,7 +7280,10 @@ cse_insn (insn, in_libcall_block)
if (src_elt == 0) if (src_elt == 0)
{ {
if (insert_regs (new_src, classp, 0)) if (insert_regs (new_src, classp, 0))
src_hash = HASH (new_src, new_mode); {
rehash_using_reg (new_src);
src_hash = HASH (new_src, new_mode);
}
src_elt = insert (new_src, classp, src_hash, new_mode); src_elt = insert (new_src, classp, src_hash, new_mode);
src_elt->in_memory = elt->in_memory; src_elt->in_memory = elt->in_memory;
src_elt->in_struct = elt->in_struct; src_elt->in_struct = elt->in_struct;
@ -7377,7 +7460,7 @@ invalidate_from_clobbers (w, x)
/* This should be *very* rare. */ /* This should be *very* rare. */
if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM)) if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
invalidate (stack_pointer_rtx); invalidate (stack_pointer_rtx, VOIDmode);
} }
if (GET_CODE (x) == CLOBBER) if (GET_CODE (x) == CLOBBER)
@ -7387,10 +7470,10 @@ invalidate_from_clobbers (w, x)
{ {
if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
|| (GET_CODE (ref) == MEM && ! w->all)) || (GET_CODE (ref) == MEM && ! w->all))
invalidate (ref); invalidate (ref, VOIDmode);
else if (GET_CODE (ref) == STRICT_LOW_PART else if (GET_CODE (ref) == STRICT_LOW_PART
|| GET_CODE (ref) == ZERO_EXTRACT) || GET_CODE (ref) == ZERO_EXTRACT)
invalidate (XEXP (ref, 0)); invalidate (XEXP (ref, 0), GET_MODE (ref));
} }
} }
else if (GET_CODE (x) == PARALLEL) else if (GET_CODE (x) == PARALLEL)
@ -7406,10 +7489,10 @@ invalidate_from_clobbers (w, x)
{ {
if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
|| (GET_CODE (ref) == MEM && !w->all)) || (GET_CODE (ref) == MEM && !w->all))
invalidate (ref); invalidate (ref, VOIDmode);
else if (GET_CODE (ref) == STRICT_LOW_PART else if (GET_CODE (ref) == STRICT_LOW_PART
|| GET_CODE (ref) == ZERO_EXTRACT) || GET_CODE (ref) == ZERO_EXTRACT)
invalidate (XEXP (ref, 0)); invalidate (XEXP (ref, 0), GET_MODE (ref));
} }
} }
} }
@ -7537,11 +7620,12 @@ cse_around_loop (loop_start)
for (p = last_jump_equiv_class->first_same_value; p; for (p = last_jump_equiv_class->first_same_value; p;
p = p->next_same_value) p = p->next_same_value)
if (GET_CODE (p->exp) == MEM || GET_CODE (p->exp) == REG if (GET_CODE (p->exp) == MEM || GET_CODE (p->exp) == REG
|| GET_CODE (p->exp) == SUBREG) || (GET_CODE (p->exp) == SUBREG
invalidate (p->exp); && GET_CODE (SUBREG_REG (p->exp)) == REG))
invalidate (p->exp, VOIDmode);
else if (GET_CODE (p->exp) == STRICT_LOW_PART else if (GET_CODE (p->exp) == STRICT_LOW_PART
|| GET_CODE (p->exp) == ZERO_EXTRACT) || GET_CODE (p->exp) == ZERO_EXTRACT)
invalidate (XEXP (p->exp, 0)); invalidate (XEXP (p->exp, 0), GET_MODE (p->exp));
/* Process insns starting after LOOP_START until we hit a CALL_INSN or /* Process insns starting after LOOP_START until we hit a CALL_INSN or
a CODE_LABEL (we could handle a CALL_INSN, but it isn't worth it). a CODE_LABEL (we could handle a CALL_INSN, but it isn't worth it).
@ -7600,10 +7684,10 @@ invalidate_skipped_set (dest, set)
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
|| (! skipped_writes_memory.all && ! cse_rtx_addr_varies_p (dest))) || (! skipped_writes_memory.all && ! cse_rtx_addr_varies_p (dest)))
invalidate (dest); invalidate (dest, VOIDmode);
else if (GET_CODE (dest) == STRICT_LOW_PART else if (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == ZERO_EXTRACT) || GET_CODE (dest) == ZERO_EXTRACT)
invalidate (XEXP (dest, 0)); invalidate (XEXP (dest, 0), GET_MODE (dest));
} }
/* Invalidate all insns from START up to the end of the function or the /* Invalidate all insns from START up to the end of the function or the
@ -7755,10 +7839,10 @@ cse_set_around_loop (x, insn, loop_start)
if (GET_CODE (SET_DEST (x)) == REG || GET_CODE (SET_DEST (x)) == SUBREG if (GET_CODE (SET_DEST (x)) == REG || GET_CODE (SET_DEST (x)) == SUBREG
|| (GET_CODE (SET_DEST (x)) == MEM && ! writes_memory.all || (GET_CODE (SET_DEST (x)) == MEM && ! writes_memory.all
&& ! cse_rtx_addr_varies_p (SET_DEST (x)))) && ! cse_rtx_addr_varies_p (SET_DEST (x))))
invalidate (SET_DEST (x)); invalidate (SET_DEST (x), VOIDmode);
else if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART else if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
|| GET_CODE (SET_DEST (x)) == ZERO_EXTRACT) || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
invalidate (XEXP (SET_DEST (x), 0)); invalidate (XEXP (SET_DEST (x), 0), GET_MODE (SET_DEST (x)));
} }
/* Find the end of INSN's basic block and return its range, /* Find the end of INSN's basic block and return its range,

View file

@ -1843,7 +1843,13 @@ dbxout_symbol_location (decl, type, suffix, home)
letter = decl_function_context (decl) ? 'V' : 'S'; letter = decl_function_context (decl) ? 'V' : 'S';
if (!DECL_INITIAL (decl)) /* This should be the same condition as in assemble_variable, but
we don't have access to dont_output_data here. So, instead,
we rely on the fact that error_mark_node initializers always
end up in bss for C++ and never end up in bss for C. */
if (DECL_INITIAL (decl) == 0
|| (!strcmp (lang_identify (), "cplusplus")
&& DECL_INITIAL (decl) == error_mark_node))
current_sym_code = N_LCSYM; current_sym_code = N_LCSYM;
else if (DECL_IN_TEXT_SECTION (decl)) else if (DECL_IN_TEXT_SECTION (decl))
/* This is not quite right, but it's the closest /* This is not quite right, but it's the closest

View file

@ -4435,118 +4435,91 @@ output_decl (decl, containing_scope)
output_formal_types (TREE_TYPE (decl)); output_formal_types (TREE_TYPE (decl));
else else
{ {
/* Generate DIEs to represent all known formal parameters */
register tree arg_decls = DECL_ARGUMENTS (decl); register tree arg_decls = DECL_ARGUMENTS (decl);
register tree parm;
{ /* WARNING! Kludge zone ahead! Here we have a special
register tree last_arg; hack for svr4 SDB compatibility. Instead of passing the
current FUNCTION_DECL node as the second parameter (i.e.
the `containing_scope' parameter) to `output_decl' (as
we ought to) we instead pass a pointer to our own private
fake_containing_scope node. That node is a RECORD_TYPE
node which NO OTHER TYPE may ever actually be a member of.
last_arg = (arg_decls && TREE_CODE (arg_decls) != ERROR_MARK) This pointer will ultimately get passed into `output_type'
? tree_last (arg_decls) as its `containing_scope' parameter. `Output_type' will
: NULL; then perform its part in the hack... i.e. it will pend
the type of the formal parameter onto the pending_types
list. Later on, when we are done generating the whole
sequence of formal parameter DIEs for this function
definition, we will un-pend all previously pended types
of formal parameters for this function definition.
/* Generate DIEs to represent all known formal parameters, but This whole kludge prevents any type DIEs from being
don't do it if this looks like a varargs function. A given mixed in with the formal parameter DIEs. That's good
function is considered to be a varargs function if (and only because svr4 SDB believes that the list of formal
if) its last named argument is named `__builtin_va_alist'. */ parameter DIEs for a function ends wherever the first
non-formal-parameter DIE appears. Thus, we have to
keep the formal parameter DIEs segregated. They must
all appear (consecutively) at the start of the list of
children for the DIE representing the function definition.
Then (and only then) may we output any additional DIEs
needed to represent the types of these formal parameters.
*/
if (! last_arg /*
|| ! DECL_NAME (last_arg) When generating DIEs, generate the unspecified_parameters
|| strcmp (IDENTIFIER_POINTER (DECL_NAME (last_arg)), DIE instead if we come across the arg "__builtin_va_alist"
"__builtin_va_alist")) */
{
register tree parm;
/* WARNING! Kludge zone ahead! Here we have a special for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
hack for svr4 SDB compatibility. Instead of passing the if (TREE_CODE (parm) == PARM_DECL)
current FUNCTION_DECL node as the second parameter (i.e. {
the `containing_scope' parameter) to `output_decl' (as if (DECL_NAME(parm) &&
we ought to) we instead pass a pointer to our own private !strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
fake_containing_scope node. That node is a RECORD_TYPE "__builtin_va_alist") )
node which NO OTHER TYPE may ever actually be a member of. output_die (output_unspecified_parameters_die, decl);
else
This pointer will ultimately get passed into `output_type' output_decl (parm, fake_containing_scope);
as its `containing_scope' parameter. `Output_type' will
then perform its part in the hack... i.e. it will pend
the type of the formal parameter onto the pending_types
list. Later on, when we are done generating the whole
sequence of formal parameter DIEs for this function
definition, we will un-pend all previously pended types
of formal parameters for this function definition.
This whole kludge prevents any type DIEs from being
mixed in with the formal parameter DIEs. That's good
because svr4 SDB believes that the list of formal
parameter DIEs for a function ends wherever the first
non-formal-parameter DIE appears. Thus, we have to
keep the formal parameter DIEs segregated. They must
all appear (consecutively) at the start of the list of
children for the DIE representing the function definition.
Then (and only then) may we output any additional DIEs
needed to represent the types of these formal parameters.
*/
for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
output_decl (parm, fake_containing_scope);
/* Now that we have finished generating all of the DIEs to
represent the formal parameters themselves, force out
any DIEs needed to represent their types. We do this
simply by un-pending all previously pended types which
can legitimately go into the chain of children DIEs for
the current FUNCTION_DECL. */
output_pending_types_for_scope (decl);
} }
}
/* Now try to decide if we should put an ellipsis at the end. */ /*
Now that we have finished generating all of the DIEs to
represent the formal parameters themselves, force out
any DIEs needed to represent their types. We do this
simply by un-pending all previously pended types which
can legitimately go into the chain of children DIEs for
the current FUNCTION_DECL.
*/
output_pending_types_for_scope (decl);
/*
Decide whether we need a unspecified_parameters DIE at the end.
There are 2 more cases to do this for:
1) the ansi ... declaration - this is detectable when the end
of the arg list is not a void_type_node
2) an unprototyped function declaration (not a definition). This
just means that we have no info about the parameters at all.
*/
{ {
register int has_ellipsis = TRUE; /* default assumption */
register tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); register tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
if (fn_arg_types) if (fn_arg_types)
{ {
/* This function declaration/definition was prototyped. */ /* this is the prototyped case, check for ... */
if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
/* If the list of formal argument types ends with a output_die (output_unspecified_parameters_die, decl);
void_type_node, then the formals list did *not* end }
with an ellipsis. */ else
{
if (TREE_VALUE (tree_last (fn_arg_types)) == void_type_node) /* this is unprotoyped, check for undefined (just declaration) */
has_ellipsis = FALSE; if (!DECL_INITIAL (decl))
} output_die (output_unspecified_parameters_die, decl);
else }
{
/* This function declaration/definition was not prototyped. */
/* Note that all non-prototyped function *declarations* are
assumed to represent varargs functions (until proven
otherwise). */
if (DECL_INITIAL (decl)) /* if this is a func definition */
{
if (!arg_decls)
has_ellipsis = FALSE; /* no args == (void) */
else
{
/* For a non-prototyped function definition which
declares one or more formal parameters, if the name
of the first formal parameter is *not*
__builtin_va_alist then we must assume that this
is *not* a varargs function. */
if (DECL_NAME (arg_decls)
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (arg_decls)),
"__builtin_va_alist"))
has_ellipsis = FALSE;
}
}
}
if (has_ellipsis)
output_die (output_unspecified_parameters_die, decl);
} }
} }

View file

@ -1176,7 +1176,7 @@ operand_subword (op, i, validate_address, mode)
if (GET_MODE_CLASS (mode) != MODE_INT if (GET_MODE_CLASS (mode) != MODE_INT
|| (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE) || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)
|| BITS_PER_WORD > HOST_BITS_PER_INT) || BITS_PER_WORD > HOST_BITS_PER_WIDE_INT)
return 0; return 0;
if (WORDS_BIG_ENDIAN) if (WORDS_BIG_ENDIAN)
@ -2130,9 +2130,10 @@ add_insn (insn)
last_insn = insn; last_insn = insn;
} }
/* Add INSN into the doubly-linked list after insn AFTER. This should be the /* Add INSN into the doubly-linked list after insn AFTER. This and
only function called to insert an insn once delay slots have been filled the next should be the only functions called to insert an insn once
since only it knows how to update a SEQUENCE. */ delay slots have been filled since only they know how to update a
SEQUENCE. */
void void
add_insn_after (insn, after) add_insn_after (insn, after)
@ -2140,6 +2141,9 @@ add_insn_after (insn, after)
{ {
rtx next = NEXT_INSN (after); rtx next = NEXT_INSN (after);
if (optimize && INSN_DELETED_P (after))
abort ();
NEXT_INSN (insn) = next; NEXT_INSN (insn) = next;
PREV_INSN (insn) = after; PREV_INSN (insn) = after;
@ -2157,7 +2161,13 @@ add_insn_after (insn, after)
/* Scan all pending sequences too. */ /* Scan all pending sequences too. */
for (; stack; stack = stack->next) for (; stack; stack = stack->next)
if (after == stack->last) if (after == stack->last)
stack->last = insn; {
stack->last = insn;
break;
}
if (stack == 0)
abort ();
} }
NEXT_INSN (after) = insn; NEXT_INSN (after) = insn;
@ -2168,6 +2178,54 @@ add_insn_after (insn, after)
} }
} }
/* Add INSN into the doubly-linked list before insn BEFORE. This and
the previous should be the only functions called to insert an insn once
delay slots have been filled since only they know how to update a
SEQUENCE. */
void
add_insn_before (insn, before)
rtx insn, before;
{
rtx prev = PREV_INSN (before);
if (optimize && INSN_DELETED_P (before))
abort ();
PREV_INSN (insn) = prev;
NEXT_INSN (insn) = before;
if (prev)
{
NEXT_INSN (prev) = insn;
if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
rtx sequence = PATTERN (prev);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
}
}
else if (first_insn == before)
first_insn = insn;
else
{
struct sequence_stack *stack = sequence_stack;
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
if (before == stack->first)
{
stack->first = insn;
break;
}
if (stack == 0)
abort ();
}
PREV_INSN (before) = insn;
if (GET_CODE (before) == INSN && GET_CODE (PATTERN (before)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
}
/* Delete all insns made since FROM. /* Delete all insns made since FROM.
FROM becomes the new last instruction. */ FROM becomes the new last instruction. */
@ -2279,7 +2337,7 @@ emit_insn_before (pattern, before)
for (i = 0; i < XVECLEN (pattern, 0); i++) for (i = 0; i < XVECLEN (pattern, 0); i++)
{ {
insn = XVECEXP (pattern, 0, i); insn = XVECEXP (pattern, 0, i);
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
} }
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE) if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern; sequence_result[XVECLEN (pattern, 0)] = pattern;
@ -2287,7 +2345,7 @@ emit_insn_before (pattern, before)
else else
{ {
insn = make_insn_raw (pattern); insn = make_insn_raw (pattern);
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
} }
return insn; return insn;
@ -2307,7 +2365,7 @@ emit_jump_insn_before (pattern, before)
else else
{ {
insn = make_jump_insn_raw (pattern); insn = make_jump_insn_raw (pattern);
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
} }
return insn; return insn;
@ -2327,7 +2385,7 @@ emit_call_insn_before (pattern, before)
else else
{ {
insn = make_call_insn_raw (pattern); insn = make_call_insn_raw (pattern);
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
PUT_CODE (insn, CALL_INSN); PUT_CODE (insn, CALL_INSN);
} }
@ -2345,7 +2403,7 @@ emit_barrier_before (before)
INSN_UID (insn) = cur_insn_uid++; INSN_UID (insn) = cur_insn_uid++;
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
return insn; return insn;
} }
@ -2361,7 +2419,7 @@ emit_note_before (subtype, before)
NOTE_SOURCE_FILE (note) = 0; NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype; NOTE_LINE_NUMBER (note) = subtype;
add_insn_after (note, PREV_INSN (before)); add_insn_before (note, before);
return note; return note;
} }
@ -2577,7 +2635,7 @@ emit_insns_before (insn, before)
while (insn) while (insn)
{ {
rtx next = NEXT_INSN (insn); rtx next = NEXT_INSN (insn);
add_insn_after (insn, PREV_INSN (before)); add_insn_before (insn, before);
last = insn; last = insn;
insn = next; insn = next;
} }

View file

@ -299,7 +299,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
/* Here we transfer the words of the field /* Here we transfer the words of the field
in the order least significant first. in the order least significant first.
This is because the most significant word is the one which may This is because the most significant word is the one which may
be less than full. */ be less than full.
However, only do that if the value is not BLKmode. */
int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
int i; int i;
@ -315,8 +318,8 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
{ {
/* If I is 0, use the low-order word in both field and target; /* If I is 0, use the low-order word in both field and target;
if I is 1, use the next to lowest word; and so on. */ if I is 1, use the next to lowest word; and so on. */
int wordnum = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); int wordnum = (backwards ? nwords - i - 1 : i);
int bit_offset = (WORDS_BIG_ENDIAN int bit_offset = (backwards
? MAX (bitsize - (i + 1) * BITS_PER_WORD, 0) ? MAX (bitsize - (i + 1) * BITS_PER_WORD, 0)
: i * BITS_PER_WORD); : i * BITS_PER_WORD);
store_bit_field (op0, MIN (BITS_PER_WORD, store_bit_field (op0, MIN (BITS_PER_WORD,
@ -369,7 +372,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT) && !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */ /* Ensure insv's size is wide enough for this field. */
&& (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]) && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3])
>= bitsize)) >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
&& (bitsize + bitpos
> GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]))))
{ {
int xbitpos = bitpos; int xbitpos = bitpos;
rtx value1; rtx value1;
@ -741,19 +747,13 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
>> (bitsize - bitsdone - thissize)) >> (bitsize - bitsdone - thissize))
& (((HOST_WIDE_INT) 1 << thissize) - 1)); & (((HOST_WIDE_INT) 1 << thissize) - 1));
else else
{ /* The args are chosen so that the last part includes the lsb.
/* The args are chosen so that the last part Give extract_bit_field the value it needs (with endianness
includes the lsb. */ compensation) to fetch the piece we want. */
int bit_offset = 0; part = extract_fixed_bit_field (word_mode, value, 0, thissize,
/* If the value isn't in memory, then it must be right aligned GET_MODE_BITSIZE (GET_MODE (value))
if a register, so skip past the padding on the left. If it - bitsize + bitsdone,
is in memory, then there is no padding on the left. */ NULL_RTX, 1, align);
if (GET_CODE (value) != MEM)
bit_offset = BITS_PER_WORD - bitsize;
part = extract_fixed_bit_field (word_mode, value, 0, thissize,
bit_offset + bitsdone,
NULL_RTX, 1, align);
}
#else #else
/* Fetch successively more significant portions. */ /* Fetch successively more significant portions. */
if (GET_CODE (value) == CONST_INT) if (GET_CODE (value) == CONST_INT)
@ -972,7 +972,10 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
#ifdef HAVE_extzv #ifdef HAVE_extzv
if (HAVE_extzv if (HAVE_extzv
&& (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]) && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0])
>= bitsize)) >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
&& (bitsize + bitpos
> GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]))))
{ {
int xbitpos = bitpos, xoffset = offset; int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx; rtx bitsize_rtx, bitpos_rtx;
@ -1111,7 +1114,10 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
#ifdef HAVE_extv #ifdef HAVE_extv
if (HAVE_extv if (HAVE_extv
&& (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]) && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0])
>= bitsize)) >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
&& (bitsize + bitpos
> GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]))))
{ {
int xbitpos = bitpos, xoffset = offset; int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx; rtx bitsize_rtx, bitpos_rtx;
@ -2053,23 +2059,31 @@ expand_mult (mode, op0, op1, target, unsignedp)
{ {
rtx const_op1 = op1; rtx const_op1 = op1;
/* synth_mult does an `unsigned int' multiply. As long as the mode is
less than or equal in size to `unsigned int' this doesn't matter.
If the mode is larger than `unsigned int', then synth_mult works only
if the constant value exactly fits in an `unsigned int' without any
truncation. This means that multiplying by negative values does
not work; results are off by 2^32 on a 32 bit machine. */
/* If we are multiplying in DImode, it may still be a win /* If we are multiplying in DImode, it may still be a win
to try to work with shifts and adds. */ to try to work with shifts and adds. */
if (GET_CODE (op1) == CONST_DOUBLE if (GET_CODE (op1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT && GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT
&& HOST_BITS_PER_INT <= BITS_PER_WORD) && HOST_BITS_PER_INT >= BITS_PER_WORD
{ && CONST_DOUBLE_HIGH (op1) == 0)
if ((CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) >= 0) const_op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
|| (CONST_DOUBLE_HIGH (op1) == -1 && CONST_DOUBLE_LOW (op1) < 0)) else if (HOST_BITS_PER_INT < GET_MODE_BITSIZE (mode)
const_op1 = GEN_INT (CONST_DOUBLE_LOW (op1)); && GET_CODE (op1) == CONST_INT
} && INTVAL (op1) < 0)
const_op1 = 0;
/* We used to test optimize here, on the grounds that it's better to /* We used to test optimize here, on the grounds that it's better to
produce a smaller program when -O is not used. produce a smaller program when -O is not used.
But this causes such a terrible slowdown sometimes But this causes such a terrible slowdown sometimes
that it seems better to use synth_mult always. */ that it seems better to use synth_mult always. */
if (GET_CODE (const_op1) == CONST_INT) if (const_op1 && GET_CODE (const_op1) == CONST_INT)
{ {
struct algorithm alg; struct algorithm alg;
struct algorithm alg2; struct algorithm alg2;
@ -2087,13 +2101,20 @@ expand_mult (mode, op0, op1, target, unsignedp)
mult_cost = MIN (12 * add_cost, mult_cost); mult_cost = MIN (12 * add_cost, mult_cost);
synth_mult (&alg, val, mult_cost); synth_mult (&alg, val, mult_cost);
synth_mult (&alg2, - val,
(alg.cost < mult_cost ? alg.cost : mult_cost) - negate_cost); /* This works only if the inverted value actually fits in an
if (alg2.cost + negate_cost < alg.cost) `unsigned int' */
alg = alg2, variant = negate_variant; if (HOST_BITS_PER_INT >= GET_MODE_BITSIZE (mode))
{
synth_mult (&alg2, - val,
(alg.cost < mult_cost ? alg.cost : mult_cost) - negate_cost);
if (alg2.cost + negate_cost < alg.cost)
alg = alg2, variant = negate_variant;
}
/* This proves very useful for division-by-constant. */ /* This proves very useful for division-by-constant. */
synth_mult (&alg2, val - 1, (alg.cost < mult_cost ? alg.cost : mult_cost) - add_cost); synth_mult (&alg2, val - 1,
(alg.cost < mult_cost ? alg.cost : mult_cost) - add_cost);
if (alg2.cost + add_cost < alg.cost) if (alg2.cost + add_cost < alg.cost)
alg = alg2, variant = add_variant; alg = alg2, variant = add_variant;
@ -2131,7 +2152,9 @@ expand_mult (mode, op0, op1, target, unsignedp)
int log = alg.log[opno]; int log = alg.log[opno];
int preserve = preserve_subexpressions_p (); int preserve = preserve_subexpressions_p ();
rtx shift_subtarget = preserve ? 0 : accum; rtx shift_subtarget = preserve ? 0 : accum;
rtx add_target = opno == alg.ops - 1 && target != 0 ? target : 0; rtx add_target
= (opno == alg.ops - 1 && target != 0 && variant != add_variant
? target : 0);
rtx accum_target = preserve ? 0 : accum; rtx accum_target = preserve ? 0 : accum;
switch (alg.op[opno]) switch (alg.op[opno])
@ -2568,7 +2591,7 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
rtx quotient = 0, remainder = 0; rtx quotient = 0, remainder = 0;
rtx last; rtx last;
int size; int size;
rtx insn; rtx insn, set;
optab optab1, optab2; optab optab1, optab2;
int op1_is_constant, op1_is_pow2; int op1_is_constant, op1_is_pow2;
@ -2813,10 +2836,13 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
} }
insn = get_last_insn (); insn = get_last_insn ();
REG_NOTES (insn) if (insn != last
= gen_rtx (EXPR_LIST, REG_EQUAL, && (set = single_set (insn)) != 0
gen_rtx (UDIV, compute_mode, op0, op1), && SET_DEST (set) == quotient)
REG_NOTES (insn)); REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_EQUAL,
gen_rtx (UDIV, compute_mode, op0, op1),
REG_NOTES (insn));
} }
else /* TRUNC_DIV, signed */ else /* TRUNC_DIV, signed */
{ {
@ -2878,11 +2904,14 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (d < 0) if (d < 0)
{ {
insn = get_last_insn (); insn = get_last_insn ();
REG_NOTES (insn) if (insn != last
= gen_rtx (EXPR_LIST, REG_EQUAL, && (set = single_set (insn)) != 0
gen_rtx (DIV, compute_mode, op0, && SET_DEST (set) == quotient)
GEN_INT (abs_d)), REG_NOTES (insn)
REG_NOTES (insn)); = gen_rtx (EXPR_LIST, REG_EQUAL,
gen_rtx (DIV, compute_mode, op0,
GEN_INT (abs_d)),
REG_NOTES (insn));
quotient = expand_unop (compute_mode, neg_optab, quotient = expand_unop (compute_mode, neg_optab,
quotient, quotient, 0); quotient, quotient, 0);
@ -2935,14 +2964,14 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
} }
} }
if (quotient != 0) insn = get_last_insn ();
{ if (insn != last
insn = get_last_insn (); && (set = single_set (insn)) != 0
REG_NOTES (insn) && SET_DEST (set) == quotient)
= gen_rtx (EXPR_LIST, REG_EQUAL, REG_NOTES (insn)
gen_rtx (DIV, compute_mode, op0, op1), = gen_rtx (EXPR_LIST, REG_EQUAL,
REG_NOTES (insn)); gen_rtx (DIV, compute_mode, op0, op1),
} REG_NOTES (insn));
} }
break; break;
} }
@ -3218,6 +3247,44 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
} }
else /* signed */ else /* signed */
{ {
if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
&& INTVAL (op1) >= 0)
{
/* This is extremely similar to the code for the unsigned case
above. For 2.7 we should merge these variants, but for
2.6.1 I don't want to touch the code for unsigned since that
get used in C. The signed case will only be used by other
languages (Ada). */
rtx t1, t2, t3;
unsigned HOST_WIDE_INT d = INTVAL (op1);
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
build_int_2 (floor_log2 (d), 0),
tquotient, 0);
t2 = expand_binop (compute_mode, and_optab, op0,
GEN_INT (d - 1),
NULL_RTX, 1, OPTAB_LIB_WIDEN);
t3 = gen_reg_rtx (compute_mode);
t3 = emit_store_flag (t3, NE, t2, const0_rtx,
compute_mode, 1, 1);
if (t3 == 0)
{
rtx lab;
lab = gen_label_rtx ();
emit_cmp_insn (t2, const0_rtx, EQ, NULL_RTX,
compute_mode, 0, 0);
emit_jump_insn (gen_beq (lab));
expand_inc (t1, const1_rtx);
emit_label (lab);
quotient = t1;
}
else
quotient = force_operand (gen_rtx (PLUS, compute_mode,
t1, t3),
tquotient);
break;
}
/* Try using an instruction that produces both the quotient and /* Try using an instruction that produces both the quotient and
remainder, using truncation. We can easily compensate the remainder, using truncation. We can easily compensate the
quotient or remainder to get ceiling rounding, once we have the quotient or remainder to get ceiling rounding, once we have the

View file

@ -1025,6 +1025,41 @@ convert_move (to, from, unsignedp)
} }
} }
if (to_mode == PDImode)
{
if (from_mode != DImode)
from = convert_to_mode (DImode, from, unsignedp);
#ifdef HAVE_truncdipdi2
if (HAVE_truncdipdi2)
{
emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
return;
}
#endif /* HAVE_truncdipdi2 */
abort ();
}
if (from_mode == PDImode)
{
if (to_mode != DImode)
{
from = convert_to_mode (DImode, from, unsignedp);
from_mode = DImode;
}
else
{
#ifdef HAVE_extendpdidi2
if (HAVE_extendpdidi2)
{
emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
return;
}
#endif /* HAVE_extendpdidi2 */
abort ();
}
}
/* Now follow all the conversions between integers /* Now follow all the conversions between integers
no more than a word long. */ no more than a word long. */
@ -1164,6 +1199,58 @@ convert_move (to, from, unsignedp)
return; return;
} }
if (from_mode == TImode && to_mode == DImode)
{
#ifdef HAVE_trunctidi2
if (HAVE_trunctidi2)
{
emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
return;
}
#endif
convert_move (to, force_reg (from_mode, from), unsignedp);
return;
}
if (from_mode == TImode && to_mode == SImode)
{
#ifdef HAVE_trunctisi2
if (HAVE_trunctisi2)
{
emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
return;
}
#endif
convert_move (to, force_reg (from_mode, from), unsignedp);
return;
}
if (from_mode == TImode && to_mode == HImode)
{
#ifdef HAVE_trunctihi2
if (HAVE_trunctihi2)
{
emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
return;
}
#endif
convert_move (to, force_reg (from_mode, from), unsignedp);
return;
}
if (from_mode == TImode && to_mode == QImode)
{
#ifdef HAVE_trunctiqi2
if (HAVE_trunctiqi2)
{
emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
return;
}
#endif
convert_move (to, force_reg (from_mode, from), unsignedp);
return;
}
/* Handle truncation of volatile memrefs, and so on; /* Handle truncation of volatile memrefs, and so on;
the things that couldn't be truncated directly, the things that couldn't be truncated directly,
and for which there was no special instruction. */ and for which there was no special instruction. */
@ -1603,6 +1690,9 @@ move_block_to_reg (regno, x, nregs, mode)
int i; int i;
rtx pat, last; rtx pat, last;
if (nregs == 0)
return;
if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x)) if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
x = validize_mem (force_const_mem (mode, x)); x = validize_mem (force_const_mem (mode, x));
@ -1823,8 +1913,6 @@ emit_move_insn_1 (x, y)
int stack = push_operand (x, GET_MODE (x)); int stack = push_operand (x, GET_MODE (x));
rtx insns; rtx insns;
start_sequence ();
/* If this is a stack, push the highpart first, so it /* If this is a stack, push the highpart first, so it
will be in the argument order. will be in the argument order.
@ -1858,17 +1946,6 @@ emit_move_insn_1 (x, y)
(gen_imagpart (submode, x), gen_imagpart (submode, y))); (gen_imagpart (submode, x), gen_imagpart (submode, y)));
} }
insns = get_insns ();
end_sequence ();
/* If X is a CONCAT, we got insns like RD = RS, ID = IS,
each with a separate pseudo as destination.
It's not correct for flow to treat them as a unit. */
if (GET_CODE (x) != CONCAT)
emit_no_conflict_block (insns, x, y, NULL_RTX, NULL_RTX);
else
emit_insns (insns);
return get_last_insn (); return get_last_insn ();
} }
@ -1880,8 +1957,6 @@ emit_move_insn_1 (x, y)
rtx last_insn = 0; rtx last_insn = 0;
rtx insns; rtx insns;
start_sequence ();
for (i = 0; for (i = 0;
i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
i++) i++)
@ -1906,10 +1981,6 @@ emit_move_insn_1 (x, y)
last_insn = emit_move_insn (xpart, ypart); last_insn = emit_move_insn (xpart, ypart);
} }
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, x, y, NULL_RTX, NULL_RTX);
return last_insn; return last_insn;
} }
else else
@ -2724,6 +2795,7 @@ store_expr (exp, target, want_value)
The string constant may be shorter than the array. The string constant may be shorter than the array.
So copy just the string's actual length, and clear the rest. */ So copy just the string's actual length, and clear the rest. */
rtx size; rtx size;
rtx addr;
/* Get the size of the data type of the string, /* Get the size of the data type of the string,
which is actually the size of the target. */ which is actually the size of the target. */
@ -2752,17 +2824,16 @@ store_expr (exp, target, want_value)
that we have to clear. */ that we have to clear. */
if (GET_CODE (copy_size_rtx) == CONST_INT) if (GET_CODE (copy_size_rtx) == CONST_INT)
{ {
temp = plus_constant (XEXP (target, 0), addr = plus_constant (XEXP (target, 0),
TREE_STRING_LENGTH (exp)); TREE_STRING_LENGTH (exp));
size = plus_constant (size, size = plus_constant (size, - TREE_STRING_LENGTH (exp));
- TREE_STRING_LENGTH (exp));
} }
else else
{ {
enum machine_mode size_mode = Pmode; enum machine_mode size_mode = Pmode;
temp = force_reg (Pmode, XEXP (target, 0)); addr = force_reg (Pmode, XEXP (target, 0));
temp = expand_binop (size_mode, add_optab, temp, addr = expand_binop (size_mode, add_optab, addr,
copy_size_rtx, NULL_RTX, 0, copy_size_rtx, NULL_RTX, 0,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
@ -2779,13 +2850,14 @@ store_expr (exp, target, want_value)
if (size != const0_rtx) if (size != const0_rtx)
{ {
#ifdef TARGET_MEM_FUNCTIONS #ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memset_libfunc, 0, VOIDmode, 3, emit_library_call (memset_libfunc, 0, VOIDmode, 3, addr,
temp, Pmode, const0_rtx, Pmode, size, Pmode); Pmode, const0_rtx, Pmode, size, Pmode);
#else #else
emit_library_call (bzero_libfunc, 0, VOIDmode, 2, emit_library_call (bzero_libfunc, 0, VOIDmode, 2,
temp, Pmode, size, Pmode); addr, Pmode, size, Pmode);
#endif #endif
} }
if (label) if (label)
emit_label (label); emit_label (label);
} }
@ -3507,7 +3579,13 @@ safe_from_p (x, exp)
rtx exp_rtl = 0; rtx exp_rtl = 0;
int i, nops; int i, nops;
if (x == 0) if (x == 0
/* If EXP has varying size, we MUST use a target since we currently
have no way of allocating temporaries of variable size. So we
assume here that something at a higher level has prevented a
clash. This is somewhat bogus, but the best we can do. */
|| (TREE_TYPE (exp) != 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST))
return 1; return 1;
/* If this is a subreg of a hard register, declare it unsafe, otherwise, /* If this is a subreg of a hard register, declare it unsafe, otherwise,
@ -4340,13 +4418,16 @@ expand_expr (exp, target, tmode, modifier)
} }
/* Fold an expression like: "foo"[2]. /* Fold an expression like: "foo"[2].
This is not done in fold so it won't happen inside &. */ This is not done in fold so it won't happen inside &.
Don't fold if this is for wide characters since it's too
difficult to do correctly and this is a very rare case. */
if (TREE_CODE (array) == STRING_CST if (TREE_CODE (array) == STRING_CST
&& TREE_CODE (index) == INTEGER_CST && TREE_CODE (index) == INTEGER_CST
&& !TREE_INT_CST_HIGH (index) && !TREE_INT_CST_HIGH (index)
&& (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array) && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array)
&& GET_MODE_CLASS (mode) == MODE_INT) && GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
return GEN_INT (TREE_STRING_POINTER (array)[i]); return GEN_INT (TREE_STRING_POINTER (array)[i]);
/* If this is a constant index into a constant array, /* If this is a constant index into a constant array,
@ -4404,9 +4485,12 @@ expand_expr (exp, target, tmode, modifier)
case COMPONENT_REF: case COMPONENT_REF:
case BIT_FIELD_REF: case BIT_FIELD_REF:
/* If the operand is a CONSTRUCTOR, we can just extract the /* If the operand is a CONSTRUCTOR, we can just extract the
appropriate field if it is present. */ appropriate field if it is present. Don't do this if we have
already written the data since we want to refer to that copy
and varasm.c assumes that's what we'll do. */
if (code != ARRAY_REF if (code != ARRAY_REF
&& TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR) && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
&& TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
{ {
tree elt; tree elt;
@ -5450,7 +5534,9 @@ expand_expr (exp, target, tmode, modifier)
temp = 0; temp = 0;
else if (original_target else if (original_target
&& safe_from_p (original_target, TREE_OPERAND (exp, 0)) && safe_from_p (original_target, TREE_OPERAND (exp, 0))
&& GET_MODE (original_target) == mode) && GET_MODE (original_target) == mode
&& ! (GET_CODE (original_target) == MEM
&& MEM_VOLATILE_P (original_target)))
temp = original_target; temp = original_target;
else if (mode == BLKmode) else if (mode == BLKmode)
{ {
@ -5498,8 +5584,7 @@ expand_expr (exp, target, tmode, modifier)
&& (TREE_CODE (binary_op) == PLUS_EXPR && (TREE_CODE (binary_op) == PLUS_EXPR
|| TREE_CODE (binary_op) == MINUS_EXPR || TREE_CODE (binary_op) == MINUS_EXPR
|| TREE_CODE (binary_op) == BIT_IOR_EXPR || TREE_CODE (binary_op) == BIT_IOR_EXPR
|| TREE_CODE (binary_op) == BIT_XOR_EXPR || TREE_CODE (binary_op) == BIT_XOR_EXPR)
|| TREE_CODE (binary_op) == BIT_AND_EXPR)
&& integer_onep (TREE_OPERAND (binary_op, 1)) && integer_onep (TREE_OPERAND (binary_op, 1))
&& TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
{ {
@ -5507,8 +5592,7 @@ expand_expr (exp, target, tmode, modifier)
optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab
: TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab
: TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
: TREE_CODE (binary_op) == BIT_XOR_EXPR ? xor_optab : xor_optab);
: and_optab);
/* If we had X ? A : A + 1, do this as A + (X == 0). /* If we had X ? A : A + 1, do this as A + (X == 0).
@ -5732,7 +5816,8 @@ expand_expr (exp, target, tmode, modifier)
left_cleanups = integer_zero_node; left_cleanups = integer_zero_node;
if (! right_cleanups) if (! right_cleanups)
right_cleanups = integer_zero_node; right_cleanups = integer_zero_node;
new_cleanups = build (COND_EXPR, void_type_node, cond, new_cleanups = build (COND_EXPR, void_type_node,
truthvalue_conversion (cond),
left_cleanups, right_cleanups); left_cleanups, right_cleanups);
new_cleanups = fold (new_cleanups); new_cleanups = fold (new_cleanups);
@ -5969,7 +6054,10 @@ expand_expr (exp, target, tmode, modifier)
op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
op0); op0);
else if (GET_CODE (op0) == MEM) else if (GET_CODE (op0) == MEM)
temp = XEXP (op0, 0); {
mark_temp_addr_taken (op0);
temp = XEXP (op0, 0);
}
else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
|| GET_CODE (op0) == CONCAT) || GET_CODE (op0) == CONCAT)
@ -5982,6 +6070,7 @@ expand_expr (exp, target, tmode, modifier)
= assign_stack_temp (inner_mode, = assign_stack_temp (inner_mode,
int_size_in_bytes (inner_type), 1); int_size_in_bytes (inner_type), 1);
mark_temp_addr_taken (memloc);
emit_move_insn (memloc, op0); emit_move_insn (memloc, op0);
op0 = memloc; op0 = memloc;
} }
@ -6055,6 +6144,7 @@ expand_expr (exp, target, tmode, modifier)
case CONJ_EXPR: case CONJ_EXPR:
{ {
enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
rtx imag_t; rtx imag_t;
rtx insns; rtx insns;
@ -6066,11 +6156,12 @@ expand_expr (exp, target, tmode, modifier)
start_sequence (); start_sequence ();
/* Store the realpart and the negated imagpart to target. */ /* Store the realpart and the negated imagpart to target. */
emit_move_insn (gen_realpart (mode, target), gen_realpart (mode, op0)); emit_move_insn (gen_realpart (partmode, target),
gen_realpart (partmode, op0));
imag_t = gen_imagpart (mode, target); imag_t = gen_imagpart (partmode, target);
temp = expand_unop (mode, neg_optab, temp = expand_unop (partmode, neg_optab,
gen_imagpart (mode, op0), imag_t, 0); gen_imagpart (partmode, op0), imag_t, 0);
if (temp != imag_t) if (temp != imag_t)
emit_move_insn (imag_t, temp); emit_move_insn (imag_t, temp);
@ -6836,6 +6927,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_SIN: case BUILT_IN_SIN:
case BUILT_IN_COS: case BUILT_IN_COS:
/* Treat these like sqrt, but only if the user asks for them. */
if (! flag_fast_math)
break;
case BUILT_IN_FSQRT: case BUILT_IN_FSQRT:
/* If not optimizing, call the library function. */ /* If not optimizing, call the library function. */
if (! optimize) if (! optimize)
@ -7792,7 +7886,7 @@ result_vector (savep, result)
align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
if (size % align != 0) if (size % align != 0)
size = CEIL (size, align) * align; size = CEIL (size, align) * align;
reg = gen_rtx (REG, mode, savep ? INCOMING_REGNO (regno) : regno); reg = gen_rtx (REG, mode, savep ? regno : INCOMING_REGNO (regno));
mem = change_address (result, mode, mem = change_address (result, mode,
plus_constant (XEXP (result, 0), size)); plus_constant (XEXP (result, 0), size));
savevec[nelts++] = (savep savevec[nelts++] = (savep
@ -8284,7 +8378,9 @@ preexpand_calls (exp)
/* Do nothing to built-in functions. */ /* Do nothing to built-in functions. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
|| TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL
|| ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
/* Do nothing if the call returns a variable-sized object. */
|| TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST)
CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0); CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
return; return;
@ -8371,6 +8467,7 @@ defer_cleanups_to (old_cleanups)
while (cleanups_this_call != old_cleanups) while (cleanups_this_call != old_cleanups)
{ {
(*interim_eh_hook) (TREE_VALUE (cleanups_this_call)); (*interim_eh_hook) (TREE_VALUE (cleanups_this_call));
last = cleanups_this_call;
cleanups_this_call = TREE_CHAIN (cleanups_this_call); cleanups_this_call = TREE_CHAIN (cleanups_this_call);
} }
@ -8555,17 +8652,117 @@ do_jump (exp, if_false_label, if_true_label)
break; break;
case TRUTH_ANDIF_EXPR: case TRUTH_ANDIF_EXPR:
if (if_false_label == 0) {
if_false_label = drop_through_label = gen_label_rtx (); rtx seq1, seq2;
do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX); tree cleanups, old_cleanups;
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
if (if_false_label == 0)
if_false_label = drop_through_label = gen_label_rtx ();
start_sequence ();
do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
seq1 = get_insns ();
end_sequence ();
old_cleanups = cleanups_this_call;
start_sequence ();
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
seq2 = get_insns ();
end_sequence ();
cleanups = defer_cleanups_to (old_cleanups);
if (cleanups)
{
rtx flag = gen_reg_rtx (word_mode);
tree new_cleanups;
tree cond;
/* Flag cleanups as not needed. */
emit_move_insn (flag, const0_rtx);
emit_insns (seq1);
/* Flag cleanups as needed. */
emit_move_insn (flag, const1_rtx);
emit_insns (seq2);
/* convert flag, which is an rtx, into a tree. */
cond = make_node (RTL_EXPR);
TREE_TYPE (cond) = integer_type_node;
RTL_EXPR_RTL (cond) = flag;
RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
new_cleanups = build (COND_EXPR, void_type_node,
truthvalue_conversion (cond),
cleanups, integer_zero_node);
new_cleanups = fold (new_cleanups);
/* Now add in the conditionalized cleanups. */
cleanups_this_call
= tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
(*interim_eh_hook) (NULL_TREE);
}
else
{
emit_insns (seq1);
emit_insns (seq2);
}
}
break; break;
case TRUTH_ORIF_EXPR: case TRUTH_ORIF_EXPR:
if (if_true_label == 0) {
if_true_label = drop_through_label = gen_label_rtx (); rtx seq1, seq2;
do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label); tree cleanups, old_cleanups;
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
if (if_true_label == 0)
if_true_label = drop_through_label = gen_label_rtx ();
start_sequence ();
do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
seq1 = get_insns ();
end_sequence ();
old_cleanups = cleanups_this_call;
start_sequence ();
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
seq2 = get_insns ();
end_sequence ();
cleanups = defer_cleanups_to (old_cleanups);
if (cleanups)
{
rtx flag = gen_reg_rtx (word_mode);
tree new_cleanups;
tree cond;
/* Flag cleanups as not needed. */
emit_move_insn (flag, const0_rtx);
emit_insns (seq1);
/* Flag cleanups as needed. */
emit_move_insn (flag, const1_rtx);
emit_insns (seq2);
/* convert flag, which is an rtx, into a tree. */
cond = make_node (RTL_EXPR);
TREE_TYPE (cond) = integer_type_node;
RTL_EXPR_RTL (cond) = flag;
RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
new_cleanups = build (COND_EXPR, void_type_node,
truthvalue_conversion (cond),
cleanups, integer_zero_node);
new_cleanups = fold (new_cleanups);
/* Now add in the conditionalized cleanups. */
cleanups_this_call
= tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
(*interim_eh_hook) (NULL_TREE);
}
else
{
emit_insns (seq1);
emit_insns (seq2);
}
}
break; break;
case COMPOUND_EXPR: case COMPOUND_EXPR:
@ -8980,9 +9177,6 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
rtx prev = get_last_insn (); rtx prev = get_last_insn ();
rtx branch = 0; rtx branch = 0;
if (prev != 0)
prev = PREV_INSN (prev);
/* Output the branch with the opposite condition. Then try to invert /* Output the branch with the opposite condition. Then try to invert
what is generated. If more than one insn is a branch, or if the what is generated. If more than one insn is a branch, or if the
branch is not the last insn written, abort. If we can't invert branch is not the last insn written, abort. If we can't invert
@ -8990,20 +9184,23 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
emit a jump to the false label and define the true label. */ emit a jump to the false label and define the true label. */
if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_false_label)); emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])(if_false_label));
else else
abort (); abort ();
/* Here we get the insn before what was just emitted. /* Here we get the first insn that was just emitted. It used to be the
On some machines, emitting the branch can discard case that, on some machines, emitting the branch would discard
the previous compare insn and emit a replacement. */ the previous compare insn and emit a replacement. This isn't
done anymore, but abort if we see that PREV is deleted. */
if (prev == 0) if (prev == 0)
/* If there's only one preceding insn... */
insn = get_insns (); insn = get_insns ();
else if (INSN_DELETED_P (prev))
abort ();
else else
insn = NEXT_INSN (prev); insn = NEXT_INSN (prev);
for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) for (; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == JUMP_INSN) if (GET_CODE (insn) == JUMP_INSN)
{ {
if (branch) if (branch)

View file

@ -824,9 +824,13 @@ asm_insn_count (body)
char *template; char *template;
int count = 1; int count = 1;
for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR, if (GET_CODE (body) == ASM_INPUT)
NULL_PTR, NULL_PTR); template = XSTR (body, 0);
*template; template++) else
template = decode_asm_operands (body, NULL_PTR, NULL_PTR,
NULL_PTR, NULL_PTR);
for ( ; *template; template++)
if (IS_ASM_LOGICAL_LINE_SEPARATOR(*template) || *template == '\n') if (IS_ASM_LOGICAL_LINE_SEPARATOR(*template) || *template == '\n')
count++; count++;
@ -953,18 +957,14 @@ static void
profile_function (file) profile_function (file)
FILE *file; FILE *file;
{ {
#ifndef NO_PROFILE_DATA
int align = MIN (BIGGEST_ALIGNMENT, POINTER_SIZE); int align = MIN (BIGGEST_ALIGNMENT, POINTER_SIZE);
#endif /* not NO_PROFILE_DATA */
int sval = current_function_returns_struct; int sval = current_function_returns_struct;
int cxt = current_function_needs_context; int cxt = current_function_needs_context;
#ifndef NO_PROFILE_DATA
data_section (); data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
#endif /* not NO_PROFILE_DATA */
text_section (); text_section ();

View file

@ -177,6 +177,12 @@ int *reg_basic_block;
int *reg_n_refs; int *reg_n_refs;
/* Indexed by N; says whether a psuedo register N was ever used
within a SUBREG that changes the size of the reg. Some machines prohibit
such objects to be in certain (usually floating-point) registers. */
char *reg_changes_size;
/* Indexed by N, gives number of places register N dies. /* Indexed by N, gives number of places register N dies.
This information remains valid for the rest of the compilation This information remains valid for the rest of the compilation
of the current function; it is used to control register allocation. */ of the current function; it is used to control register allocation. */
@ -602,6 +608,20 @@ find_basic_blocks (f, nonlocal_label_list)
} }
} }
/* ??? See if we have a "live" basic block that is not reachable.
This can happen if it is headed by a label that is preserved or
in one of the label lists, but no call or computed jump is in
the loop. It's not clear if we can delete the block or not,
but don't for now. However, we will mess up register status if
it remains unreachable, so add a fake reachability from the
previous block. */
for (i = 1; i < n_basic_blocks; i++)
if (block_live[i] && ! basic_block_drops_in[i]
&& GET_CODE (basic_block_head[i]) == CODE_LABEL
&& LABEL_REFS (basic_block_head[i]) == basic_block_head[i])
basic_block_drops_in[i] = 1;
/* Now delete the code for any basic blocks that can't be reached. /* Now delete the code for any basic blocks that can't be reached.
They can occur because jump_optimize does not recognize They can occur because jump_optimize does not recognize
unreachable loops as unreachable. */ unreachable loops as unreachable. */
@ -1055,18 +1075,18 @@ life_analysis (f, nregs)
{ {
register rtx jump, head; register rtx jump, head;
/* Update the basic_block_new_live_at_end's of the block /* Update the basic_block_new_live_at_end's of the block
that falls through into this one (if any). */ that falls through into this one (if any). */
head = basic_block_head[i]; head = basic_block_head[i];
jump = PREV_INSN (head);
if (basic_block_drops_in[i]) if (basic_block_drops_in[i])
{ {
register int from_block = BLOCK_NUM (jump);
register int j; register int j;
for (j = 0; j < regset_size; j++) for (j = 0; j < regset_size; j++)
basic_block_new_live_at_end[from_block][j] basic_block_new_live_at_end[i-1][j]
|= basic_block_live_at_start[i][j]; |= basic_block_live_at_start[i][j];
} }
/* Update the basic_block_new_live_at_end's of /* Update the basic_block_new_live_at_end's of
all the blocks that jump to this one. */ all the blocks that jump to this one. */
if (GET_CODE (head) == CODE_LABEL) if (GET_CODE (head) == CODE_LABEL)
@ -1183,6 +1203,9 @@ allocate_for_life_analysis ()
reg_n_deaths = (short *) oballoc (max_regno * sizeof (short)); reg_n_deaths = (short *) oballoc (max_regno * sizeof (short));
bzero ((char *) reg_n_deaths, max_regno * sizeof (short)); bzero ((char *) reg_n_deaths, max_regno * sizeof (short));
reg_changes_size = (char *) oballoc (max_regno * sizeof (char));
bzero (reg_changes_size, max_regno * sizeof (char));;
reg_live_length = (int *) oballoc (max_regno * sizeof (int)); reg_live_length = (int *) oballoc (max_regno * sizeof (int));
bzero ((char *) reg_live_length, max_regno * sizeof (int)); bzero ((char *) reg_live_length, max_regno * sizeof (int));
@ -1512,11 +1535,11 @@ propagate_block (old, first, last, final, significant, bnum)
/* Calls may also reference any of the global registers, /* Calls may also reference any of the global registers,
so they are made live. */ so they are made live. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i]) if (global_regs[i])
live[i / REGSET_ELT_BITS] mark_used_regs (old, live,
|= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)); gen_rtx (REG, reg_raw_mode[i], i),
final, insn);
/* Calls also clobber memory. */ /* Calls also clobber memory. */
last_mem_set = 0; last_mem_set = 0;
@ -2081,11 +2104,21 @@ find_auto_inc (needed, x, insn)
&& (use = find_use_as_address (PATTERN (insn), addr, offset), && (use = find_use_as_address (PATTERN (insn), addr, offset),
use != 0 && use != (rtx) 1)) use != 0 && use != (rtx) 1))
{ {
int win = 0;
rtx q = SET_DEST (set); rtx q = SET_DEST (set);
enum rtx_code inc_code = (INTVAL (XEXP (y, 1)) == size
? (offset ? PRE_INC : POST_INC)
: (offset ? PRE_DEC : POST_DEC));
if (dead_or_set_p (incr, addr)) if (dead_or_set_p (incr, addr))
win = 1; {
/* This is the simple case. Try to make the auto-inc. If
we can't, we are done. Otherwise, we will do any
needed updates below. */
if (! validate_change (insn, &XEXP (x, 0),
gen_rtx (inc_code, Pmode, addr),
0))
return;
}
else if (GET_CODE (q) == REG else if (GET_CODE (q) == REG
/* PREV_INSN used here to check the semi-open interval /* PREV_INSN used here to check the semi-open interval
[insn,incr). */ [insn,incr). */
@ -2113,14 +2146,25 @@ find_auto_inc (needed, x, insn)
BLOCK_NUM (temp) = BLOCK_NUM (insn); BLOCK_NUM (temp) = BLOCK_NUM (insn);
} }
/* If we can't make the auto-inc, or can't make the
replacement into Y, exit. There's no point in making
the change below if we can't do the auto-inc and doing
so is not correct in the pre-inc case. */
validate_change (insn, &XEXP (x, 0),
gen_rtx (inc_code, Pmode, q),
1);
validate_change (incr, &XEXP (y, 0), q, 1);
if (! apply_change_group ())
return;
/* We now know we'll be doing this change, so emit the
new insn(s) and do the updates. */
emit_insns_before (insns, insn); emit_insns_before (insns, insn);
if (basic_block_head[BLOCK_NUM (insn)] == insn) if (basic_block_head[BLOCK_NUM (insn)] == insn)
basic_block_head[BLOCK_NUM (insn)] = insns; basic_block_head[BLOCK_NUM (insn)] = insns;
XEXP (x, 0) = q;
XEXP (y, 0) = q;
/* INCR will become a NOTE and INSN won't contain a /* INCR will become a NOTE and INSN won't contain a
use of ADDR. If a use of ADDR was just placed in use of ADDR. If a use of ADDR was just placed in
the insn before INSN, make that the next use. the insn before INSN, make that the next use.
@ -2134,7 +2178,6 @@ find_auto_inc (needed, x, insn)
addr = q; addr = q;
regno = REGNO (q); regno = REGNO (q);
win = 1;
/* REGNO is now used in INCR which is below INSN, but /* REGNO is now used in INCR which is below INSN, but
it previously wasn't live here. If we don't mark it previously wasn't live here. If we don't mark
@ -2150,46 +2193,38 @@ find_auto_inc (needed, x, insn)
reg_n_calls_crossed[regno]++; reg_n_calls_crossed[regno]++;
} }
if (win /* If we haven't returned, it means we were able to make the
/* If we have found a suitable auto-increment, do auto-inc, so update the status. First, record that this insn
POST_INC around the register here, and patch out the has an implicit side effect. */
increment instruction that follows. */
&& validate_change (insn, &XEXP (x, 0), REG_NOTES (insn)
gen_rtx ((INTVAL (XEXP (y, 1)) == size = gen_rtx (EXPR_LIST, REG_INC, addr, REG_NOTES (insn));
? (offset ? PRE_INC : POST_INC)
: (offset ? PRE_DEC : POST_DEC)), /* Modify the old increment-insn to simply copy
Pmode, addr), 0)) the already-incremented value of our register. */
if (! validate_change (incr, &SET_SRC (set), addr, 0))
abort ();
/* If that makes it a no-op (copying the register into itself) delete
it so it won't appear to be a "use" and a "set" of this
register. */
if (SET_DEST (set) == addr)
{ {
/* Record that this insn has an implicit side effect. */ PUT_CODE (incr, NOTE);
REG_NOTES (insn) NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
= gen_rtx (EXPR_LIST, REG_INC, addr, REG_NOTES (insn)); NOTE_SOURCE_FILE (incr) = 0;
}
/* Modify the old increment-insn to simply copy if (regno >= FIRST_PSEUDO_REGISTER)
the already-incremented value of our register. */ {
SET_SRC (set) = addr; /* Count an extra reference to the reg. When a reg is
/* Indicate insn must be re-recognized. */ incremented, spilling it is worse, so we want to make
INSN_CODE (incr) = -1; that less likely. */
reg_n_refs[regno] += loop_depth;
/* If that makes it a no-op (copying the register into itself) /* Count the increment as a setting of the register,
then delete it so it won't appear to be a "use" and a "set" even though it isn't a SET in rtl. */
of this register. */ reg_n_sets[regno]++;
if (SET_DEST (set) == addr)
{
PUT_CODE (incr, NOTE);
NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (incr) = 0;
}
if (regno >= FIRST_PSEUDO_REGISTER)
{
/* Count an extra reference to the reg. When a reg is
incremented, spilling it is worse, so we want to make
that less likely. */
reg_n_refs[regno] += loop_depth;
/* Count the increment as a setting of the register,
even though it isn't a SET in rtl. */
reg_n_sets[regno]++;
}
} }
} }
} }
@ -2257,6 +2292,20 @@ mark_used_regs (needed, live, x, final, insn)
#endif #endif
break; break;
case SUBREG:
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (x))
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
&& (INTEGRAL_MODE_P (GET_MODE (x))
|| INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (x)))))
reg_changes_size[REGNO (SUBREG_REG (x))] = 1;
/* While we're here, optimize this case. */
x = SUBREG_REG (x);
/* ... fall through ... */
case REG: case REG:
/* See a register other than being set /* See a register other than being set
=> mark it as needed. */ => mark it as needed. */
@ -2368,6 +2417,16 @@ mark_used_regs (needed, live, x, final, insn)
#endif #endif
) )
{ {
/* Check for the case where the register dying partially
overlaps the register set by this insn. */
if (regno < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
{
int n = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (--n >= 0)
some_needed |= dead_or_set_regno_p (insn, regno + n);
}
/* If none of the words in X is needed, make a REG_DEAD /* If none of the words in X is needed, make a REG_DEAD
note. Otherwise, we must make partial REG_DEAD notes. */ note. Otherwise, we must make partial REG_DEAD notes. */
if (! some_needed) if (! some_needed)

View file

@ -2836,12 +2836,14 @@ fold_truthop (code, truth_type, lhs, rhs)
l_const = convert (unsigned_type (TREE_TYPE (l_const)), l_const); l_const = convert (unsigned_type (TREE_TYPE (l_const)), l_const);
l_const = const_binop (LSHIFT_EXPR, convert (type, l_const), l_const = const_binop (LSHIFT_EXPR, convert (type, l_const),
size_int (xll_bitpos), 0); size_int (xll_bitpos), 0);
l_const = const_binop (BIT_AND_EXPR, l_const, ll_mask, 0);
} }
if (r_const) if (r_const)
{ {
r_const = convert (unsigned_type (TREE_TYPE (r_const)), r_const); r_const = convert (unsigned_type (TREE_TYPE (r_const)), r_const);
r_const = const_binop (LSHIFT_EXPR, convert (type, r_const), r_const = const_binop (LSHIFT_EXPR, convert (type, r_const),
size_int (xrl_bitpos), 0); size_int (xrl_bitpos), 0);
r_const = const_binop (BIT_AND_EXPR, r_const, rl_mask, 0);
} }
/* If the right sides are not constant, do the same for it. Also, /* If the right sides are not constant, do the same for it. Also,
@ -3420,6 +3422,15 @@ fold (expr)
return t; return t;
#endif /* 0 */ #endif /* 0 */
case COMPONENT_REF:
if (TREE_CODE (arg0) == CONSTRUCTOR)
{
tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
if (m)
t = TREE_VALUE (m);
}
return t;
case RANGE_EXPR: case RANGE_EXPR:
TREE_CONSTANT (t) = wins; TREE_CONSTANT (t) = wins;
return t; return t;
@ -3733,8 +3744,8 @@ fold (expr)
Also note that operand_equal_p is always false if an operand Also note that operand_equal_p is always false if an operand
is volatile. */ is volatile. */
if (operand_equal_p (arg0, arg1, if ((! FLOAT_TYPE_P (type) || flag_fast_math)
FLOAT_TYPE_P (type) && ! flag_fast_math)) && operand_equal_p (arg0, arg1, 0))
return convert (type, integer_zero_node); return convert (type, integer_zero_node);
goto associate; goto associate;

View file

@ -152,9 +152,8 @@ int current_function_args_size;
int current_function_pretend_args_size; int current_function_pretend_args_size;
/* # of bytes of outgoing arguments required to be pushed by the prologue. /* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
If this is non-zero, it means that ACCUMULATE_OUTGOING_ARGS was defined defined, the needed space is pushed by the prologue. */
and no stack adjusts will be done on function calls. */
int current_function_outgoing_args_size; int current_function_outgoing_args_size;
@ -356,6 +355,8 @@ struct temp_slot
tree rtl_expr; tree rtl_expr;
/* Non-zero if this temporary is currently in use. */ /* Non-zero if this temporary is currently in use. */
char in_use; char in_use;
/* Non-zero if this temporary has its address taken. */
char addr_taken;
/* Nesting level at which this slot is being used. */ /* Nesting level at which this slot is being used. */
int level; int level;
/* Non-zero if this should survive a call to free_temp_slots. */ /* Non-zero if this should survive a call to free_temp_slots. */
@ -461,7 +462,8 @@ find_function_data (decl)
since this function knows only about language-independent variables. */ since this function knows only about language-independent variables. */
void void
push_function_context () push_function_context_to (toplevel)
int toplevel;
{ {
struct function *p = (struct function *) xmalloc (sizeof (struct function)); struct function *p = (struct function *) xmalloc (sizeof (struct function));
@ -512,7 +514,7 @@ push_function_context ()
p->fixup_var_refs_queue = 0; p->fixup_var_refs_queue = 0;
p->epilogue_delay_list = current_function_epilogue_delay_list; p->epilogue_delay_list = current_function_epilogue_delay_list;
save_tree_status (p); save_tree_status (p, toplevel);
save_storage_status (p); save_storage_status (p);
save_emit_status (p); save_emit_status (p);
init_emit (); init_emit ();
@ -524,11 +526,18 @@ push_function_context ()
(*save_machine_status) (p); (*save_machine_status) (p);
} }
void
push_function_context ()
{
push_function_context_to (0);
}
/* Restore the last saved context, at the end of a nested function. /* Restore the last saved context, at the end of a nested function.
This function is called from language-specific code. */ This function is called from language-specific code. */
void void
pop_function_context () pop_function_context_from (toplevel)
int toplevel;
{ {
struct function *p = outer_function_chain; struct function *p = outer_function_chain;
@ -545,7 +554,8 @@ pop_function_context ()
current_function_calls_alloca = p->calls_alloca; current_function_calls_alloca = p->calls_alloca;
current_function_has_nonlocal_label = p->has_nonlocal_label; current_function_has_nonlocal_label = p->has_nonlocal_label;
current_function_has_nonlocal_goto = p->has_nonlocal_goto; current_function_has_nonlocal_goto = p->has_nonlocal_goto;
current_function_contains_functions = 1; if (! toplevel)
current_function_contains_functions = 1;
current_function_args_size = p->args_size; current_function_args_size = p->args_size;
current_function_pretend_args_size = p->pretend_args_size; current_function_pretend_args_size = p->pretend_args_size;
current_function_arg_offset_rtx = p->arg_offset_rtx; current_function_arg_offset_rtx = p->arg_offset_rtx;
@ -577,8 +587,9 @@ pop_function_context ()
temp_slots = p->temp_slots; temp_slots = p->temp_slots;
temp_slot_level = p->temp_slot_level; temp_slot_level = p->temp_slot_level;
current_function_epilogue_delay_list = p->epilogue_delay_list; current_function_epilogue_delay_list = p->epilogue_delay_list;
reg_renumber = 0;
restore_tree_status (p); restore_tree_status (p, toplevel);
restore_storage_status (p); restore_storage_status (p);
restore_expr_status (p); restore_expr_status (p);
restore_emit_status (p); restore_emit_status (p);
@ -602,6 +613,11 @@ pop_function_context ()
rtx_equal_function_value_matters = 1; rtx_equal_function_value_matters = 1;
virtuals_instantiated = 0; virtuals_instantiated = 0;
} }
void pop_function_context ()
{
pop_function_context_from (0);
}
/* Allocate fixed slots in the stack frame of the current function. */ /* Allocate fixed slots in the stack frame of the current function. */
@ -784,6 +800,11 @@ assign_stack_temp (mode, size, keep)
{ {
struct temp_slot *p, *best_p = 0; struct temp_slot *p, *best_p = 0;
/* If SIZE is -1 it means that somebody tried to allocate a temporary
of a variable size. */
if (size == -1)
abort ();
/* First try to find an available, already-allocated temporary that is the /* First try to find an available, already-allocated temporary that is the
exact size we require. */ exact size we require. */
for (p = temp_slots; p; p = p->next) for (p = temp_slots; p; p = p->next)
@ -812,7 +833,7 @@ assign_stack_temp (mode, size, keep)
if (best_p->size - rounded_size >= alignment) if (best_p->size - rounded_size >= alignment)
{ {
p = (struct temp_slot *) oballoc (sizeof (struct temp_slot)); p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
p->in_use = 0; p->in_use = p->addr_taken = 0;
p->size = best_p->size - rounded_size; p->size = best_p->size - rounded_size;
p->slot = gen_rtx (MEM, BLKmode, p->slot = gen_rtx (MEM, BLKmode,
plus_constant (XEXP (best_p->slot, 0), plus_constant (XEXP (best_p->slot, 0),
@ -845,7 +866,9 @@ assign_stack_temp (mode, size, keep)
} }
p->in_use = 1; p->in_use = 1;
p->addr_taken = 0;
p->rtl_expr = sequence_rtl_expr; p->rtl_expr = sequence_rtl_expr;
if (keep == 2) if (keep == 2)
{ {
p->level = target_temp_slot_level; p->level = target_temp_slot_level;
@ -969,6 +992,28 @@ update_temp_slot_address (old, new)
} }
} }
/* If X could be a reference to a temporary slot, mark the fact that its
adddress was taken. */
void
mark_temp_addr_taken (x)
rtx x;
{
struct temp_slot *p;
if (x == 0)
return;
/* If X is not in memory or is at a constant address, it cannot be in
a temporary slot. */
if (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
return;
p = find_temp_slot_from_address (XEXP (x, 0));
if (p != 0)
p->addr_taken = 1;
}
/* If X could be a reference to a temporary slot, mark that slot as belonging /* If X could be a reference to a temporary slot, mark that slot as belonging
to the to one level higher. If X matched one of our slots, just mark that to the to one level higher. If X matched one of our slots, just mark that
one. Otherwise, we can't easily predict which it is, so upgrade all of one. Otherwise, we can't easily predict which it is, so upgrade all of
@ -981,31 +1026,52 @@ void
preserve_temp_slots (x) preserve_temp_slots (x)
rtx x; rtx x;
{ {
struct temp_slot *p; struct temp_slot *p = 0;
/* If there is no result, we still might have some objects whose address
were taken, so we need to make sure they stay around. */
if (x == 0) if (x == 0)
return; {
for (p = temp_slots; p; p = p->next)
if (p->in_use && p->level == temp_slot_level && p->addr_taken)
p->level--;
return;
}
/* If X is a register that is being used as a pointer, see if we have /* If X is a register that is being used as a pointer, see if we have
a temporary slot we know it points to. To be consistent with a temporary slot we know it points to. To be consistent with
the code below, we really should preserve all non-kept slots the code below, we really should preserve all non-kept slots
if we can't find a match, but that seems to be much too costly. */ if we can't find a match, but that seems to be much too costly. */
if (GET_CODE (x) == REG && REGNO_POINTER_FLAG (REGNO (x)) if (GET_CODE (x) == REG && REGNO_POINTER_FLAG (REGNO (x)))
&& (p = find_temp_slot_from_address (x)) != 0) p = find_temp_slot_from_address (x);
/* If X is not in memory or is at a constant address, it cannot be in
a temporary slot, but it can contain something whose address was
taken. */
if (p == 0 && (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0))))
{ {
p->level--; for (p = temp_slots; p; p = p->next)
if (p->in_use && p->level == temp_slot_level && p->addr_taken)
p->level--;
return; return;
} }
/* If X is not in memory or is at a constant address, it cannot be in
a temporary slot. */
if (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
return;
/* First see if we can find a match. */ /* First see if we can find a match. */
p = find_temp_slot_from_address (XEXP (x, 0)); if (p == 0)
p = find_temp_slot_from_address (XEXP (x, 0));
if (p != 0) if (p != 0)
{ {
/* Move everything at our level whose address was taken to our new
level in case we used its address. */
struct temp_slot *q;
for (q = temp_slots; q; q = q->next)
if (q != p && q->addr_taken && q->level == p->level)
q->level--;
p->level--; p->level--;
return; return;
} }
@ -2191,6 +2257,8 @@ optimize_bit_field (body, insn, equiv_mem)
and then for which byte of the word is wanted. */ and then for which byte of the word is wanted. */
register int offset = INTVAL (XEXP (bitfield, 2)); register int offset = INTVAL (XEXP (bitfield, 2));
rtx insns;
/* Adjust OFFSET to count bits from low-address byte. */ /* Adjust OFFSET to count bits from low-address byte. */
#if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN
offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0))) offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
@ -2209,8 +2277,12 @@ optimize_bit_field (body, insn, equiv_mem)
#endif #endif
} }
memref = change_address (memref, mode, start_sequence ();
memref = change_address (memref, mode,
plus_constant (XEXP (memref, 0), offset)); plus_constant (XEXP (memref, 0), offset));
insns = get_insns ();
end_sequence ();
emit_insns_before (insns, insn);
/* Store this memory reference where /* Store this memory reference where
we found the bit field reference. */ we found the bit field reference. */
@ -3150,6 +3222,13 @@ assign_parms (fndecl, second_time)
continue; continue;
} }
/* If the parm is to be passed as a transparent union, use the
type of the first field for the tests below. We have already
verified that the modes are the same. */
if (DECL_TRANSPARENT_UNION (parm)
|| TYPE_TRANSPARENT_UNION (passed_type))
passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
/* See if this arg was passed by invisible reference. It is if /* See if this arg was passed by invisible reference. It is if
it is an object whose size depends on the contents of the it is an object whose size depends on the contents of the
object itself or if the machine requires these objects be passed object itself or if the machine requires these objects be passed
@ -3426,6 +3505,9 @@ assign_parms (fndecl, second_time)
else if (PARM_BOUNDARY % BITS_PER_WORD != 0) else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
abort (); abort ();
if (TREE_READONLY (parm))
RTX_UNCHANGING_P (stack_parm) = 1;
move_block_from_reg (REGNO (entry_parm), move_block_from_reg (REGNO (entry_parm),
validize_mem (stack_parm), validize_mem (stack_parm),
size_stored / UNITS_PER_WORD, size_stored / UNITS_PER_WORD,
@ -4251,7 +4333,9 @@ trampoline_address (function)
/* Find an existing trampoline and return it. */ /* Find an existing trampoline and return it. */
for (link = trampoline_list; link; link = TREE_CHAIN (link)) for (link = trampoline_list; link; link = TREE_CHAIN (link))
if (TREE_PURPOSE (link) == function) if (TREE_PURPOSE (link) == function)
return XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0); return
round_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0));
for (fp = outer_function_chain; fp; fp = fp->next) for (fp = outer_function_chain; fp; fp = fp->next)
for (link = fp->trampoline_list; link; link = TREE_CHAIN (link)) for (link = fp->trampoline_list; link; link = TREE_CHAIN (link))
if (TREE_PURPOSE (link) == function) if (TREE_PURPOSE (link) == function)
@ -4693,6 +4777,11 @@ mark_varargs ()
/* Expand a call to __main at the beginning of a possible main function. */ /* Expand a call to __main at the beginning of a possible main function. */
#if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
#undef HAS_INIT_SECTION
#define HAS_INIT_SECTION
#endif
void void
expand_main_function () expand_main_function ()
{ {
@ -4700,10 +4789,10 @@ expand_main_function ()
{ {
/* The zero below avoids a possible parse error */ /* The zero below avoids a possible parse error */
0; 0;
#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main) #if !defined (HAS_INIT_SECTION)
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0, emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0,
VOIDmode, 0); VOIDmode, 0);
#endif /* not INIT_SECTION_ASM_OP or INVOKE__main */ #endif /* not HAS_INIT_SECTION */
} }
} }
@ -4858,7 +4947,7 @@ expand_function_start (subr, parms_have_cleanups)
if (aggregate_value_p (DECL_RESULT (subr))) if (aggregate_value_p (DECL_RESULT (subr)))
{ {
/* Returning something that won't go in a register. */ /* Returning something that won't go in a register. */
register rtx value_address; register rtx value_address = 0;
#ifdef PCC_STATIC_STRUCT_RETURN #ifdef PCC_STATIC_STRUCT_RETURN
if (current_function_returns_pcc_struct) if (current_function_returns_pcc_struct)
@ -4965,11 +5054,23 @@ expand_function_start (subr, parms_have_cleanups)
/* Fetch static chain values for containing functions. */ /* Fetch static chain values for containing functions. */
tem = decl_function_context (current_function_decl); tem = decl_function_context (current_function_decl);
/* If not doing stupid register allocation, then start off with the static /* If not doing stupid register allocation copy the static chain
chain pointer in a pseudo register. Otherwise, we use the stack pointer into a psuedo. If we have small register classes, copy the
address that was generated above. */ value from memory if static_chain_incoming_rtx is a REG. If we do
stupid register allocation, we use the stack address generated above. */
if (tem && ! obey_regdecls) if (tem && ! obey_regdecls)
last_ptr = copy_to_reg (static_chain_incoming_rtx); {
#ifdef SMALL_REGISTER_CLASSES
/* If the static chain originally came in a register, put it back
there, then move it out in the next insn. The reason for
this peculiar code is to satisfy function integration. */
if (GET_CODE (static_chain_incoming_rtx) == REG)
emit_move_insn (static_chain_incoming_rtx, last_ptr);
#endif
last_ptr = copy_to_reg (static_chain_incoming_rtx);
}
context_display = 0; context_display = 0;
while (tem) while (tem)
{ {
@ -5036,7 +5137,9 @@ expand_function_end (filename, line, end_bindings)
on a machine that fails to restore the registers. */ on a machine that fails to restore the registers. */
if (NON_SAVING_SETJMP && current_function_calls_setjmp) if (NON_SAVING_SETJMP && current_function_calls_setjmp)
{ {
setjmp_protect (DECL_INITIAL (current_function_decl)); if (DECL_INITIAL (current_function_decl) != error_mark_node)
setjmp_protect (DECL_INITIAL (current_function_decl));
setjmp_protect_args (); setjmp_protect_args ();
} }
#endif #endif

View file

@ -14,16 +14,23 @@ extern int errno;
BSD systems) now provides getcwd as called for by POSIX. Allow for BSD systems) now provides getcwd as called for by POSIX. Allow for
the few exceptions to the general rule here. */ the few exceptions to the general rule here. */
#if !(defined (POSIX) || defined (USG) || defined (VMS)) #if !(defined (POSIX) || defined (USG) || defined (VMS)) || defined (HAVE_GETWD)
#include <sys/param.h> #include <sys/param.h>
extern char *getwd (); extern char *getwd ();
#define getcwd(buf,len) getwd(buf) #define getcwd(buf,len) getwd(buf)
#ifdef MAXPATHLEN
#define GUESSPATHLEN (MAXPATHLEN + 1) #define GUESSPATHLEN (MAXPATHLEN + 1)
#else
#define GUESSPATHLEN 100
#endif
#else /* (defined (USG) || defined (VMS)) */ #else /* (defined (USG) || defined (VMS)) */
extern char *getcwd (); extern char *getcwd ();
/* We actually use this as a starting point, not a limit. */ /* We actually use this as a starting point, not a limit. */
#define GUESSPATHLEN 100 #define GUESSPATHLEN 100
#endif /* (defined (USG) || defined (VMS)) */ #endif /* (defined (USG) || defined (VMS)) */
#ifdef WINNT
#include <direct.h>
#endif
char *getenv (); char *getenv ();
char *xmalloc (); char *xmalloc ();

View file

@ -446,6 +446,18 @@ global_alloc (file)
if (regs_ever_live[i]) if (regs_ever_live[i])
local_reg_n_refs[i] = 0; local_reg_n_refs[i] = 0;
/* Likewise for regs used in a SCRATCH. */
for (i = 0; i < scratch_list_length; i++)
if (scratch_list[i])
{
int regno = REGNO (scratch_list[i]);
int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch_list[i]));
int j;
for (j = regno; j < lim; j++)
local_reg_n_refs[j] = 0;
}
/* Allocate the space for the conflict and preference tables and /* Allocate the space for the conflict and preference tables and
initialize them. */ initialize them. */
@ -923,6 +935,12 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
IOR_HARD_REG_SET (used1, hard_reg_conflicts[allocno]); IOR_HARD_REG_SET (used1, hard_reg_conflicts[allocno]);
#ifdef CLASS_CANNOT_CHANGE_SIZE
if (reg_changes_size[allocno_reg[allocno]])
IOR_HARD_REG_SET (used1,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
/* Try each hard reg to see if it fits. Do this in two passes. /* Try each hard reg to see if it fits. Do this in two passes.
In the first pass, skip registers that are preferred by some other pseudo In the first pass, skip registers that are preferred by some other pseudo
to give it a better chance of getting one of those registers. Only if to give it a better chance of getting one of those registers. Only if
@ -1097,27 +1115,42 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
/* Don't use a reg no good for this pseudo. */ /* Don't use a reg no good for this pseudo. */
&& ! TEST_HARD_REG_BIT (used2, regno) && ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode) && HARD_REGNO_MODE_OK (regno, mode)
&& (((double) local_reg_n_refs[regno] #ifdef CLASS_CANNOT_CHANGE_SIZE
/ local_reg_live_length[regno]) && ! (reg_changes_size[allocno_reg[allocno]]
< ((double) allocno_n_refs[allocno] && (TEST_HARD_REG_BIT
/ allocno_live_length[allocno]))) (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
regno)))
#endif
)
{ {
/* Hard reg REGNO was used less in total by local regs /* We explicitly evaluate the divide results into temporary
than it would be used by this one allocno! */ variables so as to avoid excess precision problems that occur
int k; on a i386-unknown-sysv4.2 (unixware) host. */
for (k = 0; k < max_regno; k++)
if (reg_renumber[k] >= 0) double tmp1 = ((double) local_reg_n_refs[regno]
{ / local_reg_live_length[regno]);
int r = reg_renumber[k]; double tmp2 = ((double) allocno_n_refs[allocno]
int endregno / allocno_live_length[allocno]);
= r + HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (k));
if (regno >= r && regno < endregno) if (tmp1 < tmp2)
reg_renumber[k] = -1; {
} /* Hard reg REGNO was used less in total by local regs
than it would be used by this one allocno! */
int k;
for (k = 0; k < max_regno; k++)
if (reg_renumber[k] >= 0)
{
int r = reg_renumber[k];
int endregno
= r + HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (k));
best_reg = regno; if (regno >= r && regno < endregno)
break; reg_renumber[k] = -1;
}
best_reg = regno;
break;
}
} }
} }
} }

View file

@ -659,6 +659,15 @@ gen_movsi (operand0, operand1)
if (flag_pic && SYMBOLIC_CONST (operands[1])) if (flag_pic && SYMBOLIC_CONST (operands[1]))
emit_pic_move (operands, SImode); emit_pic_move (operands, SImode);
/* Don't generate memory->memory moves, go through a register */
else if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
operands[1] = force_reg (SImode, operands[1]);
}
} }
operand0 = operands[0]; operand0 = operands[0];
operand1 = operands[1]; operand1 = operands[1];
@ -677,9 +686,32 @@ gen_movhi (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
return gen_rtx (SET, VOIDmode, rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
operands[1] = force_reg (HImode, operands[1]);
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
operand0, operand0,
operand1); operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
} }
rtx rtx
@ -687,16 +719,156 @@ gen_movstricthi (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
return gen_rtx (SET, VOIDmode, rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
operands[1] = force_reg (HImode, operands[1]);
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
gen_rtx (STRICT_LOW_PART, VOIDmode, gen_rtx (STRICT_LOW_PART, VOIDmode,
operand0), operand0),
operand1); operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
} }
rtx rtx
gen_movqi (operand0, operand1) gen_movqi (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{
rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
operands[1] = force_reg (QImode, operands[1]);
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_movstrictqi (operand0, operand1)
rtx operand0;
rtx operand1;
{
rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
operands[1] = force_reg (QImode, operands[1]);
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
gen_rtx (STRICT_LOW_PART, VOIDmode,
operand0),
operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_movsf (operand0, operand1)
rtx operand0;
rtx operand1;
{
rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Special case memory->memory moves and pushes */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode)))
{
rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode))
? gen_movsf_push
: gen_movsf_mem;
emit_insn ((*genfunc) (operands[0], operands[1]));
DONE;
}
/* If we are loading a floating point constant that isn't 0 or 1 into a register,
indicate we need the pic register loaded. This could be optimized into stores
of constants if the target eventually moves to memory, but better safe than
sorry. */
if (flag_pic
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
current_function_uses_pic_offset_table = 1;
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_movsf_push_nomove (operand0, operand1)
rtx operand0;
rtx operand1;
{ {
return gen_rtx (SET, VOIDmode, return gen_rtx (SET, VOIDmode,
operand0, operand0,
@ -704,18 +876,147 @@ gen_movqi (operand0, operand1)
} }
rtx rtx
gen_movstrictqi (operand0, operand1) gen_movsf_push (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movsf_mem (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movsf_normal (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
return gen_rtx (SET, VOIDmode, return gen_rtx (SET, VOIDmode,
gen_rtx (STRICT_LOW_PART, VOIDmode, operand0,
operand0),
operand1); operand1);
} }
rtx rtx
gen_movsf (operand0, operand1) gen_swapsf (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (SET, VOIDmode,
operand1,
operand0)));
}
rtx
gen_movdf (operand0, operand1)
rtx operand0;
rtx operand1;
{
rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Special case memory->memory moves and pushes */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode)))
{
rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode))
? gen_movdf_push
: gen_movdf_mem;
emit_insn ((*genfunc) (operands[0], operands[1]));
DONE;
}
/* If we are loading a floating point constant that isn't 0 or 1 into a register,
indicate we need the pic register loaded. This could be optimized into stores
of constants if the target eventually moves to memory, but better safe than
sorry. */
if (flag_pic
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
current_function_uses_pic_offset_table = 1;
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_movdf_push_nomove (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (SET, VOIDmode,
operand0,
operand1);
}
rtx
gen_movdf_push (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movdf_mem (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movdf_normal (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
@ -739,7 +1040,97 @@ gen_swapdf (operand0, operand1)
} }
rtx rtx
gen_movdf (operand0, operand1) gen_movxf (operand0, operand1)
rtx operand0;
rtx operand1;
{
rtx operands[2];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
/* Special case memory->memory moves and pushes */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode)))
{
rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode))
? gen_movxf_push
: gen_movxf_mem;
emit_insn ((*genfunc) (operands[0], operands[1]));
DONE;
}
/* If we are loading a floating point constant that isn't 0 or 1 into a register,
indicate we need the pic register loaded. This could be optimized into stores
of constants if the target eventually moves to memory, but better safe than
sorry. */
if (flag_pic
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
current_function_uses_pic_offset_table = 1;
}
}
operand0 = operands[0];
operand1 = operands[1];
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
operand1));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_movxf_push_nomove (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (SET, VOIDmode,
operand0,
operand1);
}
rtx
gen_movxf_push (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movxf_mem (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
gen_rtx (SET, VOIDmode,
operand0,
operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_movxf_normal (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
@ -762,24 +1153,19 @@ gen_swapxf (operand0, operand1)
operand0))); operand0)));
} }
rtx
gen_movxf (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (SET, VOIDmode,
operand0,
operand1);
}
rtx rtx
gen_movdi (operand0, operand1) gen_movdi (operand0, operand1)
rtx operand0; rtx operand0;
rtx operand1; rtx operand1;
{ {
return gen_rtx (SET, VOIDmode, return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
gen_rtx (SET, VOIDmode,
operand0, operand0,
operand1); operand1),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
} }
rtx rtx
@ -1477,11 +1863,14 @@ gen_adddi3 (operand0, operand1, operand2)
rtx operand1; rtx operand1;
rtx operand2; rtx operand2;
{ {
return gen_rtx (SET, VOIDmode, return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0, operand0,
gen_rtx (PLUS, DImode, gen_rtx (PLUS, DImode,
operand1, operand1,
operand2)); operand2)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
} }
rtx rtx
@ -1523,6 +1912,16 @@ gen_addqi3 (operand0, operand1, operand2)
operand2)); operand2));
} }
rtx
gen_movsi_lea (operand0, operand1)
rtx operand0;
rtx operand1;
{
return gen_rtx (SET, VOIDmode,
operand0,
operand1);
}
rtx rtx
gen_addxf3 (operand0, operand1, operand2) gen_addxf3 (operand0, operand1, operand2)
rtx operand0; rtx operand0;
@ -1568,11 +1967,14 @@ gen_subdi3 (operand0, operand1, operand2)
rtx operand1; rtx operand1;
rtx operand2; rtx operand2;
{ {
return gen_rtx (SET, VOIDmode, return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0, operand0,
gen_rtx (MINUS, DImode, gen_rtx (MINUS, DImode,
operand1, operand1,
operand2)); operand2)),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
} }
rtx rtx
@ -1739,6 +2141,48 @@ gen_mulsidi3 (operand0, operand1, operand2)
operand2))); operand2)));
} }
rtx
gen_umulsi3_highpart (operand0, operand1, operand2)
rtx operand0;
rtx operand1;
rtx operand2;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0,
gen_rtx (TRUNCATE, SImode,
gen_rtx (LSHIFTRT, DImode,
gen_rtx (MULT, DImode,
gen_rtx (ZERO_EXTEND, DImode,
operand1),
gen_rtx (ZERO_EXTEND, DImode,
operand2)),
GEN_INT (32)))),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx
gen_smulsi3_highpart (operand0, operand1, operand2)
rtx operand0;
rtx operand1;
rtx operand2;
{
return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
gen_rtx (SET, VOIDmode,
operand0,
gen_rtx (TRUNCATE, SImode,
gen_rtx (LSHIFTRT, DImode,
gen_rtx (MULT, DImode,
gen_rtx (SIGN_EXTEND, DImode,
operand1),
gen_rtx (SIGN_EXTEND, DImode,
operand2)),
GEN_INT (32)))),
gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0))));
}
rtx rtx
gen_mulxf3 (operand0, operand1, operand2) gen_mulxf3 (operand0, operand1, operand2)
rtx operand0; rtx operand0;
@ -3554,21 +3998,23 @@ gen_untyped_call (operand0, operand1, operand2)
operands[2] = operand2; operands[2] = operand2;
{ {
rtx addr; int i;
if (flag_pic) emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
current_function_uses_pic_offset_table = 1;
/* With half-pic, force the address into a register. */ for (i = 0; i < XVECLEN (operands[2], 0); i++)
addr = XEXP (operands[0], 0); {
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) rtx set = XVECEXP (operands[2], 0, i);
XEXP (operands[0], 0) = force_reg (Pmode, addr); emit_move_insn (SET_DEST (set), SET_SRC (set));
}
operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); /* The optimizer does not know that the call sets the function value
if (! expander_call_insn_operand (operands[1], QImode)) registers we stored in the result block. We avoid problems by
operands[1] claiming that all hard registers are used and clobbered at this
= change_address (operands[1], VOIDmode, point. */
copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); emit_insn (gen_blockage ());
DONE;
} }
operand0 = operands[0]; operand0 = operands[0];
operand1 = operands[1]; operand1 = operands[1];
@ -3588,59 +4034,11 @@ gen_untyped_call (operand0, operand1, operand2)
} }
rtx rtx
gen_untyped_return (operand0, operand1) gen_blockage ()
rtx operand0;
rtx operand1;
{ {
rtx operands[2]; return gen_rtx (UNSPEC_VOLATILE, VOIDmode,
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
{
rtx valreg1 = gen_rtx (REG, SImode, 0);
rtx valreg2 = gen_rtx (REG, SImode, 1);
rtx result = operands[0];
/* Restore the FPU state. */
emit_insn (gen_update_return (change_address (result, SImode,
plus_constant (XEXP (result, 0),
8))));
/* Reload the function value registers. */
emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0)));
emit_move_insn (valreg2,
change_address (result, SImode,
plus_constant (XEXP (result, 0), 4)));
/* Put USE insns before the return. */
emit_insn (gen_rtx (USE, VOIDmode, valreg1));
emit_insn (gen_rtx (USE, VOIDmode, valreg2));
/* Construct the return. */
expand_null_return ();
DONE;
}
operand0 = operands[0];
operand1 = operands[1];
emit (operand0);
emit (operand1);
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}
rtx
gen_update_return (operand0)
rtx operand0;
{
return gen_rtx (UNSPEC, SImode,
gen_rtvec (1, gen_rtvec (1,
operand0), const0_rtx),
0); 0);
} }
@ -3916,25 +4314,43 @@ add_clobbers (pattern, insn_code_number)
switch (insn_code_number) switch (insn_code_number)
{ {
case 264: case 114:
XVECEXP (pattern, 0, 1) = gen_rtx (CLOBBER, VOIDmode, case 113:
gen_rtx (SCRATCH, SImode, 0)); case 112:
break;
case 95:
case 94:
case 93:
XVECEXP (pattern, 0, 3) = gen_rtx (CLOBBER, VOIDmode, XVECEXP (pattern, 0, 3) = gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)); gen_rtx (SCRATCH, SImode, 0));
break; break;
case 89: case 108:
case 88: case 107:
case 87: case 106:
XVECEXP (pattern, 0, 4) = gen_rtx (CLOBBER, VOIDmode, XVECEXP (pattern, 0, 4) = gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0)); gen_rtx (SCRATCH, SImode, 0));
break; break;
case 84:
case 83:
case 80:
case 79:
case 74:
case 73:
XVECEXP (pattern, 0, 1) = gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0));
XVECEXP (pattern, 0, 2) = gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0));
break;
case 285:
case 151:
case 150:
case 135:
case 127:
case 68:
case 67:
XVECEXP (pattern, 0, 1) = gen_rtx (CLOBBER, VOIDmode,
gen_rtx (SCRATCH, SImode, 0));
break;
case 33: case 33:
case 32: case 32:
case 31: case 31:

View file

@ -9,12 +9,6 @@ extern rtx recog_operand[];
extern rtx *recog_operand_loc[]; extern rtx *recog_operand_loc[];
extern rtx *recog_dup_loc[]; extern rtx *recog_dup_loc[];
extern char recog_dup_num[]; extern char recog_dup_num[];
extern
#ifdef __GNUC__
__volatile__
#endif
void fatal_insn_not_found ();
void void
insn_extract (insn) insn_extract (insn)
rtx insn; rtx insn;
@ -27,7 +21,7 @@ insn_extract (insn)
case -1: case -1:
fatal_insn_not_found (insn); fatal_insn_not_found (insn);
case 308: case 326:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0, 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0, 0), 0));
ro[2] = *(ro_loc[2] = &XVECEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0, 1)); ro[2] = *(ro_loc[2] = &XVECEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0, 1));
@ -36,38 +30,38 @@ insn_extract (insn)
recog_dup_num[0] = 1; recog_dup_num[0] = 1;
break; break;
case 306: case 324:
case 303: case 321:
case 302: case 320:
case 300: case 318:
case 299: case 317:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 0));
ro[3] = *(ro_loc[3] = &XEXP (pat, 1)); ro[3] = *(ro_loc[3] = &XEXP (pat, 1));
break; break;
case 305: case 323:
case 301: case 319:
case 298: case 316:
case 297: case 315:
case 295: case 313:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1));
ro[3] = *(ro_loc[3] = &XEXP (pat, 1)); ro[3] = *(ro_loc[3] = &XEXP (pat, 1));
break; break;
case 304: case 322:
case 296: case 314:
case 294: case 312:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1));
ro[3] = *(ro_loc[3] = &XEXP (pat, 1)); ro[3] = *(ro_loc[3] = &XEXP (pat, 1));
break; break;
case 289: case 307:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
@ -80,7 +74,7 @@ insn_extract (insn)
recog_dup_num[2] = 0; recog_dup_num[2] = 0;
break; break;
case 288: case 306:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0));
@ -94,7 +88,7 @@ insn_extract (insn)
recog_dup_num[2] = 1; recog_dup_num[2] = 1;
break; break;
case 286: case 304:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
@ -106,33 +100,18 @@ insn_extract (insn)
recog_dup_num[1] = 0; recog_dup_num[1] = 0;
break; break;
case 284: case 302:
case 283: case 301:
case 300:
break; break;
case 282: case 298:
ro[0] = *(ro_loc[0] = &XVECEXP (pat, 0, 0));
break;
case 280:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0));
ro[1] = *(ro_loc[1] = &XVECEXP (pat, 0, 1));
ro[2] = *(ro_loc[2] = &XVECEXP (pat, 0, 2));
break;
case 279:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XVECEXP (pat, 0, 1));
ro[2] = *(ro_loc[2] = &XVECEXP (pat, 0, 2));
break;
case 277:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1));
break; break;
case 274: case 295:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1));
@ -141,7 +120,7 @@ insn_extract (insn)
ro[4] = *(ro_loc[4] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1)); ro[4] = *(ro_loc[4] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1));
break; break;
case 273: case 294:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1));
@ -150,7 +129,7 @@ insn_extract (insn)
ro[4] = *(ro_loc[4] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1)); ro[4] = *(ro_loc[4] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1));
break; break;
case 268: case 289:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1));
ro[2] = const0_rtx; ro[2] = const0_rtx;
@ -158,7 +137,7 @@ insn_extract (insn)
ro[3] = *(ro_loc[3] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1)); ro[3] = *(ro_loc[3] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1));
break; break;
case 267: case 288:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1));
ro[2] = const0_rtx; ro[2] = const0_rtx;
@ -166,85 +145,85 @@ insn_extract (insn)
ro[3] = *(ro_loc[3] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1)); ro[3] = *(ro_loc[3] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 1), 1));
break; break;
case 265: case 286:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 1)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 1));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 1), 0), 0));
break; break;
case 264: case 285:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0), 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0), 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1), 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
break; break;
case 261: case 282:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0));
break; break;
case 260: case 281:
case 259: case 280:
case 258: case 279:
case 257: case 278:
case 256: case 277:
case 255: case 276:
case 254: case 275:
case 253: case 274:
case 252: case 273:
case 251: case 272:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (pat, 1), 2), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (pat, 1), 2), 0));
break; break;
case 250: case 271:
case 248: case 269:
case 246: case 267:
case 244: case 265:
case 242: case 263:
case 240: case 261:
case 238: case 259:
case 236: case 257:
case 234: case 255:
case 232: case 253:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (pat, 1), 1), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (XEXP (pat, 1), 1), 0));
break; break;
case 230: case 251:
case 228: case 249:
case 226: case 247:
case 224: case 245:
case 222: case 243:
case 220: case 241:
case 218: case 239:
case 216: case 237:
case 214: case 235:
case 212: case 233:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
break; break;
case 210: case 231:
case 209: case 230:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 1)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 1));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 2)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 2));
break; break;
case 208: case 229:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 1), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 2)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 2));
break; break;
case 207: case 228:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 1));
break; break;
case 206: case 227:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 1)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 1));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1));
break; break;
case 205: case 226:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 0), 0));
ro[1] = const0_rtx; ro[1] = const0_rtx;
ro_loc[1] = &junk; ro_loc[1] = &junk;
@ -252,9 +231,9 @@ insn_extract (insn)
ro[3] = *(ro_loc[3] = &XEXP (pat, 1)); ro[3] = *(ro_loc[3] = &XEXP (pat, 1));
break; break;
case 195: case 216:
case 189: case 210:
case 183: case 204:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1));
@ -262,37 +241,37 @@ insn_extract (insn)
recog_dup_num[0] = 2; recog_dup_num[0] = 2;
break; break;
case 177: case 198:
case 174: case 195:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (XEXP (pat, 1), 0, 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (XEXP (pat, 1), 0, 0), 0));
break; break;
case 176: case 197:
case 175: case 196:
case 173: case 194:
case 172: case 193:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XVECEXP (XEXP (pat, 1), 0, 0)); ro[1] = *(ro_loc[1] = &XVECEXP (XEXP (pat, 1), 0, 0));
break; break;
case 293: case 311:
case 291: case 309:
case 171: case 192:
case 170: case 191:
case 168: case 189:
case 165: case 186:
case 163: case 184:
case 160: case 181:
case 158: case 179:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0));
break; break;
case 142: case 163:
case 141: case 162:
case 140: case 161:
case 139: case 160:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1));
@ -303,65 +282,79 @@ insn_extract (insn)
recog_dup_num[1] = 2; recog_dup_num[1] = 2;
break; break;
case 130: case 151:
case 129: case 150:
case 128: ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
case 127: ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0), 1), 0));
ro[3] = *(ro_loc[3] = &XEXP (XVECEXP (pat, 0, 1), 0));
break;
case 149:
case 148:
case 147:
case 146:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (pat, 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (XEXP (pat, 1), 1), 0));
break; break;
case 276: case 297:
case 204: case 225:
case 224:
case 223:
case 222:
case 221:
case 220:
case 219:
case 218:
case 217:
case 215:
case 213:
case 212:
case 211:
case 209:
case 207:
case 206:
case 205:
case 203: case 203:
case 202: case 172:
case 201: case 171:
case 200: case 170:
case 199: case 169:
case 198: case 168:
case 197: case 167:
case 196: case 166:
case 194: case 165:
case 192: case 164:
case 191: case 156:
case 190: case 155:
case 188:
case 186:
case 185:
case 184:
case 182:
case 151:
case 150:
case 149:
case 148:
case 147:
case 146:
case 145: case 145:
case 144: case 144:
case 143: case 143:
case 135: case 142:
case 134: case 138:
case 126: case 137:
case 125: case 136:
case 124: case 130:
case 123: case 129:
case 119: case 128:
case 118:
case 117:
case 116:
case 111:
case 110:
case 109:
case 108:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1)); ro[2] = *(ro_loc[2] = &XEXP (XEXP (pat, 1), 1));
break; break;
case 95: case 135:
case 94: case 127:
case 93: ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 1));
ro[3] = *(ro_loc[3] = &XEXP (XVECEXP (pat, 0, 1), 0));
break;
case 114:
case 113:
case 112:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
@ -369,9 +362,9 @@ insn_extract (insn)
ro[4] = *(ro_loc[4] = &XEXP (XVECEXP (pat, 0, 3), 0)); ro[4] = *(ro_loc[4] = &XEXP (XVECEXP (pat, 0, 3), 0));
break; break;
case 89: case 108:
case 88: case 107:
case 87: case 106:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 2), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 2), 0));
@ -381,53 +374,66 @@ insn_extract (insn)
recog_dup_num[0] = 1; recog_dup_num[0] = 1;
break; break;
case 78: case 97:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
break; break;
case 201:
case 200:
case 199:
case 190:
case 188:
case 187:
case 185:
case 183:
case 182:
case 180: case 180:
case 179:
case 178: case 178:
case 169: case 177:
case 167: case 176:
case 166: case 175:
case 164: case 174:
case 162: case 173:
case 161: case 126:
case 159: case 125:
case 157: case 124:
case 156: case 123:
case 155: case 122:
case 154: case 121:
case 153: case 99:
case 152: case 98:
case 107: case 95:
case 106: case 94:
case 105: case 93:
case 104: case 92:
case 103: case 91:
case 102: case 90:
case 80: case 89:
case 79: case 88:
case 76: case 87:
case 75: case 86:
case 74: case 85:
case 73:
case 72:
case 71:
case 70:
case 69:
case 68:
case 67:
case 66:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XEXP (pat, 1), 0));
break; break;
case 62: case 84:
case 59: case 83:
case 80:
case 79:
case 74:
case 73:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
ro[3] = *(ro_loc[3] = &XEXP (XVECEXP (pat, 0, 2), 0));
break;
case 82:
case 76:
case 70:
ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1));
recog_dup_loc[0] = &XEXP (XVECEXP (pat, 0, 1), 0); recog_dup_loc[0] = &XEXP (XVECEXP (pat, 0, 1), 0);
@ -436,28 +442,38 @@ insn_extract (insn)
recog_dup_num[1] = 0; recog_dup_num[1] = 0;
break; break;
case 271: case 68:
case 55: case 67:
case 52: ro[0] = *(ro_loc[0] = &XEXP (XVECEXP (pat, 0, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 0), 1));
ro[2] = *(ro_loc[2] = &XEXP (XVECEXP (pat, 0, 1), 0));
break;
case 292:
case 64:
case 57:
ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 0), 0)); ro[0] = *(ro_loc[0] = &XEXP (XEXP (pat, 0), 0));
ro[1] = *(ro_loc[1] = &XEXP (pat, 1)); ro[1] = *(ro_loc[1] = &XEXP (pat, 1));
break; break;
case 270: case 291:
case 112: case 131:
case 65: case 81:
case 64: case 78:
case 63: case 75:
case 61: case 72:
case 69:
case 66:
case 62:
case 60: case 60:
case 59:
case 58: case 58:
case 57: case 55:
case 56:
case 54:
case 53: case 53:
case 52:
case 51: case 51:
case 50: case 50:
case 49: case 48:
case 47: case 47:
case 46: case 46:
ro[0] = *(ro_loc[0] = &XEXP (pat, 0)); ro[0] = *(ro_loc[0] = &XEXP (pat, 0));
@ -520,7 +536,7 @@ insn_extract (insn)
ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 1), 0)); ro[1] = *(ro_loc[1] = &XEXP (XVECEXP (pat, 0, 1), 0));
break; break;
case 262: case 283:
case 4: case 4:
case 2: case 2:
case 0: case 0:

View file

@ -109,8 +109,14 @@ init_all_optabs ()
smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3; smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3; umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3; smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3; if (HAVE_umulsidi3)
smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3; umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
if (HAVE_mulsidi3)
smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
if (HAVE_umulsi3_highpart)
umul_highpart_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulsi3_highpart;
if (HAVE_smulsi3_highpart)
smul_highpart_optab->handlers[(int) SImode].insn_code = CODE_FOR_smulsi3_highpart;
if (HAVE_mulxf3) if (HAVE_mulxf3)
smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3; smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3;
if (HAVE_muldf3) if (HAVE_muldf3)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -134,10 +134,15 @@ function_cannot_inline_p (fndecl)
if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0) if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
return "function with varying-size return value cannot be inline"; return "function with varying-size return value cannot be inline";
/* Cannot inline a function with a varying size argument. */ /* Cannot inline a function with a varying size argument or one that
receives a transparent union. */
for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms)) for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
if (int_size_in_bytes (TREE_TYPE (parms)) < 0) {
return "function with varying-size parameter cannot be inline"; if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
return "function with varying-size parameter cannot be inline";
else if (TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
return "function with transparent unit parameter cannot be inline";
}
if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns) if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
{ {
@ -1235,6 +1240,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual)); tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
/* Mode of the variable used within the function. */ /* Mode of the variable used within the function. */
enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal)); enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
int invisiref = 0;
/* Make sure this formal has some correspondence in the users code /* Make sure this formal has some correspondence in the users code
* before emitting any line notes for it. */ * before emitting any line notes for it. */
@ -1263,6 +1269,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
store_expr (arg, stack_slot, 0); store_expr (arg, stack_slot, 0);
arg_vals[i] = XEXP (stack_slot, 0); arg_vals[i] = XEXP (stack_slot, 0);
invisiref = 1;
} }
else if (GET_CODE (loc) != MEM) else if (GET_CODE (loc) != MEM)
{ {
@ -1288,8 +1295,11 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
be two different pseudos, and `safe_from_p' will make all be two different pseudos, and `safe_from_p' will make all
sorts of smart assumptions about their not conflicting. sorts of smart assumptions about their not conflicting.
But if ARG_VALS[I] overlaps TARGET, these assumptions are But if ARG_VALS[I] overlaps TARGET, these assumptions are
wrong, so put ARG_VALS[I] into a fresh register. */ wrong, so put ARG_VALS[I] into a fresh register.
Don't worry about invisible references, since their stack
temps will never overlap the target. */
|| (target != 0 || (target != 0
&& ! invisiref
&& (GET_CODE (arg_vals[i]) == REG && (GET_CODE (arg_vals[i]) == REG
|| GET_CODE (arg_vals[i]) == SUBREG || GET_CODE (arg_vals[i]) == SUBREG
|| GET_CODE (arg_vals[i]) == MEM) || GET_CODE (arg_vals[i]) == MEM)
@ -1640,7 +1650,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
for (insn = insns; insn; insn = NEXT_INSN (insn)) for (insn = insns; insn; insn = NEXT_INSN (insn))
{ {
rtx copy, pattern; rtx copy, pattern, set;
map->orig_asm_operands_vector = 0; map->orig_asm_operands_vector = 0;
@ -1648,6 +1658,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
{ {
case INSN: case INSN:
pattern = PATTERN (insn); pattern = PATTERN (insn);
set = single_set (insn);
copy = 0; copy = 0;
if (GET_CODE (pattern) == USE if (GET_CODE (pattern) == USE
&& GET_CODE (XEXP (pattern, 0)) == REG && GET_CODE (XEXP (pattern, 0)) == REG
@ -1659,33 +1670,47 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
/* Ignore setting a function value that we don't want to use. */ /* Ignore setting a function value that we don't want to use. */
if (map->inline_target == 0 if (map->inline_target == 0
&& GET_CODE (pattern) == SET && set != 0
&& GET_CODE (SET_DEST (pattern)) == REG && GET_CODE (SET_DEST (set)) == REG
&& REG_FUNCTION_VALUE_P (SET_DEST (pattern))) && REG_FUNCTION_VALUE_P (SET_DEST (set)))
{ {
if (volatile_refs_p (SET_SRC (pattern))) if (volatile_refs_p (SET_SRC (set)))
{ {
rtx new_set;
/* If we must not delete the source, /* If we must not delete the source,
load it into a new temporary. */ load it into a new temporary. */
copy = emit_insn (copy_rtx_and_substitute (pattern, map)); copy = emit_insn (copy_rtx_and_substitute (pattern, map));
SET_DEST (PATTERN (copy))
= gen_reg_rtx (GET_MODE (SET_DEST (PATTERN (copy)))); new_set = single_set (copy);
if (new_set == 0)
abort ();
SET_DEST (new_set)
= gen_reg_rtx (GET_MODE (SET_DEST (new_set)));
} }
else else
break; break;
} }
/* If this is setting the static chain rtx, omit it. */
else if (static_chain_value != 0
&& set != 0
&& GET_CODE (SET_DEST (set)) == REG
&& rtx_equal_p (SET_DEST (set),
static_chain_incoming_rtx))
break;
/* If this is setting the static chain pseudo, set it from /* If this is setting the static chain pseudo, set it from
the value we want to give it instead. */ the value we want to give it instead. */
else if (static_chain_value != 0 else if (static_chain_value != 0
&& GET_CODE (pattern) == SET && set != 0
&& rtx_equal_p (SET_SRC (pattern), && rtx_equal_p (SET_SRC (set),
static_chain_incoming_rtx)) static_chain_incoming_rtx))
{ {
rtx newdest = copy_rtx_and_substitute (SET_DEST (pattern), map); rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map);
copy = emit_insn (gen_rtx (SET, VOIDmode, newdest,
static_chain_value));
copy = emit_move_insn (newdest, static_chain_value);
static_chain_value = 0; static_chain_value = 0;
} }
else else
@ -2585,6 +2610,9 @@ subst_constants (loc, insn, map)
/* If storing a recognizable value save it for later recording. */ /* If storing a recognizable value save it for later recording. */
if ((map->num_sets < MAX_RECOG_OPERANDS) if ((map->num_sets < MAX_RECOG_OPERANDS)
&& (CONSTANT_P (src) && (CONSTANT_P (src)
|| (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_VIRTUAL_REGISTER
&& REGNO (src) <= LAST_VIRTUAL_REGISTER)
|| (GET_CODE (src) == PLUS || (GET_CODE (src) == PLUS
&& GET_CODE (XEXP (src, 0)) == REG && GET_CODE (XEXP (src, 0)) == REG
&& REGNO (XEXP (src, 0)) >= FIRST_VIRTUAL_REGISTER && REGNO (XEXP (src, 0)) >= FIRST_VIRTUAL_REGISTER

View file

@ -661,6 +661,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
/* Detect jump to following insn. */ /* Detect jump to following insn. */
if (reallabelprev == insn && condjump_p (insn)) if (reallabelprev == insn && condjump_p (insn))
{ {
next = next_real_insn (JUMP_LABEL (insn));
delete_jump (insn); delete_jump (insn);
changed = 1; changed = 1;
continue; continue;
@ -2202,11 +2203,11 @@ duplicate_loop_exit_test (loop_start)
emit_barrier_before (loop_start); emit_barrier_before (loop_start);
} }
delete_insn (next_nonnote_insn (loop_start));
/* Mark the exit code as the virtual top of the converted loop. */ /* Mark the exit code as the virtual top of the converted loop. */
emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode); emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
delete_insn (next_nonnote_insn (loop_start));
return 1; return 1;
} }

View file

@ -165,6 +165,11 @@ static enum reg_class *qty_alternate_class;
static rtx *qty_scratch_rtx; static rtx *qty_scratch_rtx;
/* Element Q is nonzero if this quantity has been used in a SUBREG
that changes its size. */
static char *qty_changes_size;
/* Element Q is the register number of one pseudo register whose /* Element Q is the register number of one pseudo register whose
reg_qty value is Q, or -1 is this quantity is for a SCRATCH. This reg_qty value is Q, or -1 is this quantity is for a SCRATCH. This
register should be the head of the chain maintained in reg_next_in_qty. */ register should be the head of the chain maintained in reg_next_in_qty. */
@ -289,6 +294,7 @@ alloc_qty (regno, mode, size, birth)
qty_min_class[qty] = reg_preferred_class (regno); qty_min_class[qty] = reg_preferred_class (regno);
qty_alternate_class[qty] = reg_alternate_class (regno); qty_alternate_class[qty] = reg_alternate_class (regno);
qty_n_refs[qty] = reg_n_refs[regno]; qty_n_refs[qty] = reg_n_refs[regno];
qty_changes_size[qty] = reg_changes_size[regno];
} }
/* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx /* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx
@ -378,6 +384,7 @@ alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
qty_min_class[qty] = class; qty_min_class[qty] = class;
qty_alternate_class[qty] = NO_REGS; qty_alternate_class[qty] = NO_REGS;
qty_n_refs[qty] = 1; qty_n_refs[qty] = 1;
qty_changes_size[qty] = 0;
} }
/* Main entry point of this file. */ /* Main entry point of this file. */
@ -439,6 +446,7 @@ local_alloc ()
qty_alternate_class qty_alternate_class
= (enum reg_class *) alloca (max_qty * sizeof (enum reg_class)); = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
qty_n_refs = (int *) alloca (max_qty * sizeof (int)); qty_n_refs = (int *) alloca (max_qty * sizeof (int));
qty_changes_size = (char *) alloca (max_qty * sizeof (char));
reg_qty = (int *) alloca (max_regno * sizeof (int)); reg_qty = (int *) alloca (max_regno * sizeof (int));
reg_offset = (char *) alloca (max_regno * sizeof (char)); reg_offset = (char *) alloca (max_regno * sizeof (char));
@ -1925,6 +1933,9 @@ update_qty_class (qty, reg)
rclass = reg_alternate_class (reg); rclass = reg_alternate_class (reg);
if (reg_class_subset_p (rclass, qty_alternate_class[qty])) if (reg_class_subset_p (rclass, qty_alternate_class[qty]))
qty_alternate_class[qty] = rclass; qty_alternate_class[qty] = rclass;
if (reg_changes_size[reg])
qty_changes_size[qty] = 1;
} }
/* Handle something which alters the value of an rtx REG. /* Handle something which alters the value of an rtx REG.
@ -2108,6 +2119,12 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM); SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
#endif #endif
#ifdef CLASS_CANNOT_CHANGE_SIZE
if (qty_changes_size[qty])
IOR_HARD_REG_SET (used,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
/* Normally, the registers that can be used for the first register in /* Normally, the registers that can be used for the first register in
a multi-register quantity are the same as those that can be used for a multi-register quantity are the same as those that can be used for
subsequent registers. However, if just trying suggested registers, subsequent registers. However, if just trying suggested registers,

View file

@ -1791,8 +1791,9 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* Because the USAGE information potentially /* Because the USAGE information potentially
contains objects other than hard registers contains objects other than hard registers
we need to copy it. */ we need to copy it. */
CALL_INSN_FUNCTION_USAGE (i1) = if (CALL_INSN_FUNCTION_USAGE (temp))
copy_rtx (CALL_INSN_FUNCTION_USAGE (temp)); CALL_INSN_FUNCTION_USAGE (i1) =
copy_rtx (CALL_INSN_FUNCTION_USAGE (temp));
} }
else else
i1 = emit_insn_before (body, loop_start); i1 = emit_insn_before (body, loop_start);
@ -1834,8 +1835,9 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* Because the USAGE information potentially /* Because the USAGE information potentially
contains objects other than hard registers contains objects other than hard registers
we need to copy it. */ we need to copy it. */
CALL_INSN_FUNCTION_USAGE (i1) = if (CALL_INSN_FUNCTION_USAGE (p))
copy_rtx (CALL_INSN_FUNCTION_USAGE (p)); CALL_INSN_FUNCTION_USAGE (i1) =
copy_rtx (CALL_INSN_FUNCTION_USAGE (p));
} }
else else
i1 = emit_insn_before (PATTERN (p), loop_start); i1 = emit_insn_before (PATTERN (p), loop_start);

View file

@ -31,7 +31,7 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
#define POINTER void * #define POINTER void *
#else #else
#define POINTER char * #define POINTER char *
@ -267,7 +267,7 @@ _obstack_newchunk (h, length)
This is here for debugging. This is here for debugging.
If you use it in a program, you are probably losing. */ If you use it in a program, you are probably losing. */
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in /* Suppress -Wmissing-prototypes warning. We don't want to declare this in
obstack.h because it is just for debugging. */ obstack.h because it is just for debugging. */
int _obstack_allocated_p (struct obstack *h, POINTER obj); int _obstack_allocated_p (struct obstack *h, POINTER obj);
@ -374,7 +374,7 @@ obstack_free (h, obj)
/* Now define the functional versions of the obstack macros. /* Now define the functional versions of the obstack macros.
Define them to simply use the corresponding macros to do the job. */ Define them to simply use the corresponding macros to do the job. */
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
/* These function definitions do not work with non-ANSI preprocessors; /* These function definitions do not work with non-ANSI preprocessors;
they won't pass through the macro names in parentheses. */ they won't pass through the macro names in parentheses. */

View file

@ -117,6 +117,13 @@ rtx bcmp_libfunc;
rtx memset_libfunc; rtx memset_libfunc;
rtx bzero_libfunc; rtx bzero_libfunc;
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
rtx gthf2_libfunc;
rtx gehf2_libfunc;
rtx lthf2_libfunc;
rtx lehf2_libfunc;
rtx eqsf2_libfunc; rtx eqsf2_libfunc;
rtx nesf2_libfunc; rtx nesf2_libfunc;
rtx gtsf2_libfunc; rtx gtsf2_libfunc;
@ -689,13 +696,6 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (carries == 0) if (carries == 0)
inter = 0; inter = 0;
else else
inter = expand_binop (word_mode, binoptab, outof_input,
op1, outof_target, unsignedp, next_methods);
if (inter != 0 && inter != outof_target)
emit_move_insn (outof_target, inter);
if (inter != 0)
inter = expand_binop (word_mode, unsigned_shift, into_input, inter = expand_binop (word_mode, unsigned_shift, into_input,
op1, 0, unsignedp, next_methods); op1, 0, unsignedp, next_methods);
@ -705,6 +705,13 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (inter != 0 && inter != into_target) if (inter != 0 && inter != into_target)
emit_move_insn (into_target, inter); emit_move_insn (into_target, inter);
if (inter != 0)
inter = expand_binop (word_mode, binoptab, outof_input,
op1, outof_target, unsignedp, next_methods);
if (inter != 0 && inter != outof_target)
emit_move_insn (outof_target, inter);
} }
insns = get_insns (); insns = get_insns ();
@ -1260,8 +1267,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
NULL_RTX, unsignedp, methods); NULL_RTX, unsignedp, methods);
if (temp1 == 0 || temp2 == 0) if (temp1 == 0 || temp2 == 0)
res = expand_binop (submode, add_optab, temp1, temp2, break;
imagr, unsignedp, methods);
res = expand_binop (submode, add_optab, temp1, temp2,
imagr, unsignedp, methods);
if (res == 0) if (res == 0)
break; break;
@ -2760,7 +2769,34 @@ emit_float_lib_cmp (x, y, comparison)
enum machine_mode mode = GET_MODE (x); enum machine_mode mode = GET_MODE (x);
rtx libfunc = 0; rtx libfunc = 0;
if (mode == SFmode) if (mode == HFmode)
switch (comparison)
{
case EQ:
libfunc = eqhf2_libfunc;
break;
case NE:
libfunc = nehf2_libfunc;
break;
case GT:
libfunc = gthf2_libfunc;
break;
case GE:
libfunc = gehf2_libfunc;
break;
case LT:
libfunc = lthf2_libfunc;
break;
case LE:
libfunc = lehf2_libfunc;
break;
}
else if (mode == SFmode)
switch (comparison) switch (comparison)
{ {
case EQ: case EQ:
@ -3237,8 +3273,11 @@ expand_float (to, from, unsignedp)
expand_float (target, temp, 0); expand_float (target, temp, 0);
/* Multiply by 2 to undo the shift above. */ /* Multiply by 2 to undo the shift above. */
target = expand_binop (fmode, add_optab, target, target, temp = expand_binop (fmode, add_optab, target, target,
target, 0, OPTAB_LIB_WIDEN); target, 0, OPTAB_LIB_WIDEN);
if (temp != target)
emit_move_insn (target, temp);
do_pending_stack_adjust (); do_pending_stack_adjust ();
emit_label (label); emit_label (label);
goto done; goto done;
@ -3278,7 +3317,7 @@ expand_float (to, from, unsignedp)
} }
#endif #endif
/* No hardware instruction available; call a library rotine to convert from /* No hardware instruction available; call a library routine to convert from
SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
{ {
rtx libfcn; rtx libfcn;
@ -3562,6 +3601,7 @@ expand_fix (to, from, unsignedp)
if (libfcn) if (libfcn)
{ {
rtx insns; rtx insns;
rtx value;
to = protect_from_queue (to, 1); to = protect_from_queue (to, 1);
from = protect_from_queue (from, 0); from = protect_from_queue (from, 0);
@ -3571,12 +3611,14 @@ expand_fix (to, from, unsignedp)
start_sequence (); start_sequence ();
emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from)); value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
1, from, GET_MODE (from));
insns = get_insns (); insns = get_insns ();
end_sequence (); end_sequence ();
emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)), emit_libcall_block (insns, target, value,
gen_rtx (unsignedp ? FIX : UNSIGNED_FIX, gen_rtx (unsignedp ? UNSIGNED_FIX : FIX,
GET_MODE (to), from)); GET_MODE (to), from));
} }
@ -3957,6 +3999,13 @@ init_optabs ()
memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset"); memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero"); bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
gthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gthf2");
gehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gehf2");
lthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lthf2");
lehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lehf2");
eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2"); eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2"); nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2"); gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");

View file

@ -109,10 +109,22 @@ print_node_brief (file, prefix, node, indent)
fprintf (file, " overflow"); fprintf (file, " overflow");
if (TREE_INT_CST_HIGH (node) == 0) if (TREE_INT_CST_HIGH (node) == 0)
fprintf (file, " %1u", TREE_INT_CST_LOW (node)); fprintf (file,
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
" %1u",
#else
" %1lu",
#endif
TREE_INT_CST_LOW (node));
else if (TREE_INT_CST_HIGH (node) == -1 else if (TREE_INT_CST_HIGH (node) == -1
&& TREE_INT_CST_LOW (node) != 0) && TREE_INT_CST_LOW (node) != 0)
fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); fprintf (file,
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
" -%1u",
#else
" -%1lu",
#endif
-TREE_INT_CST_LOW (node));
else else
fprintf (file, fprintf (file,
#if HOST_BITS_PER_WIDE_INT == 64 #if HOST_BITS_PER_WIDE_INT == 64
@ -132,8 +144,24 @@ print_node_brief (file, prefix, node, indent)
} }
if (TREE_CODE (node) == REAL_CST) if (TREE_CODE (node) == REAL_CST)
{ {
#ifndef REAL_IS_NOT_DOUBLE REAL_VALUE_TYPE d;
fprintf (file, " %e", TREE_REAL_CST (node));
if (TREE_OVERFLOW (node))
fprintf (file, " overflow");
#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
else if (REAL_VALUE_ISNAN (d))
fprintf (file, " Nan");
else
{
char string[100];
REAL_VALUE_TO_DECIMAL (d, "%e", string);
fprintf (file, " %s", string);
}
#else #else
{ {
int i; int i;
@ -143,7 +171,7 @@ print_node_brief (file, prefix, node, indent)
fprintf (file, "%02x", *p++); fprintf (file, "%02x", *p++);
fprintf (file, ""); fprintf (file, "");
} }
#endif /* REAL_IS_NOT_DOUBLE */ #endif
} }
fprintf (file, ">"); fprintf (file, ">");
@ -324,22 +352,47 @@ print_node (file, prefix, node, indent)
case 'd': case 'd':
mode = DECL_MODE (node); mode = DECL_MODE (node);
if (DECL_EXTERNAL (node))
fputs (" external", file);
if (DECL_NONLOCAL (node))
fputs (" nonlocal", file);
if (DECL_REGISTER (node))
fputs (" regdecl", file);
if (DECL_INLINE (node))
fputs (" inline", file);
if (DECL_BIT_FIELD (node))
fputs (" bit-field", file);
if (DECL_VIRTUAL_P (node))
fputs (" virtual", file);
if (DECL_IGNORED_P (node)) if (DECL_IGNORED_P (node))
fputs (" ignored", file); fputs (" ignored", file);
if (DECL_ABSTRACT (node))
fputs (" abstract", file);
if (DECL_IN_SYSTEM_HEADER (node)) if (DECL_IN_SYSTEM_HEADER (node))
fputs (" in_system_header", file); fputs (" in_system_header", file);
if (DECL_COMMON (node))
fputs (" common", file);
if (DECL_EXTERNAL (node))
fputs (" external", file);
if (DECL_REGISTER (node))
fputs (" regdecl", file);
if (DECL_PACKED (node))
fputs (" packed", file);
if (DECL_NONLOCAL (node))
fputs (" nonlocal", file);
if (DECL_INLINE (node))
fputs (" inline", file);
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" supress-debug", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
fputs (" built-in", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN_NONANSI (node))
fputs (" built-in-nonansi", file);
if (TREE_CODE (node) == FIELD_DECL && DECL_BIT_FIELD (node))
fputs (" bit-field", file);
if (TREE_CODE (node) == LABEL_DECL && DECL_TOO_LATE (node))
fputs (" too-late", file);
if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
fputs (" in-text-section", file);
if (DECL_VIRTUAL_P (node))
fputs (" virtual", file);
if (DECL_DEFER_OUTPUT (node))
fputs (" defer-output", file);
if (DECL_TRANSPARENT_UNION (node))
fputs (" transparent-union", file);
if (DECL_LANG_FLAG_0 (node)) if (DECL_LANG_FLAG_0 (node))
fputs (" decl_0", file); fputs (" decl_0", file);
if (DECL_LANG_FLAG_1 (node)) if (DECL_LANG_FLAG_1 (node))
@ -413,7 +466,14 @@ print_node (file, prefix, node, indent)
case 't': case 't':
if (TYPE_NO_FORCE_BLK (node)) if (TYPE_NO_FORCE_BLK (node))
fputs (" no_force_blk", file); fputs (" no-force-blk", file);
if (TYPE_STRING_FLAG (node))
fputs (" string-flag", file);
if (TYPE_NEEDS_CONSTRUCTING (node))
fputs (" needs-constructing", file);
if (TYPE_TRANSPARENT_UNION (node))
fputs (" transparent-union", file);
if (TYPE_LANG_FLAG_0 (node)) if (TYPE_LANG_FLAG_0 (node))
fputs (" type_0", file); fputs (" type_0", file);
if (TYPE_LANG_FLAG_1 (node)) if (TYPE_LANG_FLAG_1 (node))
@ -558,10 +618,22 @@ print_node (file, prefix, node, indent)
fprintf (file, " overflow"); fprintf (file, " overflow");
if (TREE_INT_CST_HIGH (node) == 0) if (TREE_INT_CST_HIGH (node) == 0)
fprintf (file, " %1u", TREE_INT_CST_LOW (node)); fprintf (file,
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
" %1u",
#else
" %1lu",
#endif
TREE_INT_CST_LOW (node));
else if (TREE_INT_CST_HIGH (node) == -1 else if (TREE_INT_CST_HIGH (node) == -1
&& TREE_INT_CST_LOW (node) != 0) && TREE_INT_CST_LOW (node) != 0)
fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); fprintf (file,
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
" -%1u",
#else
" -%1lu",
#endif
-TREE_INT_CST_LOW (node));
else else
fprintf (file, fprintf (file,
#if HOST_BITS_PER_WIDE_INT == 64 #if HOST_BITS_PER_WIDE_INT == 64
@ -581,17 +653,36 @@ print_node (file, prefix, node, indent)
break; break;
case REAL_CST: case REAL_CST:
#ifndef REAL_IS_NOT_DOUBLE
fprintf (file, " %e", TREE_REAL_CST (node));
#else
{ {
char *p = (char *) &TREE_REAL_CST (node); REAL_VALUE_TYPE d;
fprintf (file, " 0x");
for (i = 0; i < sizeof TREE_REAL_CST (node); i++) if (TREE_OVERFLOW (node))
fprintf (file, "%02x", *p++); fprintf (file, " overflow");
fprintf (file, "");
#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
else if (REAL_VALUE_ISNAN (d))
fprintf (file, " Nan");
else
{
char string[100];
REAL_VALUE_TO_DECIMAL (d, "%e", string);
fprintf (file, " %s", string);
}
#else
{
int i;
unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
fprintf (file, " 0x");
for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
fprintf (file, "%02x", *p++);
fprintf (file, "");
}
#endif
} }
#endif /* REAL_IS_NOT_DOUBLE */
break; break;
case COMPLEX_CST: case COMPLEX_CST:

View file

@ -1718,9 +1718,9 @@ constrain_operands (insn_code_num, strict)
case 'p': case 'p':
/* p is used for address_operands. When we are called by /* p is used for address_operands. When we are called by
gen_input_reload, no one will have checked that the gen_reload, no one will have checked that the address is
address is strictly valid, i.e., that all pseudos strictly valid, i.e., that all pseudos requiring hard regs
requiring hard regs have gotten them. */ have gotten them. */
if (strict <= 0 if (strict <= 0
|| (strict_memory_address_p || (strict_memory_address_p
(insn_operand_mode[insn_code_num][opno], op))) (insn_operand_mode[insn_code_num][opno], op)))

View file

@ -1591,7 +1591,6 @@ delete_insn_for_stacker (insn)
PUT_CODE (insn, NOTE); PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0; NOTE_SOURCE_FILE (insn) = 0;
INSN_DELETED_P (insn) = 1;
} }
/* Emit an insn to pop virtual register REG before or after INSN. /* Emit an insn to pop virtual register REG before or after INSN.
@ -2581,7 +2580,7 @@ subst_stack_regs (insn, regstack)
/* subst_stack_regs_pat may have deleted a no-op insn. If so, any /* subst_stack_regs_pat may have deleted a no-op insn. If so, any
REG_UNUSED will already have been dealt with, so just return. */ REG_UNUSED will already have been dealt with, so just return. */
if (INSN_DELETED_P (insn)) if (GET_CODE (insn) == NOTE)
return; return;
/* If there is a REG_UNUSED note on a stack register on this insn, /* If there is a REG_UNUSED note on a stack register on this insn,

View file

@ -86,6 +86,7 @@ a register with any other reload. */
#define REG_OK_STRICT #define REG_OK_STRICT
#include <stdio.h>
#include "config.h" #include "config.h"
#include "rtl.h" #include "rtl.h"
#include "insn-config.h" #include "insn-config.h"
@ -777,8 +778,8 @@ push_reload (in, out, inloc, outloc, class,
a pseudo and hence will become a MEM) with M1 wider than M2 and the a pseudo and hence will become a MEM) with M1 wider than M2 and the
register is a pseudo, also reload the inside expression. register is a pseudo, also reload the inside expression.
For machines that extend byte loads, do this for any SUBREG of a pseudo For machines that extend byte loads, do this for any SUBREG of a pseudo
where both M1 and M2 are a word or smaller unless they are the same where both M1 and M2 are a word or smaller, M1 is wider than M2, and
size. M2 is an integral mode that gets extended when loaded.
Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
either M1 is not valid for R or M2 is wider than a word but we only either M1 is not valid for R or M2 is wider than a word but we only
need one word to store an M2-sized quantity in R. need one word to store an M2-sized quantity in R.
@ -792,7 +793,11 @@ push_reload (in, out, inloc, outloc, class,
STRICT_LOW_PART (presumably, in == out in the cas). STRICT_LOW_PART (presumably, in == out in the cas).
Also reload the inner expression if it does not require a secondary Also reload the inner expression if it does not require a secondary
reload but the SUBREG does. */ reload but the SUBREG does.
Finally, reload the inner expression if it is a register that is in
the class whose registers cannot be referenced in a different size
and M1 is not the same size as M2. */
if (in != 0 && GET_CODE (in) == SUBREG if (in != 0 && GET_CODE (in) == SUBREG
&& (CONSTANT_P (SUBREG_REG (in)) && (CONSTANT_P (SUBREG_REG (in))
@ -808,7 +813,9 @@ push_reload (in, out, inloc, outloc, class,
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
<= UNITS_PER_WORD) <= UNITS_PER_WORD)
&& (GET_MODE_SIZE (inmode) && (GET_MODE_SIZE (inmode)
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)
#endif #endif
)) ))
|| (GET_CODE (SUBREG_REG (in)) == REG || (GET_CODE (SUBREG_REG (in)) == REG
@ -832,6 +839,15 @@ push_reload (in, out, inloc, outloc, class,
GET_MODE (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)),
SUBREG_REG (in)) SUBREG_REG (in))
== NO_REGS)) == NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_SIZE
|| (GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
REGNO (SUBREG_REG (in))))
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
!= GET_MODE_SIZE (inmode)))
#endif #endif
)) ))
{ {
@ -885,15 +901,7 @@ push_reload (in, out, inloc, outloc, class,
&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER) && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
|| GET_CODE (SUBREG_REG (out)) == MEM) || GET_CODE (SUBREG_REG (out)) == MEM)
&& ((GET_MODE_SIZE (outmode) && ((GET_MODE_SIZE (outmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))))
#ifdef LOAD_EXTEND_OP
|| (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
<= UNITS_PER_WORD)
&& (GET_MODE_SIZE (outmode)
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))))
#endif
))
|| (GET_CODE (SUBREG_REG (out)) == REG || (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
@ -912,6 +920,15 @@ push_reload (in, out, inloc, outloc, class,
GET_MODE (SUBREG_REG (out)), GET_MODE (SUBREG_REG (out)),
SUBREG_REG (out)) SUBREG_REG (out))
== NO_REGS)) == NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_SIZE
|| (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
REGNO (SUBREG_REG (out))))
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
!= GET_MODE_SIZE (outmode)))
#endif #endif
)) ))
{ {
@ -1881,7 +1898,7 @@ operands_match_p (x, y)
int int
n_occurrences (c, s) n_occurrences (c, s)
char c; int c;
char *s; char *s;
{ {
int n = 0; int n = 0;
@ -2401,7 +2418,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
&& &SET_DEST (set) == recog_operand_loc[i]); && &SET_DEST (set) == recog_operand_loc[i]);
else if (code == PLUS) else if (code == PLUS)
/* We can get a PLUS as an "operand" as a result of /* We can get a PLUS as an "operand" as a result of
register elimination. See eliminate_regs and gen_input_reload. */ register elimination. See eliminate_regs and gen_reload. */
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, address_type[i], = find_reloads_toplev (recog_operand[i], i, address_type[i],
ind_levels, 0); ind_levels, 0);
@ -2550,12 +2567,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|| GET_CODE (operand) == PLUS || GET_CODE (operand) == PLUS
/* We must force a reload of paradoxical SUBREGs /* We must force a reload of paradoxical SUBREGs
of a MEM because the alignment of the inner value of a MEM because the alignment of the inner value
may not be enough to do the outer reference. may not be enough to do the outer reference. On
big-endian machines, it may also reference outside
the object.
On machines that extend byte operations and we have a On machines that extend byte operations and we have a
SUBREG where both the inner and outer modes are different SUBREG where both the inner and outer modes are no wider
size but no wider than a word, combine.c has made than a word and the inner mode is narrower, is integral,
assumptions about the behavior of the machine in such and gets extended when loaded from memory, combine.c has
made assumptions about the behavior of the machine in such
register access. If the data is, in fact, in memory we register access. If the data is, in fact, in memory we
must always load using the size assumed to be in the must always load using the size assumed to be in the
register and let the insn do the different-sized register and let the insn do the different-sized
@ -2567,12 +2587,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
< BIGGEST_ALIGNMENT) < BIGGEST_ALIGNMENT)
&& (GET_MODE_SIZE (operand_mode[i]) && (GET_MODE_SIZE (operand_mode[i])
> GET_MODE_SIZE (GET_MODE (operand)))) > GET_MODE_SIZE (GET_MODE (operand))))
|| (GET_CODE (operand) == MEM && BYTES_BIG_ENDIAN)
#ifdef LOAD_EXTEND_OP #ifdef LOAD_EXTEND_OP
|| (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (operand)) && (GET_MODE_SIZE (GET_MODE (operand))
<= UNITS_PER_WORD) <= UNITS_PER_WORD)
&& (GET_MODE_SIZE (operand_mode[i]) && (GET_MODE_SIZE (operand_mode[i])
!= GET_MODE_SIZE (GET_MODE (operand)))) > GET_MODE_SIZE (GET_MODE (operand)))
&& INTEGRAL_MODE_P (GET_MODE (operand))
&& LOAD_EXTEND_OP (GET_MODE (operand)) != NIL)
#endif #endif
)) ))
/* Subreg of a hard reg which can't handle the subreg's mode /* Subreg of a hard reg which can't handle the subreg's mode
@ -2708,7 +2731,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
case 'p': case 'p':
/* All necessary reloads for an address_operand /* All necessary reloads for an address_operand
were handled in find_reloads_address. */ were handled in find_reloads_address. */
this_alternative[i] = (int) ALL_REGS; this_alternative[i] = (int) BASE_REG_CLASS;
win = 1; win = 1;
break; break;
@ -4233,12 +4256,12 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
&& ! memory_address_p (mode, ad)) && ! memory_address_p (mode, ad))
{ {
*loc = ad = gen_rtx (PLUS, GET_MODE (ad), *loc = ad = gen_rtx (PLUS, GET_MODE (ad),
XEXP (XEXP (ad, 0), 0),
plus_constant (XEXP (XEXP (ad, 0), 1), plus_constant (XEXP (XEXP (ad, 0), 1),
INTVAL (XEXP (ad, 1))), INTVAL (XEXP (ad, 1))));
XEXP (XEXP (ad, 0), 0)); find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), BASE_REG_CLASS,
find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0), BASE_REG_CLASS,
GET_MODE (ad), opnum, type, ind_levels); GET_MODE (ad), opnum, type, ind_levels);
find_reloads_address_1 (XEXP (ad, 1), 1, &XEXP (ad, 1), opnum, type, 0); find_reloads_address_1 (XEXP (ad, 0), 1, &XEXP (ad, 0), opnum, type, 0);
return 1; return 1;
} }
@ -5648,3 +5671,110 @@ regno_clobbered_p (regno, insn)
return 0; return 0;
} }
static char *reload_when_needed_name[] =
{
"RELOAD_FOR_INPUT",
"RELOAD_FOR_OUTPUT",
"RELOAD_FOR_INSN",
"RELOAD_FOR_INPUT_ADDRESS",
"RELOAD_FOR_OUTPUT_ADDRESS",
"RELOAD_FOR_OPERAND_ADDRESS",
"RELOAD_FOR_OPADDR_ADDR",
"RELOAD_OTHER",
"RELOAD_FOR_OTHER_ADDRESS"
};
static char *reg_class_names[] = REG_CLASS_NAMES;
/* This function is used to print the variables set by 'find_reloads' */
void
debug_reload()
{
int r;
fprintf (stderr, "\nn_reloads = %d\n", n_reloads);
for (r = 0; r < n_reloads; r++)
{
fprintf (stderr, "\nRELOAD %d\n", r);
if (reload_in[r])
{
fprintf (stderr, "\nreload_in (%s) = ", mode_name[reload_inmode[r]]);
debug_rtx (reload_in[r]);
}
if (reload_out[r])
{
fprintf (stderr, "\nreload_out (%s) = ", mode_name[reload_outmode[r]]);
debug_rtx (reload_out[r]);
}
fprintf (stderr, "%s, ", reg_class_names[(int) reload_reg_class[r]]);
fprintf (stderr, "%s (opnum = %d)", reload_when_needed_name[(int)reload_when_needed[r]],
reload_opnum[r]);
if (reload_optional[r])
fprintf (stderr, ", optional");
if (reload_in[r])
fprintf (stderr, ", inc by %d\n", reload_inc[r]);
if (reload_nocombine[r])
fprintf (stderr, ", can combine", reload_nocombine[r]);
if (reload_secondary_p[r])
fprintf (stderr, ", secondary_reload_p");
if (reload_in_reg[r])
{
fprintf (stderr, "\nreload_in_reg:\t\t\t");
debug_rtx (reload_in_reg[r]);
}
if (reload_reg_rtx[r])
{
fprintf (stderr, "\nreload_reg_rtx:\t\t\t");
debug_rtx (reload_reg_rtx[r]);
}
if (reload_secondary_in_reload[r] != -1)
{
fprintf (stderr, "\nsecondary_in_reload = ");
fprintf (stderr, "%d ", reload_secondary_in_reload[r]);
}
if (reload_secondary_out_reload[r] != -1)
{
if (reload_secondary_in_reload[r] != -1)
fprintf (stderr, ", secondary_out_reload = ");
else
fprintf (stderr, "\nsecondary_out_reload = ");
fprintf (stderr, "%d", reload_secondary_out_reload[r]);
}
if (reload_secondary_in_icode[r] != CODE_FOR_nothing)
{
fprintf (stderr, "\nsecondary_in_icode = ");
fprintf (stderr, "%s", insn_name[r]);
}
if (reload_secondary_out_icode[r] != CODE_FOR_nothing)
{
if (reload_secondary_in_icode[r] != CODE_FOR_nothing)
fprintf (stderr, ", secondary_out_icode = ");
else
fprintf (stderr, "\nsecondary_out_icode = ");
fprintf (stderr, "%s ", insn_name[r]);
}
fprintf (stderr, "\n");
}
fprintf (stderr, "\n");
}

View file

@ -327,7 +327,7 @@ struct hard_reg_n_uses { int regno; int uses; };
static int possible_group_p PROTO((int, int *)); static int possible_group_p PROTO((int, int *));
static void count_possible_groups PROTO((int *, enum machine_mode *, static void count_possible_groups PROTO((int *, enum machine_mode *,
int *)); int *, int));
static int modes_equiv_for_class_p PROTO((enum machine_mode, static int modes_equiv_for_class_p PROTO((enum machine_mode,
enum machine_mode, enum machine_mode,
enum reg_class)); enum reg_class));
@ -1153,7 +1153,8 @@ reload (first, global, dumpfile)
if (other_mode != VOIDmode && other_mode != allocate_mode if (other_mode != VOIDmode && other_mode != allocate_mode
&& ! modes_equiv_for_class_p (allocate_mode, && ! modes_equiv_for_class_p (allocate_mode,
other_mode, class)) other_mode, class))
abort (); fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
insn);
} }
else if (size == 1) else if (size == 1)
{ {
@ -1349,19 +1350,14 @@ reload (first, global, dumpfile)
} }
/* Now count extra regs if there might be a conflict with /* Now count extra regs if there might be a conflict with
the return value register. the return value register. */
??? This is not quite correct because we don't properly
handle the case of groups, but if we end up doing
something wrong, it either will end up not mattering or
we will abort elsewhere. */
for (r = regno; r < regno + nregs; r++) for (r = regno; r < regno + nregs; r++)
if (spill_reg_order[r] >= 0) if (spill_reg_order[r] >= 0)
for (i = 0; i < N_REG_CLASSES; i++) for (i = 0; i < N_REG_CLASSES; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], r)) if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
{ {
if (basic_needs[i] > 0 || basic_groups[i] > 0) if (basic_needs[i] > 0)
{ {
enum reg_class *p; enum reg_class *p;
@ -1370,6 +1366,15 @@ reload (first, global, dumpfile)
while (*p != LIM_REG_CLASSES) while (*p != LIM_REG_CLASSES)
insn_needs.other.regs[0][(int) *p++]++; insn_needs.other.regs[0][(int) *p++]++;
} }
if (basic_groups[i] > 0)
{
enum reg_class *p;
insn_needs.other.groups[i]++;
p = reg_class_superclasses[i];
while (*p != LIM_REG_CLASSES)
insn_needs.other.groups[(int) *p++]++;
}
} }
} }
#endif /* SMALL_REGISTER_CLASSES */ #endif /* SMALL_REGISTER_CLASSES */
@ -1603,7 +1608,8 @@ reload (first, global, dumpfile)
/* If any single spilled regs happen to form groups, /* If any single spilled regs happen to form groups,
count them now. Maybe we don't really need count them now. Maybe we don't really need
to spill another group. */ to spill another group. */
count_possible_groups (group_size, group_mode, max_groups); count_possible_groups (group_size, group_mode, max_groups,
class);
if (max_groups[class] <= 0) if (max_groups[class] <= 0)
break; break;
@ -2063,68 +2069,65 @@ possible_group_p (regno, max_groups)
return 0; return 0;
} }
/* Count any groups that can be formed from the registers recently spilled. /* Count any groups of CLASS that can be formed from the registers recently
This is done class by class, in order of ascending class number. */ spilled. */
static void static void
count_possible_groups (group_size, group_mode, max_groups) count_possible_groups (group_size, group_mode, max_groups, class)
int *group_size; int *group_size;
enum machine_mode *group_mode; enum machine_mode *group_mode;
int *max_groups; int *max_groups;
int class;
{ {
int i; HARD_REG_SET new;
int i, j;
/* Now find all consecutive groups of spilled registers /* Now find all consecutive groups of spilled registers
and mark each group off against the need for such groups. and mark each group off against the need for such groups.
But don't count them against ordinary need, yet. */ But don't count them against ordinary need, yet. */
for (i = 0; i < N_REG_CLASSES; i++) if (group_size[class] == 0)
if (group_size[i] > 1) return;
CLEAR_HARD_REG_SET (new);
/* Make a mask of all the regs that are spill regs in class I. */
for (i = 0; i < n_spills; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
&& ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[i])
&& ! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
SET_HARD_REG_BIT (new, spill_regs[i]);
/* Find each consecutive group of them. */
for (i = 0; i < FIRST_PSEUDO_REGISTER && max_groups[class] > 0; i++)
if (TEST_HARD_REG_BIT (new, i)
&& i + group_size[class] <= FIRST_PSEUDO_REGISTER
&& HARD_REGNO_MODE_OK (i, group_mode[class]))
{ {
HARD_REG_SET new; for (j = 1; j < group_size[class]; j++)
int j; if (! TEST_HARD_REG_BIT (new, i + j))
break;
CLEAR_HARD_REG_SET (new); if (j == group_size[class])
{
/* We found a group. Mark it off against this class's need for
groups, and against each superclass too. */
register enum reg_class *p;
/* Make a mask of all the regs that are spill regs in class I. */ max_groups[class]--;
for (j = 0; j < n_spills; j++) p = reg_class_superclasses[class];
if (TEST_HARD_REG_BIT (reg_class_contents[i], spill_regs[j]) while (*p != LIM_REG_CLASSES)
&& ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[j]) max_groups[(int) *p++]--;
&& ! TEST_HARD_REG_BIT (counted_for_nongroups,
spill_regs[j]))
SET_HARD_REG_BIT (new, spill_regs[j]);
/* Find each consecutive group of them. */ /* Don't count these registers again. */
for (j = 0; j < FIRST_PSEUDO_REGISTER && max_groups[i] > 0; j++) for (j = 0; j < group_size[class]; j++)
if (TEST_HARD_REG_BIT (new, j) SET_HARD_REG_BIT (counted_for_groups, i + j);
&& j + group_size[i] <= FIRST_PSEUDO_REGISTER }
/* Next line in case group-mode for this class
demands an even-odd pair. */ /* Skip to the last reg in this group. When i is incremented above,
&& HARD_REGNO_MODE_OK (j, group_mode[i])) it will then point to the first reg of the next possible group. */
{ i += j - 1;
int k;
for (k = 1; k < group_size[i]; k++)
if (! TEST_HARD_REG_BIT (new, j + k))
break;
if (k == group_size[i])
{
/* We found a group. Mark it off against this class's
need for groups, and against each superclass too. */
register enum reg_class *p;
max_groups[i]--;
p = reg_class_superclasses[i];
while (*p != LIM_REG_CLASSES)
max_groups[(int) *p++]--;
/* Don't count these registers again. */
for (k = 0; k < group_size[i]; k++)
SET_HARD_REG_BIT (counted_for_groups, j + k);
}
/* Skip to the last reg in this group. When j is incremented
above, it will then point to the first reg of the next
possible group. */
j += k - 1;
}
} }
} }
/* ALLOCATE_MODE is a register mode that needs to be reloaded. OTHER_MODE is /* ALLOCATE_MODE is a register mode that needs to be reloaded. OTHER_MODE is
@ -2165,7 +2168,7 @@ spill_failure (insn)
if (asm_noperands (PATTERN (insn)) >= 0) if (asm_noperands (PATTERN (insn)) >= 0)
error_for_asm (insn, "`asm' needs too many reloads"); error_for_asm (insn, "`asm' needs too many reloads");
else else
abort (); fatal_insn ("Unable to find a register to spill.", insn);
} }
/* Add a new register to the tables of available spill-registers /* Add a new register to the tables of available spill-registers
@ -2886,11 +2889,20 @@ eliminate_regs (x, mem_mode, insn)
/* If we didn't change anything, we must retain the pseudo. */ /* If we didn't change anything, we must retain the pseudo. */
if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))]) if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))])
new = XEXP (x, 0); new = SUBREG_REG (x);
else else
/* Otherwise, ensure NEW isn't shared in case we have to reload {
it. */ /* Otherwise, ensure NEW isn't shared in case we have to reload
new = copy_rtx (new); it. */
new = copy_rtx (new);
/* In this case, we must show that the pseudo is used in this
insn so that delete_output_reload will do the right thing. */
if (insn != 0 && GET_CODE (insn) != EXPR_LIST
&& GET_CODE (insn) != INSN_LIST)
emit_insn_before (gen_rtx (USE, VOIDmode, SUBREG_REG (x)),
insn);
}
} }
else else
new = eliminate_regs (SUBREG_REG (x), mem_mode, insn); new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
@ -2907,7 +2919,11 @@ eliminate_regs (x, mem_mode, insn)
smaller. So leave the SUBREG then. */ smaller. So leave the SUBREG then. */
&& ! (GET_CODE (SUBREG_REG (x)) == REG && ! (GET_CODE (SUBREG_REG (x)) == REG
&& GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
&& GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD) && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (x))
> GET_MODE_SIZE (GET_MODE (new)))
&& INTEGRAL_MODE_P (GET_MODE (new))
&& LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
#endif #endif
) )
{ {
@ -3668,11 +3684,12 @@ order_regs_for_reload ()
} }
/* Used in reload_as_needed to sort the spilled regs. */ /* Used in reload_as_needed to sort the spilled regs. */
static int static int
compare_spill_regs (r1, r2) compare_spill_regs (r1, r2)
short *r1, *r2; short *r1, *r2;
{ {
return *r1 < *r2 ? -1: 1; return *r1 - *r2;
} }
/* Reload pseudo-registers into hard regs around each insn as needed. /* Reload pseudo-registers into hard regs around each insn as needed.
@ -3840,7 +3857,7 @@ reload_as_needed (first, live_known)
&& ! reload_optional[i] && ! reload_optional[i]
&& (reload_in[i] != 0 || reload_out[i] != 0 && (reload_in[i] != 0 || reload_out[i] != 0
|| reload_secondary_p[i] != 0)) || reload_secondary_p[i] != 0))
abort (); fatal_insn ("Non-optional registers need a spill register", insn);
/* Now compute which reload regs to reload them into. Perhaps /* Now compute which reload regs to reload them into. Perhaps
reusing reload regs from previous insns, or else output reusing reload regs from previous insns, or else output
@ -4836,7 +4853,7 @@ allocate_reload_reg (r, insn, last_reload, noerror)
failure: failure:
if (asm_noperands (PATTERN (insn)) < 0) if (asm_noperands (PATTERN (insn)) < 0)
/* It's the compiler's fault. */ /* It's the compiler's fault. */
abort (); fatal_insn ("Could not find a spill register", insn);
/* It's the user's fault; the operand's mode and constraint /* It's the user's fault; the operand's mode and constraint
don't match. Disable this reload so we don't crash in final. */ don't match. Disable this reload so we don't crash in final. */
@ -5628,7 +5645,9 @@ emit_reload_insns (insn)
{ {
register rtx old; register rtx old;
rtx oldequiv_reg = 0; rtx oldequiv_reg = 0;
rtx store_insn = 0;
if (reload_spill_index[j] >= 0)
new_spill_reg_store[reload_spill_index[j]] = 0;
old = reload_in[j]; old = reload_in[j];
if (old != 0 && ! reload_inherited[j] if (old != 0 && ! reload_inherited[j]
@ -6010,9 +6029,9 @@ emit_reload_insns (insn)
third_reload_reg))); third_reload_reg)));
} }
else else
gen_input_reload (second_reload_reg, oldequiv, gen_reload (second_reload_reg, oldequiv,
reload_opnum[j], reload_opnum[j],
reload_when_needed[j]); reload_when_needed[j]);
oldequiv = second_reload_reg; oldequiv = second_reload_reg;
} }
@ -6021,8 +6040,8 @@ emit_reload_insns (insn)
#endif #endif
if (! special && ! rtx_equal_p (reloadreg, oldequiv)) if (! special && ! rtx_equal_p (reloadreg, oldequiv))
gen_input_reload (reloadreg, oldequiv, reload_opnum[j], gen_reload (reloadreg, oldequiv, reload_opnum[j],
reload_when_needed[j]); reload_when_needed[j]);
#if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P) #if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
/* We may have to make a REG_DEAD note for the secondary reload /* We may have to make a REG_DEAD note for the secondary reload
@ -6246,7 +6265,7 @@ emit_reload_insns (insn)
/* VOIDmode should never happen for an output. */ /* VOIDmode should never happen for an output. */
if (asm_noperands (PATTERN (insn)) < 0) if (asm_noperands (PATTERN (insn)) < 0)
/* It's the compiler's fault. */ /* It's the compiler's fault. */
abort (); fatal_insn ("VOIDmode on an output", insn);
error_for_asm (insn, "output operand is constant in `asm'"); error_for_asm (insn, "output operand is constant in `asm'");
/* Prevent crash--use something we know is valid. */ /* Prevent crash--use something we know is valid. */
mode = word_mode; mode = word_mode;
@ -6259,7 +6278,7 @@ emit_reload_insns (insn)
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
/* If we need two reload regs, set RELOADREG to the intermediate /* If we need two reload regs, set RELOADREG to the intermediate
one, since it will be stored into OUT. We might need a secondary one, since it will be stored into OLD. We might need a secondary
register only for an input reload, so check again here. */ register only for an input reload, so check again here. */
if (reload_secondary_out_reload[j] >= 0) if (reload_secondary_out_reload[j] >= 0)
@ -6289,10 +6308,10 @@ emit_reload_insns (insn)
{ {
/* See if we need both a scratch and intermediate reload /* See if we need both a scratch and intermediate reload
register. */ register. */
int secondary_reload = reload_secondary_out_reload[j]; int secondary_reload = reload_secondary_out_reload[j];
enum insn_code tertiary_icode enum insn_code tertiary_icode
= reload_secondary_out_icode[secondary_reload]; = reload_secondary_out_icode[secondary_reload];
rtx pat;
if (GET_MODE (reloadreg) != mode) if (GET_MODE (reloadreg) != mode)
reloadreg = gen_rtx (REG, mode, REGNO (reloadreg)); reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
@ -6301,44 +6320,24 @@ emit_reload_insns (insn)
{ {
rtx third_reloadreg rtx third_reloadreg
= reload_reg_rtx[reload_secondary_out_reload[secondary_reload]]; = reload_reg_rtx[reload_secondary_out_reload[secondary_reload]];
pat = (GEN_FCN (tertiary_icode)
(reloadreg, second_reloadreg, third_reloadreg));
}
#ifdef SECONDARY_MEMORY_NEEDED
/* If we need a memory location to do the move, do it that way. */
else if (GET_CODE (reloadreg) == REG
&& REGNO (reloadreg) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (reloadreg)),
REGNO_REG_CLASS (REGNO (second_reloadreg)),
GET_MODE (second_reloadreg)))
{
/* Get the memory to use and rewrite both registers
to its mode. */
rtx loc
= get_secondary_mem (reloadreg,
GET_MODE (second_reloadreg),
reload_opnum[j],
reload_when_needed[j]);
rtx tmp_reloadreg;
if (GET_MODE (loc) != GET_MODE (second_reloadreg))
second_reloadreg = gen_rtx (REG, GET_MODE (loc),
REGNO (second_reloadreg));
if (GET_MODE (loc) != GET_MODE (reloadreg))
tmp_reloadreg = gen_rtx (REG, GET_MODE (loc),
REGNO (reloadreg));
else
tmp_reloadreg = reloadreg;
emit_move_insn (loc, second_reloadreg);
pat = gen_move_insn (tmp_reloadreg, loc);
}
#endif
else
pat = gen_move_insn (reloadreg, second_reloadreg);
emit_insn (pat); /* Copy primary reload reg to secondary reload reg.
(Note that these have been swapped above, then
secondary reload reg to OLD using our insn. */
gen_reload (reloadreg, second_reloadreg,
reload_opnum[j], reload_when_needed[j]);
emit_insn ((GEN_FCN (tertiary_icode)
(real_old, reloadreg, third_reloadreg)));
special = 1;
}
else
/* Copy between the reload regs here and then to
OUT later. */
gen_reload (reloadreg, second_reloadreg,
reload_opnum[j], reload_when_needed[j]);
} }
} }
} }
@ -6346,34 +6345,8 @@ emit_reload_insns (insn)
/* Output the last reload insn. */ /* Output the last reload insn. */
if (! special) if (! special)
{ gen_reload (old, reloadreg, reload_opnum[j],
#ifdef SECONDARY_MEMORY_NEEDED reload_when_needed[j]);
/* If we need a memory location to do the move, do it that way. */
if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)),
REGNO_REG_CLASS (REGNO (reloadreg)),
GET_MODE (reloadreg)))
{
/* Get the memory to use and rewrite both registers to
its mode. */
rtx loc = get_secondary_mem (old, GET_MODE (reloadreg),
reload_opnum[j],
reload_when_needed[j]);
if (GET_MODE (loc) != GET_MODE (reloadreg))
reloadreg = gen_rtx (REG, GET_MODE (loc),
REGNO (reloadreg));
if (GET_MODE (loc) != GET_MODE (old))
old = gen_rtx (REG, GET_MODE (loc), REGNO (old));
emit_insn (gen_move_insn (loc, reloadreg));
emit_insn (gen_move_insn (old, loc));
}
else
#endif
emit_insn (gen_move_insn (old, reloadreg));
}
#ifdef PRESERVE_DEATH_INFO_REGNO_P #ifdef PRESERVE_DEATH_INFO_REGNO_P
/* If final will look at death notes for this reg, /* If final will look at death notes for this reg,
@ -6408,17 +6381,14 @@ emit_reload_insns (insn)
reg_has_output_reload will make this do nothing. */ reg_has_output_reload will make this do nothing. */
note_stores (PATTERN (p), forget_old_reloads_1); note_stores (PATTERN (p), forget_old_reloads_1);
if (reg_mentioned_p (reload_reg_rtx[j], PATTERN (p))) if (reg_mentioned_p (reload_reg_rtx[j], PATTERN (p))
store_insn = p; && reload_spill_index[j] >= 0)
new_spill_reg_store[reload_spill_index[j]] = p;
} }
output_reload_insns[reload_opnum[j]] = get_insns (); output_reload_insns[reload_opnum[j]] = get_insns ();
end_sequence (); end_sequence ();
} }
if (reload_spill_index[j] >= 0)
new_spill_reg_store[reload_spill_index[j]] = store_insn;
} }
/* Now write all the insns we made for reloads in the order expected by /* Now write all the insns we made for reloads in the order expected by
@ -6640,14 +6610,15 @@ emit_reload_insns (insn)
} }
} }
/* Emit code to perform an input reload of IN to RELOADREG. IN is from /* Emit code to perform a reload from IN (which may be a reload register) to
operand OPNUM with reload type TYPE. OUT (which may also be a reload register). IN or OUT is from operand
OPNUM with reload type TYPE.
Returns first insn emitted. */ Returns first insn emitted. */
rtx rtx
gen_input_reload (reloadreg, in, opnum, type) gen_reload (out, in, opnum, type)
rtx reloadreg; rtx out;
rtx in; rtx in;
int opnum; int opnum;
enum reload_type type; enum reload_type type;
@ -6714,13 +6685,13 @@ gen_input_reload (reloadreg, in, opnum, type)
it will be A = A + B as constrain_operands expects. */ it will be A = A + B as constrain_operands expects. */
if (GET_CODE (XEXP (in, 1)) == REG if (GET_CODE (XEXP (in, 1)) == REG
&& REGNO (reloadreg) == REGNO (XEXP (in, 1))) && REGNO (out) == REGNO (XEXP (in, 1)))
tem = op0, op0 = op1, op1 = tem; tem = op0, op0 = op1, op1 = tem;
if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1)) if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1))
in = gen_rtx (PLUS, GET_MODE (in), op0, op1); in = gen_rtx (PLUS, GET_MODE (in), op0, op1);
insn = emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in)); insn = emit_insn (gen_rtx (SET, VOIDmode, out, in));
code = recog_memoized (insn); code = recog_memoized (insn);
if (code >= 0) if (code >= 0)
@ -6749,16 +6720,16 @@ gen_input_reload (reloadreg, in, opnum, type)
&& REGNO (op1) >= FIRST_PSEUDO_REGISTER)) && REGNO (op1) >= FIRST_PSEUDO_REGISTER))
tem = op0, op0 = op1, op1 = tem; tem = op0, op0 = op1, op1 = tem;
emit_insn (gen_move_insn (reloadreg, op0)); emit_insn (gen_move_insn (out, op0));
/* If OP0 and OP1 are the same, we can use RELOADREG for OP1. /* If OP0 and OP1 are the same, we can use OUT for OP1.
This fixes a problem on the 32K where the stack pointer cannot This fixes a problem on the 32K where the stack pointer cannot
be used as an operand of an add insn. */ be used as an operand of an add insn. */
if (rtx_equal_p (op0, op1)) if (rtx_equal_p (op0, op1))
op1 = reloadreg; op1 = out;
insn = emit_insn (gen_add2_insn (reloadreg, op1)); insn = emit_insn (gen_add2_insn (out, op1));
/* If that failed, copy the address register to the reload register. /* If that failed, copy the address register to the reload register.
Then add the constant to the reload register. */ Then add the constant to the reload register. */
@ -6777,43 +6748,44 @@ gen_input_reload (reloadreg, in, opnum, type)
delete_insns_since (last); delete_insns_since (last);
emit_insn (gen_move_insn (reloadreg, op1)); emit_insn (gen_move_insn (out, op1));
emit_insn (gen_add2_insn (reloadreg, op0)); emit_insn (gen_add2_insn (out, op0));
} }
#ifdef SECONDARY_MEMORY_NEEDED #ifdef SECONDARY_MEMORY_NEEDED
/* If we need a memory location to do the move, do it that way. */ /* If we need a memory location to do the move, do it that way. */
else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
&& GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
REGNO_REG_CLASS (REGNO (reloadreg)), REGNO_REG_CLASS (REGNO (out)),
GET_MODE (reloadreg))) GET_MODE (out)))
{ {
/* Get the memory to use and rewrite both registers to its mode. */ /* Get the memory to use and rewrite both registers to its mode. */
rtx loc = get_secondary_mem (in, GET_MODE (reloadreg), opnum, type); rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
if (GET_MODE (loc) != GET_MODE (reloadreg)) if (GET_MODE (loc) != GET_MODE (out))
reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg)); out = gen_rtx (REG, GET_MODE (loc), REGNO (out));
if (GET_MODE (loc) != GET_MODE (in)) if (GET_MODE (loc) != GET_MODE (in))
in = gen_rtx (REG, GET_MODE (loc), REGNO (in)); in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
emit_insn (gen_move_insn (loc, in)); emit_insn (gen_move_insn (loc, in));
emit_insn (gen_move_insn (reloadreg, loc)); emit_insn (gen_move_insn (out, loc));
} }
#endif #endif
/* If IN is a simple operand, use gen_move_insn. */ /* If IN is a simple operand, use gen_move_insn. */
else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG) else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
emit_insn (gen_move_insn (reloadreg, in)); emit_insn (gen_move_insn (out, in));
#ifdef HAVE_reload_load_address #ifdef HAVE_reload_load_address
else if (HAVE_reload_load_address) else if (HAVE_reload_load_address)
emit_insn (gen_reload_load_address (reloadreg, in)); emit_insn (gen_reload_load_address (out, in));
#endif #endif
/* Otherwise, just write (set REGLOADREG IN) and hope for the best. */ /* Otherwise, just write (set OUT IN) and hope for the best. */
else else
emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in)); emit_insn (gen_rtx (SET, VOIDmode, out, in));
/* Return the first insn emitted. /* Return the first insn emitted.
We can not just return get_last_insn, because there may have We can not just return get_last_insn, because there may have
@ -6960,7 +6932,7 @@ inc_for_reload (reloadreg, value, inc_amount)
emit_insn (gen_move_insn (reloadreg, incloc)); emit_insn (gen_move_insn (reloadreg, incloc));
/* See if we can directly increment INCLOC. Use a method similar to that /* See if we can directly increment INCLOC. Use a method similar to that
in gen_input_reload. */ in gen_reload. */
last = get_last_insn (); last = get_last_insn ();
add_insn = emit_insn (gen_rtx (SET, VOIDmode, incloc, add_insn = emit_insn (gen_rtx (SET, VOIDmode, incloc,

View file

@ -607,6 +607,22 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
mark_set_resources (XEXP (x, 0), res, 0, 0); mark_set_resources (XEXP (x, 0), res, 0, 0);
return; return;
case SUBREG:
if (in_dest)
{
if (GET_CODE (SUBREG_REG (x)) != REG)
mark_set_resources (SUBREG_REG (x), res,
in_dest, include_delayed_effects);
else
{
int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
for (i = regno; i < last_regno; i++)
SET_HARD_REG_BIT (res->regs, i);
}
}
return;
case REG: case REG:
if (in_dest) if (in_dest)
for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++) for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
@ -1762,6 +1778,7 @@ try_merge_delay_insns (insn, thread)
for (trial = thread; !stop_search_p (trial, 1); trial = next_trial) for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
{ {
rtx pat = PATTERN (trial); rtx pat = PATTERN (trial);
rtx oldtrial = trial;
next_trial = next_nonnote_insn (trial); next_trial = next_nonnote_insn (trial);
@ -1781,6 +1798,8 @@ try_merge_delay_insns (insn, thread)
&& (trial = try_split (pat, trial, 0)) != 0 && (trial = try_split (pat, trial, 0)) != 0
/* Update next_trial, in case try_split succeeded. */ /* Update next_trial, in case try_split succeeded. */
&& (next_trial = next_nonnote_insn (trial)) && (next_trial = next_nonnote_insn (trial))
/* Likewise THREAD. */
&& (thread = oldtrial == thread ? trial : thread)
&& rtx_equal_p (PATTERN (next_to_match), PATTERN (trial)) && rtx_equal_p (PATTERN (next_to_match), PATTERN (trial))
/* Have to test this condition if annul condition is different /* Have to test this condition if annul condition is different
from (and less restrictive than) non-annulling one. */ from (and less restrictive than) non-annulling one. */
@ -1790,6 +1809,9 @@ try_merge_delay_insns (insn, thread)
if (! annul_p) if (! annul_p)
{ {
update_block (trial, thread); update_block (trial, thread);
if (trial == thread)
thread = next_active_insn (thread);
delete_insn (trial); delete_insn (trial);
INSN_FROM_TARGET_P (next_to_match) = 0; INSN_FROM_TARGET_P (next_to_match) = 0;
} }
@ -3265,6 +3287,13 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (own_thread) if (own_thread)
{ {
update_block (trial, thread); update_block (trial, thread);
if (trial == thread)
{
thread = next_active_insn (thread);
if (new_thread == trial)
new_thread = thread;
}
delete_insn (trial); delete_insn (trial);
} }
else else
@ -3284,6 +3313,8 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
trial = try_split (pat, trial, 0); trial = try_split (pat, trial, 0);
if (new_thread == old_trial) if (new_thread == old_trial)
new_thread = trial; new_thread = trial;
if (thread == old_trial)
thread = trial;
pat = PATTERN (trial); pat = PATTERN (trial);
if (eligible_for_delay (insn, *pslots_filled, trial, flags)) if (eligible_for_delay (insn, *pslots_filled, trial, flags))
goto winner; goto winner;

View file

@ -1603,6 +1603,10 @@ may_trap_p (x)
we can link this file into other programs. */ we can link this file into other programs. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0) if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0)
return 1; return 1;
case EXPR_LIST:
/* An EXPR_LIST is used to represent a function call. This
certainly may trap. */
return 1;
default: default:
/* Any floating arithmetic may trap. */ /* Any floating arithmetic may trap. */
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)

View file

@ -315,7 +315,7 @@ static void add_insn_mem_dependence PROTO((rtx *, rtx *, rtx, rtx));
static void flush_pending_lists PROTO((rtx)); static void flush_pending_lists PROTO((rtx));
static void sched_analyze_1 PROTO((rtx, rtx)); static void sched_analyze_1 PROTO((rtx, rtx));
static void sched_analyze_2 PROTO((rtx, rtx)); static void sched_analyze_2 PROTO((rtx, rtx));
static void sched_analyze_insn PROTO((rtx, rtx)); static void sched_analyze_insn PROTO((rtx, rtx, rtx));
static int sched_analyze PROTO((rtx, rtx)); static int sched_analyze PROTO((rtx, rtx));
static void sched_note_set PROTO((int, rtx, int)); static void sched_note_set PROTO((int, rtx, int));
static int rank_for_schedule PROTO((rtx *, rtx *)); static int rank_for_schedule PROTO((rtx *, rtx *));
@ -2013,8 +2013,9 @@ sched_analyze_2 (x, insn)
/* Analyze an INSN with pattern X to find all dependencies. */ /* Analyze an INSN with pattern X to find all dependencies. */
static void static void
sched_analyze_insn (x, insn) sched_analyze_insn (x, insn, loop_notes)
rtx x, insn; rtx x, insn;
rtx loop_notes;
{ {
register RTX_CODE code = GET_CODE (x); register RTX_CODE code = GET_CODE (x);
rtx link; rtx link;
@ -2048,6 +2049,36 @@ sched_analyze_insn (x, insn)
sched_analyze_2 (XEXP (link, 0), insn); sched_analyze_2 (XEXP (link, 0), insn);
} }
/* If there is a LOOP_{BEG,END} note in the middle of a basic block, then
we must be sure that no instructions are scheduled across it.
Otherwise, the reg_n_refs info (which depends on loop_depth) would
become incorrect. */
if (loop_notes)
{
int max_reg = max_reg_num ();
rtx link;
for (i = 0; i < max_reg; i++)
{
rtx u;
for (u = reg_last_uses[i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
reg_last_uses[i] = 0;
if (reg_last_sets[i])
add_dependence (insn, reg_last_sets[i], 0);
}
reg_pending_sets_all = 1;
flush_pending_lists (insn);
link = loop_notes;
while (XEXP (link, 1))
link = XEXP (link, 1);
XEXP (link, 1) = REG_NOTES (insn);
REG_NOTES (insn) = loop_notes;
}
/* After reload, it is possible for an instruction to have a REG_DEAD note /* After reload, it is possible for an instruction to have a REG_DEAD note
for a register that actually dies a few instructions earlier. For for a register that actually dies a few instructions earlier. For
example, this can happen with SECONDARY_MEMORY_NEEDED reloads. example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
@ -2107,7 +2138,8 @@ sched_analyze_insn (x, insn)
prev_dep_insn = insn; prev_dep_insn = insn;
dep_insn = PREV_INSN (insn); dep_insn = PREV_INSN (insn);
while (GET_CODE (dep_insn) == INSN while (GET_CODE (dep_insn) == INSN
&& GET_CODE (PATTERN (dep_insn)) == USE) && GET_CODE (PATTERN (dep_insn)) == USE
&& GET_CODE (XEXP (PATTERN (dep_insn), 0)) == REG)
{ {
SCHED_GROUP_P (prev_dep_insn) = 1; SCHED_GROUP_P (prev_dep_insn) = 1;
@ -2135,6 +2167,7 @@ sched_analyze (head, tail)
register int n_insns = 0; register int n_insns = 0;
register rtx u; register rtx u;
register int luid = 0; register int luid = 0;
rtx loop_notes = 0;
for (insn = head; ; insn = NEXT_INSN (insn)) for (insn = head; ; insn = NEXT_INSN (insn))
{ {
@ -2142,7 +2175,8 @@ sched_analyze (head, tail)
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{ {
sched_analyze_insn (PATTERN (insn), insn); sched_analyze_insn (PATTERN (insn), insn, loop_notes);
loop_notes = 0;
n_insns += 1; n_insns += 1;
} }
else if (GET_CODE (insn) == CALL_INSN) else if (GET_CODE (insn) == CALL_INSN)
@ -2179,7 +2213,8 @@ sched_analyze (head, tail)
/* Add a fake REG_NOTE which we will later convert /* Add a fake REG_NOTE which we will later convert
back into a NOTE_INSN_SETJMP note. */ back into a NOTE_INSN_SETJMP note. */
REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD, constm1_rtx, REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (NOTE_INSN_SETJMP),
REG_NOTES (insn)); REG_NOTES (insn));
} }
else else
@ -2207,7 +2242,8 @@ sched_analyze (head, tail)
} }
LOG_LINKS (sched_before_next_call) = 0; LOG_LINKS (sched_before_next_call) = 0;
sched_analyze_insn (PATTERN (insn), insn); sched_analyze_insn (PATTERN (insn), insn, loop_notes);
loop_notes = 0;
/* We don't need to flush memory for a function call which does /* We don't need to flush memory for a function call which does
not involve memory. */ not involve memory. */
@ -2224,6 +2260,11 @@ sched_analyze (head, tail)
last_function_call = insn; last_function_call = insn;
n_insns += 1; n_insns += 1;
} }
else if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
if (insn == tail) if (insn == tail)
return n_insns; return n_insns;
@ -2825,6 +2866,16 @@ attach_deaths (x, insn, set_p)
{ {
if (! all_needed && ! dead_or_set_p (insn, x)) if (! all_needed && ! dead_or_set_p (insn, x))
{ {
/* Check for the case where the register dying partially
overlaps the register set by this insn. */
if (regno < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
{
int n = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (--n >= 0)
some_needed |= dead_or_set_regno_p (insn, regno + n);
}
/* If none of the words in X is needed, make a REG_DEAD /* If none of the words in X is needed, make a REG_DEAD
note. Otherwise, we must make partial REG_DEAD note. Otherwise, we must make partial REG_DEAD
notes. */ notes. */
@ -2985,8 +3036,11 @@ unlink_notes (insn, tail)
/* Don't save away NOTE_INSN_SETJMPs, because they must remain /* Don't save away NOTE_INSN_SETJMPs, because they must remain
immediately after the call they follow. We use a fake immediately after the call they follow. We use a fake
(REG_DEAD (const_int -1)) note to remember them. */ (REG_DEAD (const_int -1)) note to remember them.
else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP) Likewise with NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END. */
else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END)
{ {
/* Insert the note at the end of the notes list. */ /* Insert the note at the end of the notes list. */
PREV_INSN (insn) = note_list; PREV_INSN (insn) = note_list;
@ -3803,17 +3857,23 @@ schedule_block (b, file)
PREV_INSN (last) = insn; PREV_INSN (last) = insn;
last = insn; last = insn;
/* Check to see if we need to re-emit a NOTE_INSN_SETJMP here. */ /* Check to see if we need to re-emit any notes here. */
if (GET_CODE (insn) == CALL_INSN) {
{ rtx note;
rtx note = find_reg_note (insn, REG_DEAD, constm1_rtx);
if (note) for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{ {
emit_note_after (NOTE_INSN_SETJMP, insn); if (REG_NOTE_KIND (note) == REG_DEAD
remove_note (insn, note); && GET_CODE (XEXP (note, 0)) == CONST_INT)
} {
} if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
emit_note_after (INTVAL (XEXP (note, 0)), insn);
else
last = emit_note_before (INTVAL (XEXP (note, 0)), last);
remove_note (insn, note);
}
}
}
/* Everything that precedes INSN now either becomes "ready", if /* Everything that precedes INSN now either becomes "ready", if
it can execute immediately before INSN, or "pending", if it can execute immediately before INSN, or "pending", if

View file

@ -53,7 +53,7 @@ AT&T C compiler. From the example below I would conclude the following:
/* Mips systems use the SDB functions to dump out symbols, but /* Mips systems use the SDB functions to dump out symbols, but
do not supply usable syms.h include files. */ do not supply usable syms.h include files. */
#if defined(USG) && !defined(MIPS) && !defined (hpux) #if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(WINNT)
#include <syms.h> #include <syms.h>
/* Use T_INT if we don't have T_VOID. */ /* Use T_INT if we don't have T_VOID. */
#ifndef T_VOID #ifndef T_VOID

View file

@ -1380,6 +1380,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
i = decode_reg_name (regname); i = decode_reg_name (regname);
if (i >= 0 || i == -4) if (i >= 0 || i == -4)
++nclobbers; ++nclobbers;
else if (i == -2)
error ("unknown register name `%s' in `asm'", regname);
} }
last_expr_type = 0; last_expr_type = 0;
@ -1569,8 +1571,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
continue; continue;
} }
error ("unknown register name `%s' in `asm'", regname); /* Ignore unknown register, error already signalled. */
return;
} }
/* Use QImode since that's guaranteed to clobber just one reg. */ /* Use QImode since that's guaranteed to clobber just one reg. */
@ -1730,7 +1731,7 @@ warn_if_unused_value (exp)
while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR) while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR)
tem = TREE_OPERAND (tem, 0); tem = TREE_OPERAND (tem, 0);
if (TREE_CODE (tem) == MODIFY_EXPR) if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR)
return 0; return 0;
} }
/* ... fall through ... */ /* ... fall through ... */
@ -1932,6 +1933,17 @@ expand_start_else ()
cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */ cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */
} }
/* After calling expand_start_else, turn this "else" into an "else if"
by providing another condition. */
void
expand_elseif (cond)
tree cond;
{
cond_stack->data.cond.next_label = gen_label_rtx ();
do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
}
/* Generate RTL for the end of an if-then. /* Generate RTL for the end of an if-then.
Pop the record for it off of cond_stack. */ Pop the record for it off of cond_stack. */
@ -2501,7 +2513,15 @@ expand_return (retval)
} }
/* Are any cleanups needed? E.g. C++ destructors to be run? */ /* Are any cleanups needed? E.g. C++ destructors to be run? */
/* This is not sufficient. We also need to watch for cleanups of the
expression we are about to expand. Unfortunately, we cannot know
if it has cleanups until we expand it, and we want to change how we
expand it depending upon if we need cleanups. We can't win. */
#if 0
cleanups = any_pending_cleanups (1); cleanups = any_pending_cleanups (1);
#else
cleanups = 1;
#endif
if (TREE_CODE (retval) == RESULT_DECL) if (TREE_CODE (retval) == RESULT_DECL)
retval_rhs = retval; retval_rhs = retval;
@ -3510,6 +3530,17 @@ expand_anon_union_decl (decl, cleanup, decl_elts)
tree cleanup_elt = TREE_PURPOSE (decl_elts); tree cleanup_elt = TREE_PURPOSE (decl_elts);
enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt)); enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
/* Propagate the union's alignment to the elements. */
DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
/* If the element has BLKmode and the union doesn't, the union is
aligned such that the element doesn't need to have BLKmode, so
change the element's mode to the appropriate one for its size. */
if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
DECL_MODE (decl_elt) = mode
= mode_for_size (TREE_INT_CST_LOW (DECL_SIZE (decl_elt)),
MODE_INT, 1);
/* (SUBREG (MEM ...)) at RTL generation time is invalid, so we /* (SUBREG (MEM ...)) at RTL generation time is invalid, so we
instead create a new MEM rtx with the proper mode. */ instead create a new MEM rtx with the proper mode. */
if (GET_CODE (x) == MEM) if (GET_CODE (x) == MEM)
@ -4055,6 +4086,191 @@ bc_pushcase (value, label)
return 0; return 0;
} }
/* Returns the number of possible values of TYPE.
Returns -1 if the number is unknown or variable.
Returns -2 if the number does not fit in a HOST_WIDE_INT.
Sets *SPARENESS to 2 if TYPE is an ENUMERAL_TYPE whose values
do not increase monotonically (there may be duplicates);
to 1 if the values increase monotonically, but not always by 1;
otherwise sets it to 0. */
HOST_WIDE_INT
all_cases_count (type, spareness)
tree type;
int *spareness;
{
HOST_WIDE_INT count, count_high = 0;
*spareness = 0;
switch (TREE_CODE (type))
{
tree t;
case BOOLEAN_TYPE:
count = 2;
break;
case CHAR_TYPE:
count = 1 << BITS_PER_UNIT;
break;
default:
case INTEGER_TYPE:
if (TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST)
return -1;
else
{
/* count
= TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) + 1
but with overflow checking. */
tree mint = TYPE_MIN_VALUE (type);
tree maxt = TYPE_MAX_VALUE (type);
HOST_WIDE_INT lo, hi;
neg_double(TREE_INT_CST_LOW (mint), TREE_INT_CST_HIGH (mint),
&lo, &hi);
add_double(TREE_INT_CST_LOW (maxt), TREE_INT_CST_HIGH (maxt),
lo, hi, &lo, &hi);
add_double (lo, hi, 1, 0, &lo, &hi);
if (hi != 0 || lo < 0)
return -2;
count = lo;
}
break;
case ENUMERAL_TYPE:
count = 0;
for (t = TYPE_VALUES (type); t != NULL_TREE; t = TREE_CHAIN (t))
{
if (TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST
|| TREE_CODE (TREE_VALUE (t)) != INTEGER_CST
|| TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) + count
!= TREE_INT_CST_LOW (TREE_VALUE (t)))
*spareness = 1;
count++;
}
if (*spareness == 1)
{
tree prev = TREE_VALUE (TYPE_VALUES (type));
for (t = TYPE_VALUES (type); t = TREE_CHAIN (t), t != NULL_TREE; )
{
if (! tree_int_cst_lt (prev, TREE_VALUE (t)))
{
*spareness = 2;
break;
}
prev = TREE_VALUE (t);
}
}
}
return count;
}
#define BITARRAY_TEST(ARRAY, INDEX) \
((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
& (1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR)))
#define BITARRAY_SET(ARRAY, INDEX) \
((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
|= 1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR))
/* Set the elements of the bitstring CASES_SEEN (which has length COUNT),
with the case values we have seen, assuming the case expression
has the given TYPE.
SPARSENESS is as determined by all_cases_count.
The time needed is propotional to COUNT, unless
SPARSENESS is 2, in which case quadratic time is needed. */
void
mark_seen_cases (type, cases_seen, count, sparseness)
tree type;
unsigned char *cases_seen;
long count;
int sparseness;
{
long i;
tree next_node_to_try = NULL_TREE;
long next_node_offset = 0;
register struct case_node *n;
tree val = make_node (INTEGER_CST);
TREE_TYPE (val) = type;
for (n = case_stack->data.case_stmt.case_list; n;
n = n->right)
{
TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
while ( ! tree_int_cst_lt (n->high, val))
{
/* Calculate (into xlo) the "offset" of the integer (val).
The element with lowest value has offset 0, the next smallest
element has offset 1, etc. */
HOST_WIDE_INT xlo, xhi;
tree t;
if (sparseness == 2)
{
/* This less efficient loop is only needed to handle
duplicate case values (multiple enum constants
with the same value). */
for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
t = TREE_CHAIN (t), xlo++)
{
if (tree_int_cst_equal (val, TREE_VALUE (t)))
BITARRAY_SET (cases_seen, xlo);
}
}
else
{
if (sparseness && TYPE_VALUES (type) != NULL_TREE)
{
/* The TYPE_VALUES will be in increasing order, so
starting searching where we last ended. */
t = next_node_to_try;
xlo = next_node_offset;
xhi = 0;
for (;;)
{
if (t == NULL_TREE)
{
t = TYPE_VALUES (type);
xlo = 0;
}
if (tree_int_cst_equal (val, TREE_VALUE (t)))
{
next_node_to_try = TREE_CHAIN (t);
next_node_offset = xlo + 1;
break;
}
xlo++;
t = TREE_CHAIN (t);
if (t == next_node_to_try)
break;
}
}
else
{
t = TYPE_MIN_VALUE (type);
if (t)
neg_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t),
&xlo, &xhi);
else
xlo = xhi = 0;
add_double (xlo, xhi,
TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
&xlo, &xhi);
}
if (xhi == 0 && xlo >= 0 && xlo < count)
BITARRAY_SET (cases_seen, xlo);
}
add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
1, 0,
&TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
}
}
}
/* Called when the index of a switch statement is an enumerated type /* Called when the index of a switch statement is an enumerated type
and there is no default label. and there is no default label.
@ -4075,37 +4291,55 @@ check_for_full_enumeration_handling (type)
register tree chain; register tree chain;
int all_values = 1; int all_values = 1;
/* True iff the selector type is a numbered set mode. */
int sparseness = 0;
/* The number of possible selector values. */
HOST_WIDE_INT size;
/* For each possible selector value. a one iff it has been matched
by a case value alternative. */
unsigned char *cases_seen;
/* The allocated size of cases_seen, in chars. */
long bytes_needed;
tree t;
if (output_bytecode) if (output_bytecode)
{ {
bc_check_for_full_enumeration_handling (type); bc_check_for_full_enumeration_handling (type);
return; return;
} }
/* The time complexity of this loop is currently O(N * M), with if (! warn_switch)
N being the number of members in the enumerated type, and return;
M being the number of case expressions in the switch. */
for (chain = TYPE_VALUES (type); size = all_cases_count (type, &sparseness);
chain; bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
chain = TREE_CHAIN (chain))
if (size > 0 && size < 600000
/* We deliberately use malloc here - not xmalloc. */
&& (cases_seen = (unsigned char *) malloc (bytes_needed)) != NULL)
{ {
/* Find a match between enumeral and case expression, if possible. long i;
Quit looking when we've gone too far (since case expressions tree v = TYPE_VALUES (type);
are kept sorted in ascending order). Warn about enumerators not bzero (cases_seen, bytes_needed);
handled in the switch statement case expression list. */
for (n = case_stack->data.case_stmt.case_list; /* The time complexity of this code is normally O(N), where
n && tree_int_cst_lt (n->high, TREE_VALUE (chain)); N being the number of members in the enumerated type.
n = n->right) However, if type is a ENUMERAL_TYPE whose values do not
; increase monotonically, quadratic time may be needed. */
if (!n || tree_int_cst_lt (TREE_VALUE (chain), n->low)) mark_seen_cases (type, cases_seen, size, sparseness);
for (i = 0; v != NULL_TREE && i < size; i++, v = TREE_CHAIN (v))
{ {
if (warn_switch) if (BITARRAY_TEST(cases_seen, i) == 0)
warning ("enumeration value `%s' not handled in switch", warning ("enumeration value `%s' not handled in switch",
IDENTIFIER_POINTER (TREE_PURPOSE (chain))); IDENTIFIER_POINTER (TREE_PURPOSE (v)));
all_values = 0;
} }
free (cases_seen);
} }
/* Now we go the other way around; we warn if there are case /* Now we go the other way around; we warn if there are case

View file

@ -44,6 +44,10 @@ tree size_one_node;
The value is measured in bits. */ The value is measured in bits. */
int maximum_field_alignment; int maximum_field_alignment;
/* If non-zero, the alignment of a bitsting or (power-)set value, in bits.
May be overridden by front-ends. */
int set_alignment = 0;
#define GET_MODE_ALIGNMENT(MODE) \ #define GET_MODE_ALIGNMENT(MODE) \
MIN (BIGGEST_ALIGNMENT, \ MIN (BIGGEST_ALIGNMENT, \
MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))) MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)))
@ -84,8 +88,8 @@ variable_size (size)
{ {
/* If the language-processor is to take responsibility for variable-sized /* If the language-processor is to take responsibility for variable-sized
items (e.g., languages which have elaboration procedures like Ada), items (e.g., languages which have elaboration procedures like Ada),
just return SIZE unchanged. */ just return SIZE unchanged. Likewise for self-referential sizes. */
if (global_bindings_p () < 0) if (global_bindings_p () < 0 || contains_placeholder_p (size))
return size; return size;
size = save_expr (size); size = save_expr (size);
@ -898,6 +902,31 @@ layout_type (type)
TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
break; break;
case SET_TYPE:
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
abort();
else
{
#ifndef SET_WORD_SIZE
#define SET_WORD_SIZE BITS_PER_WORD
#endif
int alignment = set_alignment ? set_alignment : SET_WORD_SIZE;
int size_in_bits =
TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1;
int rounded_size
= ((size_in_bits + alignment - 1) / alignment) * alignment;
if (rounded_size > alignment)
TYPE_MODE (type) = BLKmode;
else
TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
TYPE_SIZE (type) = size_int (rounded_size);
TYPE_ALIGN (type) = alignment;
TYPE_PRECISION (type) = size_in_bits;
}
break;
case FILE_TYPE: case FILE_TYPE:
/* The size may vary in different languages, so the language front end /* The size may vary in different languages, so the language front end
should fill in the size. */ should fill in the size. */

View file

@ -82,6 +82,11 @@ static int *reg_order;
static char *regs_live; static char *regs_live;
/* Indexed by reg number, nonzero if reg was used in a SUBREG that changes
its size. */
static char *regs_change_size;
/* Indexed by insn's suid, the set of hard regs live after that insn. */ /* Indexed by insn's suid, the set of hard regs live after that insn. */
static HARD_REG_SET *after_insn_hard_regs; static HARD_REG_SET *after_insn_hard_regs;
@ -93,7 +98,7 @@ static HARD_REG_SET *after_insn_hard_regs;
static int stupid_reg_compare PROTO((int *, int *)); static int stupid_reg_compare PROTO((int *, int *));
static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode, static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode,
int, int)); int, int, int));
static void stupid_mark_refs PROTO((rtx, rtx)); static void stupid_mark_refs PROTO((rtx, rtx));
/* Stupid life analysis is for the case where only variables declared /* Stupid life analysis is for the case where only variables declared
@ -157,6 +162,9 @@ stupid_life_analysis (f, nregs, file)
reg_order = (int *) alloca (nregs * sizeof (int)); reg_order = (int *) alloca (nregs * sizeof (int));
bzero ((char *) reg_order, nregs * sizeof (int)); bzero ((char *) reg_order, nregs * sizeof (int));
regs_change_size = (char *) alloca (nregs * sizeof (char));
bzero ((char *) regs_change_size, nregs * sizeof (char));
reg_renumber = (short *) oballoc (nregs * sizeof (short)); reg_renumber = (short *) oballoc (nregs * sizeof (short));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
reg_renumber[i] = i; reg_renumber[i] = i;
@ -254,7 +262,8 @@ stupid_life_analysis (f, nregs, file)
reg_preferred_class (r), reg_preferred_class (r),
PSEUDO_REGNO_MODE (r), PSEUDO_REGNO_MODE (r),
reg_where_born[r], reg_where_born[r],
reg_where_dead[r]); reg_where_dead[r],
regs_change_size[r]);
/* If no reg available in that class, try alternate class. */ /* If no reg available in that class, try alternate class. */
if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS) if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS)
@ -262,7 +271,8 @@ stupid_life_analysis (f, nregs, file)
reg_alternate_class (r), reg_alternate_class (r),
PSEUDO_REGNO_MODE (r), PSEUDO_REGNO_MODE (r),
reg_where_born[r], reg_where_born[r],
reg_where_dead[r]); reg_where_dead[r],
regs_change_size[r]);
} }
if (file) if (file)
@ -303,14 +313,19 @@ stupid_reg_compare (r1p, r2p)
Return -1 if such a block cannot be found. Return -1 if such a block cannot be found.
If CALL_PRESERVED is nonzero, insist on registers preserved If CALL_PRESERVED is nonzero, insist on registers preserved
over subroutine calls, and return -1 if cannot find such. */ over subroutine calls, and return -1 if cannot find such.
If CHANGES_SIZE is nonzero, it means this register was used as the
operand of a SUBREG that changes its size. */
static int static int
stupid_find_reg (call_preserved, class, mode, born_insn, dead_insn) stupid_find_reg (call_preserved, class, mode,
born_insn, dead_insn, changes_size)
int call_preserved; int call_preserved;
enum reg_class class; enum reg_class class;
enum machine_mode mode; enum machine_mode mode;
int born_insn, dead_insn; int born_insn, dead_insn;
int changes_size;
{ {
register int i, ins; register int i, ins;
#ifdef HARD_REG_SET #ifdef HARD_REG_SET
@ -339,6 +354,12 @@ stupid_find_reg (call_preserved, class, mode, born_insn, dead_insn)
IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]); IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
#ifdef CLASS_CANNOT_CHANGE_SIZE
if (changes_size)
IOR_HARD_REG_SET (used,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{ {
#ifdef REG_ALLOC_ORDER #ifdef REG_ALLOC_ORDER
@ -471,9 +492,18 @@ stupid_mark_refs (x, insn)
return; return;
} }
else if (code == SUBREG
&& GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (x))
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
&& (INTEGRAL_MODE_P (GET_MODE (x))
|| INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (x)))))
regs_change_size[REGNO (SUBREG_REG (x))] = 1;
/* Register value being used, not set. */ /* Register value being used, not set. */
if (code == REG) else if (code == REG)
{ {
regno = REGNO (x); regno = REGNO (x);
if (regno < FIRST_PSEUDO_REGISTER) if (regno < FIRST_PSEUDO_REGISTER)

View file

@ -36,6 +36,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <ctype.h> #include <ctype.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifndef WINNT
#ifdef USG #ifdef USG
#undef FLOAT #undef FLOAT
#include <sys/param.h> #include <sys/param.h>
@ -50,6 +51,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/resource.h> #include <sys/resource.h>
#endif #endif
#endif #endif
#endif
#include "input.h" #include "input.h"
#include "tree.h" #include "tree.h"
@ -430,11 +432,7 @@ int flag_inline_functions;
int flag_keep_inline_functions; int flag_keep_inline_functions;
/* Nonzero means that functions declared `inline' will be treated /* Nonzero means that functions will not be inlined. */
as `static'. Prevents generation of zillions of copies of unused
static inline functions; instead, `inlines' are written out
only when actually used. Used in conjunction with -g. Also
does the right thing with #pragma interface. */
int flag_no_inline; int flag_no_inline;
@ -640,6 +638,8 @@ char *lang_options[] =
"-+e0", /* gcc.c tacks the `-' on the front. */ "-+e0", /* gcc.c tacks the `-' on the front. */
"-+e1", "-+e1",
"-+e2", "-+e2",
"-faccess-control",
"-fno-access-control",
"-fall-virtual", "-fall-virtual",
"-fno-all-virtual", "-fno-all-virtual",
"-falt-external-templates", "-falt-external-templates",
@ -707,6 +707,10 @@ char *lang_options[] =
"-Wno-non-virtual-dtor", "-Wno-non-virtual-dtor",
"-Wextern-inline", "-Wextern-inline",
"-Wno-extern-inline", "-Wno-extern-inline",
"-Wreorder",
"-Wno-reorder",
"-Wsynth",
"-Wno-synth",
/* these are for obj c */ /* these are for obj c */
"-lang-objc", "-lang-objc",
@ -849,6 +853,9 @@ int dump_time;
int int
get_run_time () get_run_time ()
{ {
#ifdef WINNT
return 0;
#else
#ifdef USG #ifdef USG
struct tms tms; struct tms tms;
#else #else
@ -881,6 +888,7 @@ get_run_time ()
return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000; return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
#endif #endif
#endif #endif
#endif
} }
#define TIMEVAR(VAR, BODY) \ #define TIMEVAR(VAR, BODY) \
@ -942,20 +950,17 @@ fatal_io_error (name)
exit (35); exit (35);
} }
/* Called to give a better error message when we don't have an insn to match /* Called to give a better error message for a bad insn rather than
what we are looking for or if the insn's constraints aren't satisfied, just calling abort(). */
rather than just calling abort(). */
void void
fatal_insn_not_found (insn) fatal_insn (message, insn)
char *message;
rtx insn; rtx insn;
{ {
if (!output_bytecode) if (!output_bytecode)
{ {
if (INSN_CODE (insn) < 0) error (message);
error ("internal error--unrecognizable insn:");
else
error ("internal error--insn does not satisfy its constraints:");
debug_rtx (insn); debug_rtx (insn);
} }
if (asm_out_file) if (asm_out_file)
@ -993,6 +998,20 @@ fatal_insn_not_found (insn)
abort (); abort ();
} }
/* Called to give a better error message when we don't have an insn to match
what we are looking for or if the insn's constraints aren't satisfied,
rather than just calling abort(). */
void
fatal_insn_not_found (insn)
rtx insn;
{
if (INSN_CODE (insn) < 0)
fatal_insn ("internal error--unrecognizable insn:", insn);
else
fatal_insn ("internal error--insn does not satisfy its constraints:", insn);
}
/* This is the default decl_printable_name function. */ /* This is the default decl_printable_name function. */
static char * static char *
@ -2719,6 +2738,7 @@ rest_of_compilation (decl)
if (warn_inline && specd) if (warn_inline && specd)
warning_with_decl (decl, lose); warning_with_decl (decl, lose);
DECL_INLINE (decl) = 0; DECL_INLINE (decl) = 0;
DECL_ABSTRACT_ORIGIN (decl) = 0;
/* Don't really compile an extern inline function. /* Don't really compile an extern inline function.
If we can't make it inline, pretend If we can't make it inline, pretend
it was only declared. */ it was only declared. */
@ -3927,8 +3947,7 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
compile_file (filename); compile_file (filename);
#ifndef OS2 #if !defined(OS2) && !defined(VMS) && !defined(WINNT)
#ifndef VMS
if (flag_print_mem) if (flag_print_mem)
{ {
#ifdef __alpha #ifdef __alpha
@ -3946,8 +3965,7 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
system ("ps v"); system ("ps v");
#endif /* not USG */ #endif /* not USG */
} }
#endif /* not VMS */ #endif /* not OS2 and not VMS and not WINNT */
#endif /* not OS2 */
if (errorcount) if (errorcount)
exit (FATAL_EXIT_CODE); exit (FATAL_EXIT_CODE);

View file

@ -319,8 +319,9 @@ gcc_obstack_init (obstack)
This is used before starting a nested function. */ This is used before starting a nested function. */
void void
save_tree_status (p) save_tree_status (p, toplevel)
struct function *p; struct function *p;
int toplevel;
{ {
p->all_types_permanent = all_types_permanent; p->all_types_permanent = all_types_permanent;
p->momentary_stack = momentary_stack; p->momentary_stack = momentary_stack;
@ -334,10 +335,15 @@ save_tree_status (p)
p->saveable_obstack = saveable_obstack; p->saveable_obstack = saveable_obstack;
p->rtl_obstack = rtl_obstack; p->rtl_obstack = rtl_obstack;
/* Objects that need to be saved in this function can be in the nonsaved if (! toplevel)
obstack of the enclosing function since they can't possibly be needed {
once it has returned. */ /* Objects that need to be saved in this function can be in the nonsaved
function_maybepermanent_obstack = function_obstack; obstack of the enclosing function since they can't possibly be needed
once it has returned. */
function_maybepermanent_obstack = function_obstack;
maybepermanent_firstobj
= (char *) obstack_finish (function_maybepermanent_obstack);
}
function_obstack = (struct obstack *) xmalloc (sizeof (struct obstack)); function_obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
gcc_obstack_init (function_obstack); gcc_obstack_init (function_obstack);
@ -348,30 +354,32 @@ save_tree_status (p)
momentary_firstobj = (char *) obstack_finish (&momentary_obstack); momentary_firstobj = (char *) obstack_finish (&momentary_obstack);
momentary_function_firstobj = momentary_firstobj; momentary_function_firstobj = momentary_firstobj;
maybepermanent_firstobj
= (char *) obstack_finish (function_maybepermanent_obstack);
} }
/* Restore all variables describing the current status from the structure *P. /* Restore all variables describing the current status from the structure *P.
This is used after a nested function. */ This is used after a nested function. */
void void
restore_tree_status (p) restore_tree_status (p, toplevel)
struct function *p; struct function *p;
int toplevel;
{ {
all_types_permanent = p->all_types_permanent; all_types_permanent = p->all_types_permanent;
momentary_stack = p->momentary_stack; momentary_stack = p->momentary_stack;
obstack_free (&momentary_obstack, momentary_function_firstobj); obstack_free (&momentary_obstack, momentary_function_firstobj);
/* Free saveable storage used by the function just compiled and not if (! toplevel)
saved. {
/* Free saveable storage used by the function just compiled and not
saved.
CAUTION: This is in function_obstack of the containing function. So CAUTION: This is in function_obstack of the containing function.
we must be sure that we never allocate from that obstack during So we must be sure that we never allocate from that obstack during
the compilation of a nested function if we expect it to survive past the the compilation of a nested function if we expect it to survive
nested function's end. */ past the nested function's end. */
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj); obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
}
obstack_free (function_obstack, 0); obstack_free (function_obstack, 0);
free (function_obstack); free (function_obstack);
@ -519,7 +527,10 @@ permanent_allocation (function_end)
/* Free up previous temporary obstack data */ /* Free up previous temporary obstack data */
obstack_free (&temporary_obstack, temporary_firstobj); obstack_free (&temporary_obstack, temporary_firstobj);
if (function_end) if (function_end)
obstack_free (&momentary_obstack, momentary_function_firstobj); {
obstack_free (&momentary_obstack, momentary_function_firstobj);
momentary_firstobj = momentary_function_firstobj;
}
else else
obstack_free (&momentary_obstack, momentary_firstobj); obstack_free (&momentary_obstack, momentary_firstobj);
obstack_free (&maybepermanent_obstack, maybepermanent_firstobj); obstack_free (&maybepermanent_obstack, maybepermanent_firstobj);
@ -2353,6 +2364,13 @@ stabilize_reference (ref)
stabilize_reference_1 (TREE_OPERAND (ref, 1))); stabilize_reference_1 (TREE_OPERAND (ref, 1)));
break; break;
case COMPOUND_EXPR:
result = build_nt (COMPOUND_EXPR,
stabilize_reference_1 (TREE_OPERAND (ref, 0)),
stabilize_reference (TREE_OPERAND (ref, 1)));
break;
/* If arg isn't a kind of lvalue we recognize, make no change. /* If arg isn't a kind of lvalue we recognize, make no change.
Caller should recognize the error for an invalid lvalue. */ Caller should recognize the error for an invalid lvalue. */
default: default:
@ -2792,19 +2810,14 @@ build_type_variant (type, constp, volatilep)
constp = !!constp; constp = !!constp;
volatilep = !!volatilep; volatilep = !!volatilep;
/* If not generating auxiliary info, search the chain of variants to see /* Search the chain of variants to see if there is already one there just
if there is already one there just like the one we need to have. If so, like the one we need to have. If so, use that existing one. We must
use that existing one. preserve the TYPE_NAME, since there is code that depends on this. */
We don't do this in the case where we are generating aux info because for (t = TYPE_MAIN_VARIANT(type); t; t = TYPE_NEXT_VARIANT (t))
in that case we want each typedef names to get it's own distinct type if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
node, even if the type of this new typedef is the same as some other && TYPE_NAME (t) == TYPE_NAME (type))
(existing) type. */ return t;
if (!flag_gen_aux_info)
for (t = TYPE_MAIN_VARIANT(type); t; t = TYPE_NEXT_VARIANT (t))
if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t))
return t;
/* We need a new one. */ /* We need a new one. */
@ -2819,7 +2832,7 @@ build_type_variant (type, constp, volatilep)
This is the right thing to do only when something else This is the right thing to do only when something else
about TYPE is modified in place. */ about TYPE is modified in place. */
tree void
change_main_variant (type, new_main) change_main_variant (type, new_main)
tree type, new_main; tree type, new_main;
{ {
@ -3054,7 +3067,9 @@ type_list_equal (l1, l2)
int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
if (cmp < 0) if (cmp < 0)
abort (); abort ();
if (cmp == 0) if (cmp == 0
|| TREE_TYPE (TREE_PURPOSE (t1))
!= TREE_TYPE (TREE_PURPOSE (t2)))
return 0; return 0;
} }
} }
@ -3843,7 +3858,7 @@ decl_function_context (decl)
{ {
if (TREE_CODE (context) == RECORD_TYPE if (TREE_CODE (context) == RECORD_TYPE
|| TREE_CODE (context) == UNION_TYPE) || TREE_CODE (context) == UNION_TYPE)
context = TYPE_CONTEXT (context); context = NULL_TREE;
else if (TREE_CODE (context) == TYPE_DECL) else if (TREE_CODE (context) == TYPE_DECL)
context = DECL_CONTEXT (context); context = DECL_CONTEXT (context);
else if (TREE_CODE (context) == BLOCK) else if (TREE_CODE (context) == BLOCK)
@ -3994,3 +4009,102 @@ get_file_function_name (kind)
return get_identifier (buf); return get_identifier (buf);
} }
/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
The result is placed in BUFFER (which has length BIT_SIZE),
with one bit in each char ('\000' or '\001').
If the constructor is constant, NULL_TREE is returned.
Otherwise, a TREE_LIST of the non-constant elements is emitted. */
tree
get_set_constructor_bits (init, buffer, bit_size)
tree init;
char *buffer;
int bit_size;
{
int i;
tree vals;
HOST_WIDE_INT domain_min
= TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (init))));
tree non_const_bits = NULL_TREE;
for (i = 0; i < bit_size; i++)
buffer[i] = 0;
for (vals = TREE_OPERAND (init, 1);
vals != NULL_TREE; vals = TREE_CHAIN (vals))
{
if (TREE_CODE (TREE_VALUE (vals)) != INTEGER_CST
|| (TREE_PURPOSE (vals) != NULL_TREE
&& TREE_CODE (TREE_PURPOSE (vals)) != INTEGER_CST))
non_const_bits =
tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
else if (TREE_PURPOSE (vals) != NULL_TREE)
{
/* Set a range of bits to ones. */
HOST_WIDE_INT lo_index
= TREE_INT_CST_LOW (TREE_PURPOSE (vals)) - domain_min;
HOST_WIDE_INT hi_index
= TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
if (lo_index < 0 || lo_index >= bit_size
|| hi_index < 0 || hi_index >= bit_size)
abort ();
for ( ; lo_index <= hi_index; lo_index++)
buffer[lo_index] = 1;
}
else
{
/* Set a single bit to one. */
HOST_WIDE_INT index
= TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
if (index < 0 || index >= bit_size)
{
error ("invalid initializer for bit string");
return NULL_TREE;
}
buffer[index] = 1;
}
}
return non_const_bits;
}
/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
The result is placed in BUFFER (which is an array of WD_SIZE
words). TYPE_ALIGN bits are stored in each element of BUFFER.
If the constructor is constant, NULL_TREE is returned.
Otherwise, a TREE_LIST of the non-constant elements is emitted. */
tree
get_set_constructor_words (init, buffer, wd_size)
tree init;
HOST_WIDE_INT *buffer;
int wd_size;
{
int i;
tree vals = TREE_OPERAND (init, 1);
int set_word_size = TYPE_ALIGN (TREE_TYPE (init));
int bit_size = wd_size * set_word_size;
int bit_pos = 0;
HOST_WIDE_INT *wordp = buffer;
char *bit_buffer = (char*)alloca(bit_size);
tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size);
for (i = 0; i < wd_size; i++)
buffer[i] = 0;
for (i = 0; i < bit_size; i++)
{
if (bit_buffer[i])
{
#if BITS_BIG_ENDIAN
*wordp |= (1 << (set_word_size - 1 - bit_pos));
#else
*wordp |= 1 << bit_pos;
#endif
}
bit_pos++;
if (bit_pos >= set_word_size)
bit_pos = 0, wordp++;
}
return non_const_bits;
}

View file

@ -1335,11 +1335,27 @@ calculate_giv_inc (pattern, src_insn, regno)
one of the LO_SUM rtx. */ one of the LO_SUM rtx. */
if (GET_CODE (increment) == LO_SUM) if (GET_CODE (increment) == LO_SUM)
increment = XEXP (increment, 1); increment = XEXP (increment, 1);
else if (GET_CODE (increment) == IOR)
{
/* The rs6000 port loads some constants with IOR. */
rtx second_part = XEXP (increment, 1);
src_insn = PREV_INSN (src_insn);
increment = SET_SRC (PATTERN (src_insn));
/* Don't need the last insn anymore. */
delete_insn (get_last_insn ());
if (GET_CODE (second_part) != CONST_INT
|| GET_CODE (increment) != CONST_INT)
abort ();
increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
}
if (GET_CODE (increment) != CONST_INT) if (GET_CODE (increment) != CONST_INT)
abort (); abort ();
/* The insn loading the constant into a register is not longer needed, /* The insn loading the constant into a register is no longer needed,
so delete it. */ so delete it. */
delete_insn (get_last_insn ()); delete_insn (get_last_insn ());
} }
@ -1730,12 +1746,32 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
case to be a branch past the end of the loop, and the case to be a branch past the end of the loop, and the
original jump label case to fall_through. */ original jump label case to fall_through. */
if (! invert_exp (pattern, copy) if (invert_exp (pattern, copy))
|| ! redirect_exp (&pattern, {
map->label_map[CODE_LABEL_NUMBER if (! redirect_exp (&pattern,
(JUMP_LABEL (insn))], map->label_map[CODE_LABEL_NUMBER
exit_label, copy)) (JUMP_LABEL (insn))],
abort (); exit_label, copy))
abort ();
}
else
{
rtx jmp;
rtx lab = gen_label_rtx ();
/* Can't do it by reversing the jump (probably becasue we
couln't reverse the conditions), so emit a new
jump_insn after COPY, and redirect the jump around
that. */
jmp = emit_jump_insn_after (gen_jump (exit_label), copy);
jmp = emit_barrier_after (jmp);
emit_label_after (lab, jmp);
LABEL_NUSES (lab) = 0;
if (! redirect_exp (&pattern,
map->label_map[CODE_LABEL_NUMBER
(JUMP_LABEL (insn))],
lab, copy))
abort ();
}
} }
#ifdef HAVE_cc0 #ifdef HAVE_cc0
@ -3077,7 +3113,11 @@ loop_iterations (loop_start, loop_end)
loop_final_value = 0; loop_final_value = 0;
loop_iteration_var = 0; loop_iteration_var = 0;
last_loop_insn = prev_nonnote_insn (loop_end); /* We used to use pren_nonnote_insn here, but that fails because it might
accidentally get the branch for a contained loop if the branch for this
loop was deleted. We can only trust branches immediately before the
loop_end. */
last_loop_insn = PREV_INSN (loop_end);
comparison = get_condition_for_loop (last_loop_insn); comparison = get_condition_for_loop (last_loop_insn);
if (comparison == 0) if (comparison == 0)
@ -3115,28 +3155,6 @@ loop_iterations (loop_start, loop_end)
/* iteration_info already printed a message. */ /* iteration_info already printed a message. */
return 0; return 0;
if (increment == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Increment value can't be calculated.\n");
return 0;
}
if (GET_CODE (increment) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Increment value not constant.\n");
return 0;
}
if (GET_CODE (initial_value) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Initial value not constant.\n");
return 0;
}
/* If the comparison value is an invariant register, then try to find /* If the comparison value is an invariant register, then try to find
its value from the insns before the start of the loop. */ its value from the insns before the start of the loop. */
@ -3185,7 +3203,28 @@ loop_iterations (loop_start, loop_end)
loop_increment = increment; loop_increment = increment;
loop_final_value = final_value; loop_final_value = final_value;
if (final_value == 0) if (increment == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Increment value can't be calculated.\n");
return 0;
}
else if (GET_CODE (increment) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Increment value not constant.\n");
return 0;
}
else if (GET_CODE (initial_value) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Initial value not constant.\n");
return 0;
}
else if (final_value == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,

View file

@ -1358,10 +1358,9 @@ contains_pointers_p (type)
} }
} }
/* Output text storage for constructor CONSTR. Returns rtx of /* Output text storage for constructor CONSTR. */
storage. */
rtx void
bc_output_constructor (constr) bc_output_constructor (constr)
tree constr; tree constr;
{ {

View file

@ -1 +1 @@
char *version_string = "2.6.0"; char *version_string = "2.6.1";

View file

@ -93,7 +93,6 @@ typedef unsigned char U_CHAR;
/* VMS-specific definitions */ /* VMS-specific definitions */
#ifdef VMS #ifdef VMS
#include <time.h> #include <time.h>
#include <perror.h> /* This defines sys_errlist/sys_nerr properly */
#include <descrip.h> #include <descrip.h>
#define O_RDONLY 0 /* Open arg for Read/Only */ #define O_RDONLY 0 /* Open arg for Read/Only */
#define O_WRONLY 1 /* Open arg for Write/Only */ #define O_WRONLY 1 /* Open arg for Write/Only */
@ -186,13 +185,22 @@ extern char *getenv ();
extern FILE *fdopen (); extern FILE *fdopen ();
extern char *version_string; extern char *version_string;
extern struct tm *localtime (); extern struct tm *localtime ();
#ifndef VMS
#ifndef HAVE_STRERROR
extern int sys_nerr; extern int sys_nerr;
#if defined(bsd4_4) || defined(__NetBSD__) #if defined(bsd4_4) || defined(__NetBSD__) || defined(__FreeBSD__)
extern const char *const sys_errlist[]; extern const char *const sys_errlist[];
#else #else
extern char *sys_errlist[]; extern char *sys_errlist[];
#endif #endif
#else /* HAVE_STERRROR */
char *strerror ();
#endif
#else /* VMS */
char *strerror (int,...);
#endif
extern int parse_escape (); extern int parse_escape ();
extern HOST_WIDE_INT parse_c_expression ();
#ifndef errno #ifndef errno
extern int errno; extern int errno;
@ -276,7 +284,7 @@ static void write_output ();
static int check_macro_name (); static int check_macro_name ();
static int compare_defs (); static int compare_defs ();
static int compare_token_lists (); static int compare_token_lists ();
static int eval_if_expression (); static HOST_WIDE_INT eval_if_expression ();
static int discard_comments (); static int discard_comments ();
static int change_newlines (); static int change_newlines ();
static int line_for_error (); static int line_for_error ();
@ -388,6 +396,11 @@ static int print_include_names = 0;
static int no_line_commands; static int no_line_commands;
/* Nonzero means output the text in failing conditionals,
inside #failed ... #endfailed. */
static int output_conditionals;
/* dump_only means inhibit output of the preprocessed text /* dump_only means inhibit output of the preprocessed text
and instead output the definitions of all user-defined and instead output the definitions of all user-defined
macros in a form suitable for use as input to cccp. macros in a form suitable for use as input to cccp.
@ -1123,7 +1136,12 @@ main (argc, argv)
#endif #endif
p = argv[0] + strlen (argv[0]); p = argv[0] + strlen (argv[0]);
while (p != argv[0] && p[-1] != '/') --p; while (p != argv[0] && p[-1] != '/'
#ifdef DIR_SEPARATOR
&& p[-1] != DIR_SEPARATOR
#endif
)
--p;
progname = p; progname = p;
#ifdef VMS #ifdef VMS
@ -1195,6 +1213,9 @@ main (argc, argv)
else else
include_prefix = argv[++i]; include_prefix = argv[++i];
} }
if (!strcmp (argv[i], "-ifoutput")) {
output_conditionals = 1;
}
if (!strcmp (argv[i], "-isystem")) { if (!strcmp (argv[i], "-isystem")) {
struct file_name_list *dirtmp; struct file_name_list *dirtmp;
@ -1322,7 +1343,10 @@ main (argc, argv)
pedantic = 1; pedantic = 1;
pedantic_errors = 1; pedantic_errors = 1;
} else if (!strcmp (argv[i], "-pcp")) { } else if (!strcmp (argv[i], "-pcp")) {
char *pcp_fname = argv[++i]; char *pcp_fname;
if (i + 1 == argc)
fatal ("Filename missing after -pcp option");
pcp_fname = argv[++i];
pcp_outfile = pcp_outfile =
((pcp_fname[0] != '-' || pcp_fname[1] != '\0') ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
? fopen (pcp_fname, "w") ? fopen (pcp_fname, "w")
@ -1429,6 +1453,8 @@ main (argc, argv)
/* For -MD and -MMD options, write deps on file named by next arg. */ /* For -MD and -MMD options, write deps on file named by next arg. */
if (!strcmp (argv[i], "-MD") if (!strcmp (argv[i], "-MD")
|| !strcmp (argv[i], "-MMD")) { || !strcmp (argv[i], "-MMD")) {
if (i + 1 == argc)
fatal ("Filename missing after %s option", argv[i]);
i++; i++;
deps_file = argv[i]; deps_file = argv[i];
deps_mode = "w"; deps_mode = "w";
@ -1606,7 +1632,11 @@ main (argc, argv)
/* Some people say that CPATH should replace the standard include dirs, /* Some people say that CPATH should replace the standard include dirs,
but that seems pointless: it comes before them, so it overrides them but that seems pointless: it comes before them, so it overrides them
anyway. */ anyway. */
#ifdef WINNT
p = (char *) getenv ("Include");
#else
p = (char *) getenv ("CPATH"); p = (char *) getenv ("CPATH");
#endif
if (p != 0 && ! no_standard_includes) if (p != 0 && ! no_standard_includes)
path_include (p); path_include (p);
@ -1958,7 +1988,11 @@ main (argc, argv)
int len; int len;
/* Discard all directory prefixes from filename. */ /* Discard all directory prefixes from filename. */
if ((q = rindex (in_fname, '/')) != NULL) if ((q = rindex (in_fname, '/')) != NULL
#ifdef DIR_SEPARATOR
&& (q = rindex (in_fname, DIR_SEPARATOR)) != NULL
#endif
)
++q; ++q;
else else
q = in_fname; q = in_fname;
@ -2175,6 +2209,33 @@ path_include (path)
} }
} }
/* Return the address of the first character in S that equals C.
S is an array of length N, possibly containing '\0's, and followed by '\0'.
Return 0 if there is no such character. Assume that C itself is not '\0'.
If we knew we could use memchr, we could just invoke memchr (S, C, N),
but unfortunately memchr isn't autoconfigured yet. */
static U_CHAR *
index0 (s, c, n)
U_CHAR *s;
int c;
int n;
{
for (;;) {
char *q = index (s, c);
if (q)
return (U_CHAR *) q;
else {
int l = strlen (s);
if (l == n)
return 0;
l++;
s += l;
n -= l;
}
}
}
/* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF
before main CCCP processing. Name `pcp' is also in honor of the before main CCCP processing. Name `pcp' is also in honor of the
drugs the trigraph designers must have been on. drugs the trigraph designers must have been on.
@ -2188,11 +2249,12 @@ static void
trigraph_pcp (buf) trigraph_pcp (buf)
FILE_BUF *buf; FILE_BUF *buf;
{ {
register U_CHAR c, *fptr, *bptr, *sptr; register U_CHAR c, *fptr, *bptr, *sptr, *lptr;
int len; int len;
fptr = bptr = sptr = buf->buf; fptr = bptr = sptr = buf->buf;
while ((sptr = (U_CHAR *) index (sptr, '?')) != NULL) { lptr = fptr + buf->length;
while ((sptr = (U_CHAR *) index0 (sptr, '?', lptr - sptr)) != NULL) {
if (*++sptr != '?') if (*++sptr != '?')
continue; continue;
switch (*++sptr) { switch (*++sptr) {
@ -2261,25 +2323,15 @@ newline_fix (bp)
U_CHAR *bp; U_CHAR *bp;
{ {
register U_CHAR *p = bp; register U_CHAR *p = bp;
register int count = 0;
/* First count the backslash-newline pairs here. */ /* First count the backslash-newline pairs here. */
while (1) { while (p[0] == '\\' && p[1] == '\n')
if (p[0] == '\\') { p += 2;
if (p[1] == '\n')
p += 2, count++;
else if (p[1] == '\r' && p[2] == '\n')
p += 3, count++;
else
break;
} else
break;
}
/* What follows the backslash-newlines is not embarrassing. */ /* What follows the backslash-newlines is not embarrassing. */
if (count == 0 || (*p != '/' && *p != '*')) if (*p != '/' && *p != '*')
return; return;
/* Copy all potentially embarrassing characters /* Copy all potentially embarrassing characters
@ -2290,7 +2342,7 @@ newline_fix (bp)
*bp++ = *p++; *bp++ = *p++;
/* Now write the same number of pairs after the embarrassing chars. */ /* Now write the same number of pairs after the embarrassing chars. */
while (count-- > 0) { while (bp < p) {
*bp++ = '\\'; *bp++ = '\\';
*bp++ = '\n'; *bp++ = '\n';
} }
@ -2304,24 +2356,14 @@ name_newline_fix (bp)
U_CHAR *bp; U_CHAR *bp;
{ {
register U_CHAR *p = bp; register U_CHAR *p = bp;
register int count = 0;
/* First count the backslash-newline pairs here. */ /* First count the backslash-newline pairs here. */
while (1) { while (p[0] == '\\' && p[1] == '\n')
if (p[0] == '\\') { p += 2;
if (p[1] == '\n')
p += 2, count++;
else if (p[1] == '\r' && p[2] == '\n')
p += 3, count++;
else
break;
} else
break;
}
/* What follows the backslash-newlines is not embarrassing. */ /* What follows the backslash-newlines is not embarrassing. */
if (count == 0 || !is_idchar[*p]) if (!is_idchar[*p])
return; return;
/* Copy all potentially embarrassing characters /* Copy all potentially embarrassing characters
@ -2332,7 +2374,7 @@ name_newline_fix (bp)
*bp++ = *p++; *bp++ = *p++;
/* Now write the same number of pairs after the embarrassing chars. */ /* Now write the same number of pairs after the embarrassing chars. */
while (count-- > 0) { while (bp < p) {
*bp++ = '\\'; *bp++ = '\\';
*bp++ = '\n'; *bp++ = '\n';
} }
@ -2495,7 +2537,7 @@ do { ip = &instack[indepth]; \
obp = op->bufp; } while (0) obp = op->bufp; } while (0)
if (no_output && instack[indepth].fname != 0) if (no_output && instack[indepth].fname != 0)
skip_if_group (&instack[indepth], 1); skip_if_group (&instack[indepth], 1, NULL);
obp = op->bufp; obp = op->bufp;
RECACHE; RECACHE;
@ -2513,22 +2555,25 @@ do { ip = &instack[indepth]; \
switch (c) { switch (c) {
case '\\': case '\\':
if (ibp >= limit) if (*ibp == '\n' && !ip->macro) {
break; /* At the top level, always merge lines ending with backslash-newline,
if (*ibp == '\n') { even in middle of identifier. But do not merge lines in a macro,
/* Always merge lines ending with backslash-newline, since backslash might be followed by a newline-space marker. */
even in middle of identifier. */
++ibp; ++ibp;
++ip->lineno; ++ip->lineno;
--obp; /* remove backslash from obuf */ --obp; /* remove backslash from obuf */
break; break;
} }
/* If ANSI, backslash is just another character outside a string. */
if (!traditional)
goto randomchar;
/* Otherwise, backslash suppresses specialness of following char, /* Otherwise, backslash suppresses specialness of following char,
so copy it here to prevent the switch from seeing it. so copy it here to prevent the switch from seeing it.
But first get any pending identifier processed. */ But first get any pending identifier processed. */
if (ident_length > 0) if (ident_length > 0)
goto specialchar; goto specialchar;
*obp++ = *ibp++; if (ibp < limit)
*obp++ = *ibp++;
break; break;
case '#': case '#':
@ -2608,7 +2653,7 @@ do { ip = &instack[indepth]; \
/* If not generating expanded output, /* If not generating expanded output,
what we do with ordinary text is skip it. what we do with ordinary text is skip it.
Discard everything until next # directive. */ Discard everything until next # directive. */
skip_if_group (&instack[indepth], 1); skip_if_group (&instack[indepth], 1, 0);
RECACHE; RECACHE;
beg_of_line = ibp; beg_of_line = ibp;
break; break;
@ -2632,7 +2677,7 @@ do { ip = &instack[indepth]; \
/* If not generating expanded output, ignore everything until /* If not generating expanded output, ignore everything until
next # directive. */ next # directive. */
if (no_output && instack[indepth].fname) if (no_output && instack[indepth].fname)
skip_if_group (&instack[indepth], 1); skip_if_group (&instack[indepth], 1, 0);
obp = op->bufp; obp = op->bufp;
RECACHE; RECACHE;
beg_of_line = ibp; beg_of_line = ibp;
@ -2790,6 +2835,9 @@ do { ip = &instack[indepth]; \
char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen); char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
if (lintcmd != NULL) { if (lintcmd != NULL) {
op->bufp = obp;
check_expand (op, cmdlen + arglen + 14);
obp = op->bufp;
/* I believe it is always safe to emit this newline: */ /* I believe it is always safe to emit this newline: */
obp[-1] = '\n'; obp[-1] = '\n';
bcopy ("#pragma lint ", (char *) obp, 13); bcopy ("#pragma lint ", (char *) obp, 13);
@ -2804,10 +2852,12 @@ do { ip = &instack[indepth]; \
} }
/* OK, now bring us back to the state we were in before we entered /* OK, now bring us back to the state we were in before we entered
this branch. We need #line b/c the newline for the pragma this branch. We need #line because the #pragma's newline always
could fuck things up. */ messes up the line count. */
op->bufp = obp;
output_line_command (ip, op, 0, same_file); output_line_command (ip, op, 0, same_file);
*(obp++) = ' '; /* just in case, if comments are copied thru */ check_expand (op, limit - ibp + 2);
obp = op->bufp;
*(obp++) = '/'; *(obp++) = '/';
} }
} }
@ -2884,9 +2934,7 @@ do { ip = &instack[indepth]; \
ibp += 2; ibp += 2;
} }
c = *ibp++; c = *ibp++;
/* ".." terminates a preprocessing number. This is useless for C if (!is_idchar[c] && c != '.') {
code but useful for preprocessing other things. */
if (!isalnum (c) && (c != '.' || *ibp == '.') && c != '_') {
--ibp; --ibp;
break; break;
} }
@ -2988,7 +3036,7 @@ do { ip = &instack[indepth]; \
if (ip->lineno != op->lineno) { if (ip->lineno != op->lineno) {
op->bufp = obp; op->bufp = obp;
output_line_command (ip, op, 1, same_file); output_line_command (ip, op, 1, same_file);
check_expand (op, ip->length - (ip->bufp - ip->buf)); check_expand (op, limit - ibp);
obp = op->bufp; obp = op->bufp;
} }
break; break;
@ -3226,9 +3274,17 @@ do { ip = &instack[indepth]; \
/* This is now known to be a macro call. /* This is now known to be a macro call.
Discard the macro name from the output, Discard the macro name from the output,
along with any following whitespace just copied. */ along with any following whitespace just copied,
but preserve newlines at the top level since this
is more likely to do the right thing with line numbers. */
obp = op->buf + obufp_before_macroname; obp = op->buf + obufp_before_macroname;
op->lineno = op_lineno_before_macroname; if (ip->macro != 0)
op->lineno = op_lineno_before_macroname;
else {
int newlines = op->lineno - op_lineno_before_macroname;
while (0 < newlines--)
*obp++ = '\n';
}
/* Prevent accidental token-pasting with a character /* Prevent accidental token-pasting with a character
before the macro call. */ before the macro call. */
@ -3529,8 +3585,9 @@ handle_directive (ip, op)
if (*bp == '\n') { if (*bp == '\n') {
ip->lineno++; ip->lineno++;
copy_command = 1; copy_command = 1;
} bp++;
bp++; } else if (traditional)
bp++;
} }
break; break;
@ -3555,7 +3612,14 @@ handle_directive (ip, op)
case '<': case '<':
if (!kt->angle_brackets) if (!kt->angle_brackets)
break; break;
while (*bp && *bp != '>') bp++; while (bp < limit && *bp != '>' && *bp != '\n') {
if (*bp == '\\' && bp[1] == '\n') {
ip->lineno++;
copy_command = 1;
bp++;
}
bp++;
}
break; break;
case '/': case '/':
@ -3783,7 +3847,7 @@ timestamp ()
{ {
static struct tm *timebuf; static struct tm *timebuf;
if (!timebuf) { if (!timebuf) {
time_t t = time (0); time_t t = time ((time_t *)0);
timebuf = localtime (&t); timebuf = localtime (&t);
} }
return timebuf; return timebuf;
@ -3925,7 +3989,8 @@ special_symbol (hp, op)
goto oops; goto oops;
if (hp = lookup (ip->bufp, -1, -1)) { if (hp = lookup (ip->bufp, -1, -1)) {
if (pcp_outfile && pcp_inside_if if (pcp_outfile && pcp_inside_if
&& hp->value.defn->predefined) && (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
/* Output a precondition for this macro use. */ /* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name); fprintf (pcp_outfile, "#define %s\n", hp->name);
buf = " 1 "; buf = " 1 ";
@ -5360,9 +5425,31 @@ create_definition (buf, limit, op)
} else { } else {
/* Simple expansion or empty definition. */ /* Simple expansion or empty definition. */
/* Skip spaces and tabs if any. */ if (bp < limit)
while (bp < limit && (*bp == ' ' || *bp == '\t')) {
++bp; switch (*bp)
{
case '\t': case ' ':
/* Skip spaces and tabs. */
while (++bp < limit && (*bp == ' ' || *bp == '\t'))
continue;
break;
case '!': case '"': case '#': case '%': case '&': case '\'':
case ')': case '*': case '+': case ',': case '-': case '.':
case '/': case ':': case ';': case '<': case '=': case '>':
case '?': case '[': case '\\': case ']': case '^': case '{':
case '|': case '}': case '~':
warning ("missing white space after `#define %.*s'",
sym_length, symname);
break;
default:
pedwarn ("missing white space after `#define %.*s'",
sym_length, symname);
break;
}
}
/* Now everything from bp before limit is the definition. */ /* Now everything from bp before limit is the definition. */
defn = collect_expansion (bp, limit, -1, NULL_PTR); defn = collect_expansion (bp, limit, -1, NULL_PTR);
defn->args.argnames = (U_CHAR *) ""; defn->args.argnames = (U_CHAR *) "";
@ -5659,16 +5746,8 @@ collect_expansion (buf, end, nargs, arglist)
expected_delimiter = c; expected_delimiter = c;
break; break;
/* Special hack: if a \# is written in the #define
include a # in the definition. This is useless for C code
but useful for preprocessing other things. */
case '\\': case '\\':
/* \# quotes a # even outside of strings. */ if (p < limit && expected_delimiter) {
if (p < limit && *p == '#' && !expected_delimiter) {
exp_p--;
*exp_p++ = *p++;
} else if (p < limit && expected_delimiter) {
/* In a string, backslash goes through /* In a string, backslash goes through
and makes next char ordinary. */ and makes next char ordinary. */
*exp_p++ = *p++; *exp_p++ = *p++;
@ -6537,7 +6616,7 @@ do_ident (buf, limit)
free (trybuf.buf); free (trybuf.buf);
/* Output directive name. */ /* Output directive name. */
check_expand (op, 8); check_expand (op, 7);
bcopy ("#ident ", (char *) op->bufp, 7); bcopy ("#ident ", (char *) op->bufp, 7);
op->bufp += 7; op->bufp += 7;
@ -6647,11 +6726,11 @@ do_if (buf, limit, op, keyword)
FILE_BUF *op; FILE_BUF *op;
struct directive *keyword; struct directive *keyword;
{ {
int value; HOST_WIDE_INT value;
FILE_BUF *ip = &instack[indepth]; FILE_BUF *ip = &instack[indepth];
value = eval_if_expression (buf, limit - buf); value = eval_if_expression (buf, limit - buf);
conditional_skip (ip, value == 0, T_IF, NULL_PTR); conditional_skip (ip, value == 0, T_IF, NULL_PTR, op);
return 0; return 0;
} }
@ -6666,7 +6745,7 @@ do_elif (buf, limit, op, keyword)
FILE_BUF *op; FILE_BUF *op;
struct directive *keyword; struct directive *keyword;
{ {
int value; HOST_WIDE_INT value;
FILE_BUF *ip = &instack[indepth]; FILE_BUF *ip = &instack[indepth];
if (if_stack == instack[indepth].if_stack) { if (if_stack == instack[indepth].if_stack) {
@ -6685,11 +6764,11 @@ do_elif (buf, limit, op, keyword)
} }
if (if_stack->if_succeeded) if (if_stack->if_succeeded)
skip_if_group (ip, 0); skip_if_group (ip, 0, op);
else { else {
value = eval_if_expression (buf, limit - buf); value = eval_if_expression (buf, limit - buf);
if (value == 0) if (value == 0)
skip_if_group (ip, 0); skip_if_group (ip, 0, op);
else { else {
++if_stack->if_succeeded; /* continue processing input */ ++if_stack->if_succeeded; /* continue processing input */
output_line_command (ip, op, 1, same_file); output_line_command (ip, op, 1, same_file);
@ -6702,16 +6781,16 @@ do_elif (buf, limit, op, keyword)
* evaluate a #if expression in BUF, of length LENGTH, * evaluate a #if expression in BUF, of length LENGTH,
* then parse the result as a C expression and return the value as an int. * then parse the result as a C expression and return the value as an int.
*/ */
static int static HOST_WIDE_INT
eval_if_expression (buf, length) eval_if_expression (buf, length)
U_CHAR *buf; U_CHAR *buf;
int length; int length;
{ {
FILE_BUF temp_obuf; FILE_BUF temp_obuf;
HASHNODE *save_defined; HASHNODE *save_defined;
int value; HOST_WIDE_INT value;
save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1); save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, NULL_PTR, -1);
pcp_inside_if = 1; pcp_inside_if = 1;
temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
pcp_inside_if = 0; pcp_inside_if = 0;
@ -6790,7 +6869,9 @@ do_xifdef (buf, limit, op, keyword)
if (pcp_outfile) { if (pcp_outfile) {
/* Output a precondition for this macro. */ /* Output a precondition for this macro. */
if (hp && hp->value.defn->predefined) if (hp &&
(hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
fprintf (pcp_outfile, "#define %s\n", hp->name); fprintf (pcp_outfile, "#define %s\n", hp->name);
else { else {
U_CHAR *cp = buf; U_CHAR *cp = buf;
@ -6809,7 +6890,7 @@ do_xifdef (buf, limit, op, keyword)
} }
} }
conditional_skip (ip, skip, T_IF, control_macro); conditional_skip (ip, skip, T_IF, control_macro, op);
return 0; return 0;
} }
@ -6819,11 +6900,12 @@ do_xifdef (buf, limit, op, keyword)
Otherwise, CONTROL_MACRO is 0. */ Otherwise, CONTROL_MACRO is 0. */
static void static void
conditional_skip (ip, skip, type, control_macro) conditional_skip (ip, skip, type, control_macro, op)
FILE_BUF *ip; FILE_BUF *ip;
int skip; int skip;
enum node_type type; enum node_type type;
U_CHAR *control_macro; U_CHAR *control_macro;
FILE_BUF *op;
{ {
IF_STACK_FRAME *temp; IF_STACK_FRAME *temp;
@ -6837,7 +6919,7 @@ conditional_skip (ip, skip, type, control_macro)
if_stack->type = type; if_stack->type = type;
if (skip != 0) { if (skip != 0) {
skip_if_group (ip, 0); skip_if_group (ip, 0, op);
return; return;
} else { } else {
++if_stack->if_succeeded; ++if_stack->if_succeeded;
@ -6851,9 +6933,10 @@ conditional_skip (ip, skip, type, control_macro)
* If ANY is nonzero, return at next directive of any sort. * If ANY is nonzero, return at next directive of any sort.
*/ */
static void static void
skip_if_group (ip, any) skip_if_group (ip, any, op)
FILE_BUF *ip; FILE_BUF *ip;
int any; int any;
FILE_BUF *op;
{ {
register U_CHAR *bp = ip->bufp, *cp; register U_CHAR *bp = ip->bufp, *cp;
register U_CHAR *endb = ip->buf + ip->length; register U_CHAR *endb = ip->buf + ip->length;
@ -6862,6 +6945,25 @@ skip_if_group (ip, any)
U_CHAR *beg_of_line = bp; U_CHAR *beg_of_line = bp;
register int ident_length; register int ident_length;
U_CHAR *ident, *after_ident; U_CHAR *ident, *after_ident;
/* Save info about where the group starts. */
U_CHAR *beg_of_group = bp;
int beg_lineno = ip->lineno;
if (output_conditionals && op != 0) {
char *ptr = "#failed\n";
int len = strlen (ptr);
if (op->bufp > op->buf && op->bufp[-1] != '\n')
{
*op->bufp++ = '\n';
op->lineno++;
}
check_expand (op, len);
bcopy (ptr, (char *) op->bufp, len);
op->bufp += len;
op->lineno++;
output_line_command (ip, op, 1, 0);
}
while (bp < endb) { while (bp < endb) {
switch (*bp++) { switch (*bp++) {
@ -7013,7 +7115,7 @@ skip_if_group (ip, any)
&& strncmp (cp, kt->name, kt->length) == 0) { && strncmp (cp, kt->name, kt->length) == 0) {
/* If we are asked to return on next directive, do so now. */ /* If we are asked to return on next directive, do so now. */
if (any) if (any)
return; goto done;
switch (kt->type) { switch (kt->type) {
case T_IF: case T_IF:
@ -7036,7 +7138,7 @@ skip_if_group (ip, any)
break; break;
} }
else if (if_stack == save_if_stack) else if (if_stack == save_if_stack)
return; /* found what we came for */ goto done; /* found what we came for */
if (kt->type != T_ENDIF) { if (kt->type != T_ENDIF) {
if (if_stack->type == T_ELSE) if (if_stack->type == T_ELSE)
@ -7058,10 +7160,32 @@ skip_if_group (ip, any)
pedwarn ("invalid preprocessor directive name"); pedwarn ("invalid preprocessor directive name");
} }
} }
ip->bufp = bp; ip->bufp = bp;
/* after this returns, rescan will exit because ip->bufp /* after this returns, rescan will exit because ip->bufp
now points to the end of the buffer. now points to the end of the buffer.
rescan is responsible for the error message also. */ rescan is responsible for the error message also. */
done:
if (output_conditionals && op != 0) {
char *ptr = "#endfailed\n";
int len = strlen (ptr);
if (op->bufp > op->buf && op->bufp[-1] != '\n')
{
*op->bufp++ = '\n';
op->lineno++;
}
check_expand (op, beg_of_line - beg_of_group);
bcopy ((char *) beg_of_group, (char *) op->bufp,
beg_of_line - beg_of_group);
op->bufp += beg_of_line - beg_of_group;
op->lineno += ip->lineno - beg_lineno;
check_expand (op, len);
bcopy (ptr, (char *) op->bufp, len);
op->bufp += len;
op->lineno++;
}
} }
/* /*
@ -7104,7 +7228,7 @@ do_else (buf, limit, op, keyword)
} }
if (if_stack->if_succeeded) if (if_stack->if_succeeded)
skip_if_group (ip, 0); skip_if_group (ip, 0, op);
else { else {
++if_stack->if_succeeded; /* continue processing input */ ++if_stack->if_succeeded; /* continue processing input */
output_line_command (ip, op, 1, same_file); output_line_command (ip, op, 1, same_file);
@ -8383,6 +8507,39 @@ change_newlines (start, length)
return obp - start; return obp - start;
} }
/*
* my_strerror - return the descriptive text associated with an `errno' code.
*/
char *
my_strerror (errnum)
int errnum;
{
char *result;
#ifndef VMS
#ifndef HAVE_STRERROR
result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
#else
result = strerror (errnum);
#endif
#else /* VMS */
/* VAXCRTL's strerror() takes an optional second argument, which only
matters when the first argument is EVMSERR. However, it's simplest
just to pass it unconditionally. `vaxc$errno' is declared in
<errno.h>, and maintained by the library in parallel with `errno'.
We assume that caller's `errnum' either matches the last setting of
`errno' by the library or else does not have the value `EVMSERR'. */
result = strerror (errnum, vaxc$errno);
#endif
if (!result)
result = "undocumented I/O error";
return result;
}
/* /*
* error - print error message and increment count of errors. * error - print error message and increment count of errors.
*/ */
@ -8430,10 +8587,7 @@ error_from_errno (name)
if (ip != NULL) if (ip != NULL)
fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
if (errno < sys_nerr) fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]);
else
fprintf (stderr, "%s: undocumented I/O error\n", name);
errors++; errors++;
} }
@ -8929,15 +9083,16 @@ dump_defn_1 (base, start, length, of)
U_CHAR *limit = base + start + length; U_CHAR *limit = base + start + length;
while (p < limit) { while (p < limit) {
if (*p != '\n') if (*p == '\"' || *p =='\'') {
putc (*p, of);
else if (*p == '\"' || *p =='\'') {
U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR, U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR,
NULL_PTR, NULL_PTR); NULL_PTR, NULL_PTR);
fwrite (p, p1 - p, 1, of); fwrite (p, p1 - p, 1, of);
p = p1 - 1; p = p1;
} else {
if (*p != '\n')
putc (*p, of);
p++;
} }
p++;
} }
} }
@ -9012,29 +9167,29 @@ initialize_builtins (inp, outp)
FILE_BUF *inp; FILE_BUF *inp;
FILE_BUF *outp; FILE_BUF *outp;
{ {
install ("__LINE__", -1, T_SPECLINE, 0, 0, -1); install ("__LINE__", -1, T_SPECLINE, 0, NULL_PTR, -1);
install ("__DATE__", -1, T_DATE, 0, 0, -1); install ("__DATE__", -1, T_DATE, 0, NULL_PTR, -1);
install ("__FILE__", -1, T_FILE, 0, 0, -1); install ("__FILE__", -1, T_FILE, 0, NULL_PTR, -1);
install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1); install ("__BASE_FILE__", -1, T_BASE_FILE, 0, NULL_PTR, -1);
install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1); install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, NULL_PTR, -1);
install ("__VERSION__", -1, T_VERSION, 0, 0, -1); install ("__VERSION__", -1, T_VERSION, 0, NULL_PTR, -1);
#ifndef NO_BUILTIN_SIZE_TYPE #ifndef NO_BUILTIN_SIZE_TYPE
install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1); install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, NULL_PTR, -1);
#endif #endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE #ifndef NO_BUILTIN_PTRDIFF_TYPE
install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1); install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, NULL_PTR, -1);
#endif #endif
install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1); install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, NULL_PTR, -1);
install ("__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1); install ("__USER_LABEL_PREFIX__",-1,T_USER_LABEL_PREFIX_TYPE,0,NULL_PTR, -1);
install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1); install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, NULL_PTR, -1);
install ("__TIME__", -1, T_TIME, 0, 0, -1); install ("__TIME__", -1, T_TIME, 0, NULL_PTR, -1);
if (!traditional) if (!traditional)
install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1); install ("__STDC__", -1, T_CONST, STDC_VALUE, NULL_PTR, -1);
if (objc) if (objc)
install ("__OBJC__", -1, T_CONST, 1, 0, -1); install ("__OBJC__", -1, T_CONST, 1, NULL_PTR, -1);
/* This is supplied using a -D by the compiler driver /* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */ so that it is present only when truly compiling with GNU C. */
/* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */ /* install ("__GNUC__", -1, T_CONST, 2, NULL_PTR, -1); */
if (debug_output) if (debug_output)
{ {
@ -9119,6 +9274,12 @@ make_definition (str, op)
} }
while (is_idchar[*++p]) while (is_idchar[*++p])
; ;
if (*p == '(') {
while (is_idchar[*++p] || *p == ',' || is_hor_space[*p])
;
if (*p++ != ')')
p = str; /* Error */
}
if (*p == 0) { if (*p == 0) {
buf = (U_CHAR *) alloca (p - buf + 4); buf = (U_CHAR *) alloca (p - buf + 4);
strcpy ((char *)buf, str); strcpy ((char *)buf, str);
@ -9137,7 +9298,18 @@ make_definition (str, op)
p++; p++;
q = &buf[p - str]; q = &buf[p - str];
while (*p) { while (*p) {
if (*p == '\\' && p[1] == '\n') if (*p == '\"' || *p == '\'') {
int unterminated = 0;
U_CHAR *p1 = skip_quoted_string (p, p + strlen (p), 0,
NULL_PTR, NULL_PTR, &unterminated);
if (unterminated)
return;
while (p != p1)
if (*p == '\\' && p[1] == '\n')
p += 2;
else
*q++ = *p++;
} else if (*p == '\\' && p[1] == '\n')
p += 2; p += 2;
/* Change newline chars into newline-markers. */ /* Change newline chars into newline-markers. */
else if (*p == '\n') else if (*p == '\n')
@ -9167,7 +9339,7 @@ make_definition (str, op)
; ;
/* Pass NULL instead of OP, since this is a "predefined" macro. */ /* Pass NULL instead of OP, since this is a "predefined" macro. */
do_define (buf, buf + strlen (buf), NULL, kt); do_define (buf, buf + strlen (buf), NULL_PTR, kt);
--indepth; --indepth;
} }
@ -9392,10 +9564,7 @@ perror_with_name (name)
char *name; char *name;
{ {
fprintf (stderr, "%s: ", progname); fprintf (stderr, "%s: ", progname);
if (errno < sys_nerr) fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]);
else
fprintf (stderr, "%s: undocumented I/O error\n", name);
errors++; errors++;
} }

View file

@ -55,13 +55,27 @@ struct arglist {
#endif #endif
#endif #endif
/* Find the largest host integer type and set its size and type. */
#ifndef HOST_BITS_PER_WIDE_INT
#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
#define HOST_WIDE_INT long
#else
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
#define HOST_WIDE_INT int
#endif
#endif
#ifndef NULL_PTR #ifndef NULL_PTR
#define NULL_PTR ((GENERIC_PTR)0) #define NULL_PTR ((GENERIC_PTR)0)
#endif #endif
int yylex (); int yylex ();
void yyerror (); void yyerror ();
int expression_value; HOST_WIDE_INT expression_value;
static jmp_buf parse_return_error; static jmp_buf parse_return_error;
@ -119,7 +133,7 @@ static void integer_overflow ();
static long left_shift (); static long left_shift ();
static long right_shift (); static long right_shift ();
#line 127 "cexp.y" #line 141 "cexp.y"
typedef union { typedef union {
struct constant {long value; int unsignedp;} integer; struct constant {long value; int unsignedp;} integer;
struct name {U_CHAR *address; int length;} name; struct name {U_CHAR *address; int length;} name;
@ -218,10 +232,10 @@ static const short yyrhs[] = { 35,
#if YYDEBUG != 0 #if YYDEBUG != 0
static const short yyrline[] = { 0, static const short yyrline[] = { 0,
159, 164, 165, 172, 177, 180, 182, 185, 189, 191, 173, 178, 179, 186, 191, 194, 196, 199, 203, 205,
196, 201, 213, 228, 239, 246, 253, 259, 265, 268, 210, 215, 227, 242, 253, 260, 267, 273, 279, 282,
271, 277, 283, 289, 295, 298, 301, 304, 307, 310, 285, 291, 297, 303, 309, 312, 315, 318, 321, 324,
313, 315, 317, 322, 324, 337 327, 329, 331, 336, 338, 351
}; };
static const char * const yytname[] = { "$","error","$illegal.","INT","CHAR", static const char * const yytname[] = { "$","error","$illegal.","INT","CHAR",
@ -805,59 +819,59 @@ yyparse(YYPARSE_PARAM)
switch (yyn) { switch (yyn) {
case 1: case 1:
#line 160 "cexp.y" #line 174 "cexp.y"
{ expression_value = yyvsp[0].integer.value; ; { expression_value = yyvsp[0].integer.value; ;
break;} break;}
case 3: case 3:
#line 166 "cexp.y" #line 180 "cexp.y"
{ if (pedantic) { if (pedantic)
pedwarn ("comma operator in operand of `#if'"); pedwarn ("comma operator in operand of `#if'");
yyval.integer = yyvsp[0].integer; ; yyval.integer = yyvsp[0].integer; ;
break;} break;}
case 4: case 4:
#line 173 "cexp.y" #line 187 "cexp.y"
{ yyval.integer.value = - yyvsp[0].integer.value; { yyval.integer.value = - yyvsp[0].integer.value;
if ((yyval.integer.value & yyvsp[0].integer.value) < 0 && ! yyvsp[0].integer.unsignedp) if ((yyval.integer.value & yyvsp[0].integer.value) < 0 && ! yyvsp[0].integer.unsignedp)
integer_overflow (); integer_overflow ();
yyval.integer.unsignedp = yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[0].integer.unsignedp; ;
break;} break;}
case 5: case 5:
#line 178 "cexp.y" #line 192 "cexp.y"
{ yyval.integer.value = ! yyvsp[0].integer.value; { yyval.integer.value = ! yyvsp[0].integer.value;
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 6: case 6:
#line 181 "cexp.y" #line 195 "cexp.y"
{ yyval.integer = yyvsp[0].integer; ; { yyval.integer = yyvsp[0].integer; ;
break;} break;}
case 7: case 7:
#line 183 "cexp.y" #line 197 "cexp.y"
{ yyval.integer.value = ~ yyvsp[0].integer.value; { yyval.integer.value = ~ yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[0].integer.unsignedp; ;
break;} break;}
case 8: case 8:
#line 186 "cexp.y" #line 200 "cexp.y"
{ yyval.integer.value = check_assertion (yyvsp[0].name.address, yyvsp[0].name.length, { yyval.integer.value = check_assertion (yyvsp[0].name.address, yyvsp[0].name.length,
0, NULL_PTR); 0, NULL_PTR);
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 9: case 9:
#line 190 "cexp.y" #line 204 "cexp.y"
{ keyword_parsing = 1; ; { keyword_parsing = 1; ;
break;} break;}
case 10: case 10:
#line 192 "cexp.y" #line 206 "cexp.y"
{ yyval.integer.value = check_assertion (yyvsp[-4].name.address, yyvsp[-4].name.length, { yyval.integer.value = check_assertion (yyvsp[-4].name.address, yyvsp[-4].name.length,
1, yyvsp[-1].keywords); 1, yyvsp[-1].keywords);
keyword_parsing = 0; keyword_parsing = 0;
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 11: case 11:
#line 197 "cexp.y" #line 211 "cexp.y"
{ yyval.integer = yyvsp[-1].integer; ; { yyval.integer = yyvsp[-1].integer; ;
break;} break;}
case 12: case 12:
#line 202 "cexp.y" #line 216 "cexp.y"
{ yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; { yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp;
if (yyval.integer.unsignedp) if (yyval.integer.unsignedp)
yyval.integer.value = (unsigned long) yyvsp[-2].integer.value * yyvsp[0].integer.value; yyval.integer.value = (unsigned long) yyvsp[-2].integer.value * yyvsp[0].integer.value;
@ -871,7 +885,7 @@ case 12:
} ; } ;
break;} break;}
case 13: case 13:
#line 214 "cexp.y" #line 228 "cexp.y"
{ if (yyvsp[0].integer.value == 0) { if (yyvsp[0].integer.value == 0)
{ {
error ("division by zero in #if"); error ("division by zero in #if");
@ -888,7 +902,7 @@ case 13:
} ; } ;
break;} break;}
case 14: case 14:
#line 229 "cexp.y" #line 243 "cexp.y"
{ if (yyvsp[0].integer.value == 0) { if (yyvsp[0].integer.value == 0)
{ {
error ("division by zero in #if"); error ("division by zero in #if");
@ -901,7 +915,7 @@ case 14:
yyval.integer.value = yyvsp[-2].integer.value % yyvsp[0].integer.value; ; yyval.integer.value = yyvsp[-2].integer.value % yyvsp[0].integer.value; ;
break;} break;}
case 15: case 15:
#line 240 "cexp.y" #line 254 "cexp.y"
{ yyval.integer.value = yyvsp[-2].integer.value + yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-2].integer.value + yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp;
if (! yyval.integer.unsignedp if (! yyval.integer.unsignedp
@ -910,7 +924,7 @@ case 15:
integer_overflow (); ; integer_overflow (); ;
break;} break;}
case 16: case 16:
#line 247 "cexp.y" #line 261 "cexp.y"
{ yyval.integer.value = yyvsp[-2].integer.value - yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-2].integer.value - yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp;
if (! yyval.integer.unsignedp if (! yyval.integer.unsignedp
@ -919,7 +933,7 @@ case 16:
integer_overflow (); ; integer_overflow (); ;
break;} break;}
case 17: case 17:
#line 254 "cexp.y" #line 268 "cexp.y"
{ yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp; { yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp;
if (yyvsp[0].integer.value < 0 && ! yyvsp[0].integer.unsignedp) if (yyvsp[0].integer.value < 0 && ! yyvsp[0].integer.unsignedp)
yyval.integer.value = right_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value); yyval.integer.value = right_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value);
@ -927,7 +941,7 @@ case 17:
yyval.integer.value = left_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ; yyval.integer.value = left_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ;
break;} break;}
case 18: case 18:
#line 260 "cexp.y" #line 274 "cexp.y"
{ yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp; { yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp;
if (yyvsp[0].integer.value < 0 && ! yyvsp[0].integer.unsignedp) if (yyvsp[0].integer.value < 0 && ! yyvsp[0].integer.unsignedp)
yyval.integer.value = left_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value); yyval.integer.value = left_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value);
@ -935,17 +949,17 @@ case 18:
yyval.integer.value = right_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ; yyval.integer.value = right_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ;
break;} break;}
case 19: case 19:
#line 266 "cexp.y" #line 280 "cexp.y"
{ yyval.integer.value = (yyvsp[-2].integer.value == yyvsp[0].integer.value); { yyval.integer.value = (yyvsp[-2].integer.value == yyvsp[0].integer.value);
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 20: case 20:
#line 269 "cexp.y" #line 283 "cexp.y"
{ yyval.integer.value = (yyvsp[-2].integer.value != yyvsp[0].integer.value); { yyval.integer.value = (yyvsp[-2].integer.value != yyvsp[0].integer.value);
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 21: case 21:
#line 272 "cexp.y" #line 286 "cexp.y"
{ yyval.integer.unsignedp = 0; { yyval.integer.unsignedp = 0;
if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp) if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp)
yyval.integer.value = (unsigned long) yyvsp[-2].integer.value <= yyvsp[0].integer.value; yyval.integer.value = (unsigned long) yyvsp[-2].integer.value <= yyvsp[0].integer.value;
@ -953,7 +967,7 @@ case 21:
yyval.integer.value = yyvsp[-2].integer.value <= yyvsp[0].integer.value; ; yyval.integer.value = yyvsp[-2].integer.value <= yyvsp[0].integer.value; ;
break;} break;}
case 22: case 22:
#line 278 "cexp.y" #line 292 "cexp.y"
{ yyval.integer.unsignedp = 0; { yyval.integer.unsignedp = 0;
if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp) if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp)
yyval.integer.value = (unsigned long) yyvsp[-2].integer.value >= yyvsp[0].integer.value; yyval.integer.value = (unsigned long) yyvsp[-2].integer.value >= yyvsp[0].integer.value;
@ -961,7 +975,7 @@ case 22:
yyval.integer.value = yyvsp[-2].integer.value >= yyvsp[0].integer.value; ; yyval.integer.value = yyvsp[-2].integer.value >= yyvsp[0].integer.value; ;
break;} break;}
case 23: case 23:
#line 284 "cexp.y" #line 298 "cexp.y"
{ yyval.integer.unsignedp = 0; { yyval.integer.unsignedp = 0;
if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp) if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp)
yyval.integer.value = (unsigned long) yyvsp[-2].integer.value < yyvsp[0].integer.value; yyval.integer.value = (unsigned long) yyvsp[-2].integer.value < yyvsp[0].integer.value;
@ -969,7 +983,7 @@ case 23:
yyval.integer.value = yyvsp[-2].integer.value < yyvsp[0].integer.value; ; yyval.integer.value = yyvsp[-2].integer.value < yyvsp[0].integer.value; ;
break;} break;}
case 24: case 24:
#line 290 "cexp.y" #line 304 "cexp.y"
{ yyval.integer.unsignedp = 0; { yyval.integer.unsignedp = 0;
if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp) if (yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp)
yyval.integer.value = (unsigned long) yyvsp[-2].integer.value > yyvsp[0].integer.value; yyval.integer.value = (unsigned long) yyvsp[-2].integer.value > yyvsp[0].integer.value;
@ -977,54 +991,54 @@ case 24:
yyval.integer.value = yyvsp[-2].integer.value > yyvsp[0].integer.value; ; yyval.integer.value = yyvsp[-2].integer.value > yyvsp[0].integer.value; ;
break;} break;}
case 25: case 25:
#line 296 "cexp.y" #line 310 "cexp.y"
{ yyval.integer.value = yyvsp[-2].integer.value & yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-2].integer.value & yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ;
break;} break;}
case 26: case 26:
#line 299 "cexp.y" #line 313 "cexp.y"
{ yyval.integer.value = yyvsp[-2].integer.value ^ yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-2].integer.value ^ yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ;
break;} break;}
case 27: case 27:
#line 302 "cexp.y" #line 316 "cexp.y"
{ yyval.integer.value = yyvsp[-2].integer.value | yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-2].integer.value | yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ;
break;} break;}
case 28: case 28:
#line 305 "cexp.y" #line 319 "cexp.y"
{ yyval.integer.value = (yyvsp[-2].integer.value && yyvsp[0].integer.value); { yyval.integer.value = (yyvsp[-2].integer.value && yyvsp[0].integer.value);
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 29: case 29:
#line 308 "cexp.y" #line 322 "cexp.y"
{ yyval.integer.value = (yyvsp[-2].integer.value || yyvsp[0].integer.value); { yyval.integer.value = (yyvsp[-2].integer.value || yyvsp[0].integer.value);
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 30: case 30:
#line 311 "cexp.y" #line 325 "cexp.y"
{ yyval.integer.value = yyvsp[-4].integer.value ? yyvsp[-2].integer.value : yyvsp[0].integer.value; { yyval.integer.value = yyvsp[-4].integer.value ? yyvsp[-2].integer.value : yyvsp[0].integer.value;
yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ; yyval.integer.unsignedp = yyvsp[-2].integer.unsignedp || yyvsp[0].integer.unsignedp; ;
break;} break;}
case 31: case 31:
#line 314 "cexp.y" #line 328 "cexp.y"
{ yyval.integer = yylval.integer; ; { yyval.integer = yylval.integer; ;
break;} break;}
case 32: case 32:
#line 316 "cexp.y" #line 330 "cexp.y"
{ yyval.integer = yylval.integer; ; { yyval.integer = yylval.integer; ;
break;} break;}
case 33: case 33:
#line 318 "cexp.y" #line 332 "cexp.y"
{ yyval.integer.value = 0; { yyval.integer.value = 0;
yyval.integer.unsignedp = 0; ; yyval.integer.unsignedp = 0; ;
break;} break;}
case 34: case 34:
#line 323 "cexp.y" #line 337 "cexp.y"
{ yyval.keywords = 0; ; { yyval.keywords = 0; ;
break;} break;}
case 35: case 35:
#line 325 "cexp.y" #line 339 "cexp.y"
{ struct arglist *temp; { struct arglist *temp;
yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist)); yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist));
yyval.keywords->next = yyvsp[-2].keywords; yyval.keywords->next = yyvsp[-2].keywords;
@ -1039,7 +1053,7 @@ case 35:
temp->next->length = 1; ; temp->next->length = 1; ;
break;} break;}
case 36: case 36:
#line 338 "cexp.y" #line 352 "cexp.y"
{ yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist)); { yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist));
yyval.keywords->name = yyvsp[-1].name.address; yyval.keywords->name = yyvsp[-1].name.address;
yyval.keywords->length = yyvsp[-1].name.length; yyval.keywords->length = yyvsp[-1].name.length;
@ -1243,7 +1257,7 @@ case 36:
yystate = yyn; yystate = yyn;
goto yynewstate; goto yynewstate;
} }
#line 343 "cexp.y" #line 357 "cexp.y"
/* During parsing of a C expression, the pointer to the next character /* During parsing of a C expression, the pointer to the next character
@ -1809,7 +1823,7 @@ right_shift (a, b)
/* We do not support C comments. They should be removed before /* We do not support C comments. They should be removed before
this function is called. */ this function is called. */
int HOST_WIDE_INT
parse_c_expression (string) parse_c_expression (string)
char *string; char *string;
{ {
@ -1858,7 +1872,7 @@ main ()
if (buf[n] == EOF) if (buf[n] == EOF)
break; break;
buf[n] = '\0'; buf[n] = '\0';
printf ("parser returned %d\n", parse_c_expression (buf)); printf ("parser returned %ld\n", parse_c_expression (buf));
} }
return 0; return 0;

View file

@ -372,6 +372,13 @@ extern rtx bcmp_libfunc;
extern rtx memset_libfunc; extern rtx memset_libfunc;
extern rtx bzero_libfunc; extern rtx bzero_libfunc;
extern rtx eqhf2_libfunc;
extern rtx nehf2_libfunc;
extern rtx gthf2_libfunc;
extern rtx gehf2_libfunc;
extern rtx lthf2_libfunc;
extern rtx lehf2_libfunc;
extern rtx eqsf2_libfunc; extern rtx eqsf2_libfunc;
extern rtx nesf2_libfunc; extern rtx nesf2_libfunc;
extern rtx gtsf2_libfunc; extern rtx gtsf2_libfunc;

View file

@ -63,18 +63,23 @@ extern void __do_global_dtors ();
we define it once here as a macro to avoid various instances getting we define it once here as a macro to avoid various instances getting
out-of-sync with one another. */ out-of-sync with one another. */
/* The first word may or may not contain the number of pointers in the table. /* Some systems place the number of pointers
in the first word of the table.
On other systems, that word is -1.
In all cases, the table is null-terminated. In all cases, the table is null-terminated.
We ignore the first word and scan up to the null. */ If the length is not recorded, count up to the null. */
/* Some systems use a different strategy for finding the ctors. /* Some systems use a different strategy for finding the ctors.
For example, svr3. */ For example, svr3. */
#ifndef DO_GLOBAL_CTORS_BODY #ifndef DO_GLOBAL_CTORS_BODY
#define DO_GLOBAL_CTORS_BODY \ #define DO_GLOBAL_CTORS_BODY \
do { \ do { \
func_ptr *p; \ unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; \
for (p = __CTOR_LIST__ + 1; *p; ) \ unsigned i; \
(*p++) (); \ if (nptrs == -1) \
} while (0) for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++); \
for (i = nptrs; i >= 1; i--) \
__CTOR_LIST__[i] (); \
} while (0)
#endif #endif

View file

@ -1,4 +1,4 @@
/* Definitions of target machine for GNU compiler for Intel 80386. /* Definitions of target machine for GNU compiler for Intel X86 (386, 486, pentium)
Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc. Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
@ -62,77 +62,130 @@ extern int target_flags;
#define TARGET_CPU_DEFAULT 0 #define TARGET_CPU_DEFAULT 0
#endif #endif
/* Compile 80387 insns for floating point (not library calls). */ /* Masks for the -m switches */
#define TARGET_80387 (target_flags & 1) #define MASK_80387 000000000001 /* Hardware floating point */
/* Compile code for an i486. */ #define MASK_486 000000000002 /* 80486 specific */
#define TARGET_486 (target_flags & 2) #define MASK_NOTUSED 000000000004 /* bit not currently used */
#define MASK_RTD 000000000010 /* Use ret that pops args */
#define MASK_REGPARM 000000000020 /* Pass args in eax, edx */
#define MASK_SVR3_SHLIB 000000000040 /* Uninit locals into bss */
#define MASK_IEEE_FP 000000000100 /* IEEE fp comparisons */
#define MASK_FLOAT_RETURNS 000000000200 /* Return float in st(0) */
#define MASK_NO_FANCY_MATH_387 000000000400 /* Disable sin, cos, sqrt */
/* Temporary codegen switches */
#define MASK_DEBUG_ADDR 000001000000 /* Debug GO_IF_LEGITIMATE_ADDRESS */
#define MASK_NO_WIDE_MULTIPLY 000002000000 /* Disable 32x32->64 multiplies */
#define MASK_NO_MOVE 000004000000 /* Don't generate mem->mem */
/* Use the floating point instructions */
#define TARGET_80387 (target_flags & MASK_80387)
/* Compile using ret insn that pops args. /* Compile using ret insn that pops args.
This will not work unless you use prototypes at least This will not work unless you use prototypes at least
for all functions that can take varying numbers of args. */ for all functions that can take varying numbers of args. */
#define TARGET_RTD (target_flags & 8) #define TARGET_RTD (target_flags & MASK_RTD)
/* Compile passing first two args in regs 0 and 1. /* Compile passing first two args in regs 0 and 1.
This exists only to test compiler features that will This exists only to test compiler features that will
be needed for RISC chips. It is not usable be needed for RISC chips. It is not usable
and is not intended to be usable on this cpu. */ and is not intended to be usable on this cpu. */
#define TARGET_REGPARM (target_flags & 020) #define TARGET_REGPARM (target_flags & MASK_RTD)
/* Put uninitialized locals into bss, not data. /* Put uninitialized locals into bss, not data.
Meaningful only on svr3. */ Meaningful only on svr3. */
#define TARGET_SVR3_SHLIB (target_flags & 040) #define TARGET_SVR3_SHLIB (target_flags & MASK_SVR3_SHLIB)
/* Use IEEE floating point comparisons. These handle correctly the cases /* Use IEEE floating point comparisons. These handle correctly the cases
where the result of a comparison is unordered. Normally SIGFPE is where the result of a comparison is unordered. Normally SIGFPE is
generated in such cases, in which case this isn't needed. */ generated in such cases, in which case this isn't needed. */
#define TARGET_IEEE_FP (target_flags & 0100) #define TARGET_IEEE_FP (target_flags & MASK_IEEE_FP)
/* Functions that return a floating point value may return that value /* Functions that return a floating point value may return that value
in the 387 FPU or in 386 integer registers. If set, this flag causes in the 387 FPU or in 386 integer registers. If set, this flag causes
the 387 to be used, which is compatible with most calling conventions. */ the 387 to be used, which is compatible with most calling conventions. */
#define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & 0200) #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & MASK_FLOAT_RETURNS)
/* Disable generation of FP sin, cos and sqrt operations for 387. /* Disable generation of FP sin, cos and sqrt operations for 387.
This is because FreeBSD lacks these in the math-emulator-code */ This is because FreeBSD lacks these in the math-emulator-code */
#define TARGET_NO_FANCY_MATH_387 (target_flags & 0400) #define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387)
/* Macro to define tables used to set the flags. /* Temporary switches for tuning code generation */
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
where VALUE is the bits to set or minus the bits to clear.
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \ /* Disable 32x32->64 bit multiplies that are used for long long multiplies
{ { "80387", 1}, \ and division by constants, but sometimes cause reload problems. */
{ "no-80387", -1}, \ #define TARGET_NO_WIDE_MULTIPLY (target_flags & MASK_NO_WIDE_MULTIPLY)
{ "soft-float", -1}, \ #define TARGET_WIDE_MULTIPLY (!TARGET_NO_WIDE_MULTIPLY)
{ "no-soft-float", 1}, \
{ "486", 2}, \
{ "no-486", -2}, \
{ "386", -2}, \
{ "rtd", 8}, \
{ "no-rtd", -8}, \
{ "regparm", 020}, \
{ "no-regparm", -020}, \
{ "svr3-shlib", 040}, \
{ "no-svr3-shlib", -040}, \
{ "ieee-fp", 0100}, \
{ "no-ieee-fp", -0100}, \
{ "fp-ret-in-387", 0200}, \
{ "no-fp-ret-in-387", -0200}, \
{ "no-fancy-math-387", 0400}, \
{ "fancy-math-387", -0400}, \
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
/* This is meant to be redefined in the host dependent files */ /* Debug GO_IF_LEGITIMATE_ADDRESS */
#define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR)
/* Hack macros for tuning code generation */
#define TARGET_MOVE ((target_flags & MASK_NO_MOVE) == 0) /* Don't generate memory->memory */
/* Specific hardware switches */
#define TARGET_486 (target_flags & MASK_486) /* 80486DX, 80486SX, 80486DX[24] */
#define TARGET_386 (!TARGET_486) /* 80386 */
#define TARGET_SWITCHES \
{ { "80387", MASK_80387 }, \
{ "no-80387", -MASK_80387 }, \
{ "hard-float", MASK_80387 }, \
{ "soft-float", -MASK_80387 }, \
{ "no-soft-float", MASK_80387 }, \
{ "386", -MASK_486 }, \
{ "no-386", MASK_486 }, \
{ "486", MASK_486 }, \
{ "no-486", -MASK_486 }, \
{ "rtd", MASK_RTD }, \
{ "no-rtd", -MASK_RTD }, \
{ "regparm", MASK_REGPARM }, \
{ "no-regparm", -MASK_REGPARM }, \
{ "svr3-shlib", MASK_SVR3_SHLIB }, \
{ "no-svr3-shlib", -MASK_SVR3_SHLIB }, \
{ "ieee-fp", MASK_IEEE_FP }, \
{ "no-ieee-fp", -MASK_IEEE_FP }, \
{ "fp-ret-in-387", MASK_FLOAT_RETURNS }, \
{ "no-fp-ret-in-387", -MASK_FLOAT_RETURNS }, \
{ "no-fancy-math-387", MASK_NO_FANCY_MATH_387 }, \
{ "fancy-math-387", -MASK_NO_FANCY_MATH_387 }, \
{ "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \
{ "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \
{ "debug-addr", MASK_DEBUG_ADDR }, \
{ "no-debug-addr", -MASK_DEBUG_ADDR }, \
{ "move", -MASK_NO_MOVE }, \
{ "no-move", MASK_NO_MOVE }, \
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
/* This macro is similar to `TARGET_SWITCHES' but defines names of
command options that have values. Its definition is an
initializer with a subgrouping for each command option.
Each subgrouping contains a string constant, that defines the
fixed part of the option name, and the address of a variable. The
variable, type `char *', is set to the variable part of the given
option if the fixed part matches. The actual option name is made
by appending `-m' to the specified name. */
#define TARGET_OPTIONS \
{ { "reg-alloc=", &i386_reg_alloc_order }, \
SUBTARGET_OPTIONS }
/* Sometimes certain combinations of command options do not make
sense on a particular target machine. You can define a macro
`OVERRIDE_OPTIONS' to take account of this. This macro, if
defined, is executed once just after all the command options have
been parsed.
Don't use this macro to turn on various extra optimizations for
`-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
#define OVERRIDE_OPTIONS override_options ()
/* These are meant to be redefined in the host dependent files */
#define SUBTARGET_SWITCHES #define SUBTARGET_SWITCHES
#define SUBTARGET_OPTIONS
#define OVERRIDE_OPTIONS \
{ \
SUBTARGET_OVERRIDE_OPTIONS \
}
/* This is meant to be redefined in the host dependent files */
#define SUBTARGET_OVERRIDE_OPTIONS
/* target machine storage layout */ /* target machine storage layout */
@ -263,11 +316,39 @@ extern int target_flags;
listed once, even those in FIXED_REGISTERS. List frame pointer listed once, even those in FIXED_REGISTERS. List frame pointer
late and fixed registers last. Note that, in general, we prefer late and fixed registers last. Note that, in general, we prefer
registers listed in CALL_USED_REGISTERS, keeping the others registers listed in CALL_USED_REGISTERS, keeping the others
available for storage of persistent values. */ available for storage of persistent values.
Three different versions of REG_ALLOC_ORDER have been tried:
If the order is edx, ecx, eax, ... it produces a slightly faster compiler,
but slower code on simple functions returning values in eax.
If the order is eax, ecx, edx, ... it causes reload to abort when compiling
perl 4.036 due to not being able to create a DImode register (to hold a 2
word union).
If the order is eax, edx, ecx, ... it produces better code for simple
functions, and a slightly slower compiler. Users complained about the code
generated by allocating edx first, so restore the 'natural' order of things. */
#define REG_ALLOC_ORDER \ #define REG_ALLOC_ORDER \
/*ax,cx,dx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \ /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
/* A C statement (sans semicolon) to choose the order in which to
allocate hard registers for pseudo-registers local to a basic
block.
Store the desired register order in the array `reg_alloc_order'.
Element 0 should be the register to allocate first; element 1, the
next register; and so on.
The macro body should not assume anything about the contents of
`reg_alloc_order' before execution of the macro.
On most machines, it is not necessary to define this macro. */
#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
/* Macro to conditionally modify fixed_regs/call_used_regs. */ /* Macro to conditionally modify fixed_regs/call_used_regs. */
#define CONDITIONAL_REGISTER_USAGE \ #define CONDITIONAL_REGISTER_USAGE \
@ -381,6 +462,27 @@ extern int target_flags;
/* Place in which caller passes the structure value address. /* Place in which caller passes the structure value address.
0 means push the value on the stack like an argument. */ 0 means push the value on the stack like an argument. */
#define STRUCT_VALUE 0 #define STRUCT_VALUE 0
/* A C expression which can inhibit the returning of certain function
values in registers, based on the type of value. A nonzero value
says to return the function value in memory, just as large
structures are always returned. Here TYPE will be a C expression
of type `tree', representing the data type of the value.
Note that values of mode `BLKmode' must be explicitly handled by
this macro. Also, the option `-fpcc-struct-return' takes effect
regardless of this macro. On most systems, it is possible to
leave the macro undefined; this causes a default definition to be
used, whose value is the constant 1 for `BLKmode' values, and 0
otherwise.
Do not use this macro to indicate that structures and unions
should always be returned in memory. You should instead use
`DEFAULT_PCC_STRUCT_RETURN' to indicate this. */
#define RETURN_IN_MEMORY(TYPE) \
((TYPE_MODE (TYPE) == BLKmode) || int_size_in_bytes (TYPE) > 12)
/* Define the classes of registers for register constraints in the /* Define the classes of registers for register constraints in the
machine description. Also define ranges of constants. machine description. Also define ranges of constants.
@ -448,7 +550,7 @@ enum reg_class
0x3, /* AD_REGS */ \ 0x3, /* AD_REGS */ \
0xf, /* Q_REGS */ \ 0xf, /* Q_REGS */ \
0x10, 0x20, /* SIREG, DIREG */ \ 0x10, 0x20, /* SIREG, DIREG */ \
0x1007f, /* INDEX_REGS */ \ 0x07f, /* INDEX_REGS */ \
0x100ff, /* GENERAL_REGS */ \ 0x100ff, /* GENERAL_REGS */ \
0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \ 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \
0xff00, /* FLOAT_REGS */ \ 0xff00, /* FLOAT_REGS */ \
@ -459,7 +561,6 @@ enum reg_class
reg number REGNO. This could be a conditional expression reg number REGNO. This could be a conditional expression
or could index an array. */ or could index an array. */
extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO]) #define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
/* When defined, the compiler allows registers explicitly used in the /* When defined, the compiler allows registers explicitly used in the
@ -591,6 +692,32 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define CLASS_MAX_NREGS(CLASS, MODE) \ #define CLASS_MAX_NREGS(CLASS, MODE) \
(FLOAT_CLASS_P (CLASS) ? 1 : \ (FLOAT_CLASS_P (CLASS) ? 1 : \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* A C expression whose value is nonzero if pseudos that have been
assigned to registers of class CLASS would likely be spilled
because registers of CLASS are needed for spill registers.
The default value of this macro returns 1 if CLASS has exactly one
register and zero otherwise. On most machines, this default
should be used. Only define this macro to some other expression
if pseudo allocated by `local-alloc.c' end up in memory because
their hard registers were needed for spill regisers. If this
macro returns nonzero for those classes, those pseudos will only
be allocated by `global.c', which knows how to reallocate the
pseudo to another register. If there would not be another
register available for reallocation, you should not change the
definition of this macro since the only effect of such a
definition would be to slow down register allocation. */
#define CLASS_LIKELY_SPILLED_P(CLASS) \
(((CLASS) == AREG) \
|| ((CLASS) == DREG) \
|| ((CLASS) == CREG) \
|| ((CLASS) == BREG) \
|| ((CLASS) == AD_REGS) \
|| ((CLASS) == SIREG) \
|| ((CLASS) == DIREG))
/* Stack layout; function entry, exit and calling. */ /* Stack layout; function entry, exit and calling. */
@ -762,6 +889,102 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
} \ } \
} }
/* A C statement or compound statement to output to FILE some
assembler code to initialize basic-block profiling for the current
object module. This code should call the subroutine
`__bb_init_func' once per object module, passing it as its sole
argument the address of a block allocated in the object module.
The name of the block is a local symbol made with this statement:
ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
Of course, since you are writing the definition of
`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
can take a short cut in the definition of this macro and use the
name that you know will result.
The first word of this block is a flag which will be nonzero if the
object module has already been initialized. So test this word
first, and do not call `__bb_init_func' if the flag is nonzero. */
#undef FUNCTION_BLOCK_PROFILER
#define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \
do \
{ \
static int num_func = 0; \
rtx xops[8]; \
char block_table[80], false_label[80]; \
\
ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \
ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \
\
xops[0] = const0_rtx; \
xops[1] = gen_rtx (SYMBOL_REF, VOIDmode, block_table); \
xops[2] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, false_label)); \
xops[3] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, "__bb_init_func")); \
xops[4] = gen_rtx (MEM, Pmode, xops[1]); \
xops[5] = stack_pointer_rtx; \
xops[6] = GEN_INT (4); \
xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \
\
CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \
CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \
\
output_asm_insn (AS2(cmp%L4,%0,%4), xops); \
output_asm_insn (AS1(jne,%2), xops); \
\
if (!flag_pic) \
output_asm_insn (AS1(push%L1,%1), xops); \
else \
{ \
output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \
output_asm_insn (AS1 (push%L7,%7), xops); \
} \
\
output_asm_insn (AS1(call,%P3), xops); \
output_asm_insn (AS2(add%L0,%6,%5), xops); \
ASM_OUTPUT_INTERNAL_LABEL (STREAM, "LPBZ", num_func); \
num_func++; \
} \
while (0)
/* A C statement or compound statement to increment the count
associated with the basic block number BLOCKNO. Basic blocks are
numbered separately from zero within each compilation. The count
associated with block number BLOCKNO is at index BLOCKNO in a
vector of words; the name of this array is a local symbol made
with this statement:
ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
Of course, since you are writing the definition of
`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
can take a short cut in the definition of this macro and use the
name that you know will result. */
#define BLOCK_PROFILER(STREAM, BLOCKNO) \
do \
{ \
rtx xops[1], cnt_rtx; \
char counts[80]; \
\
ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \
cnt_rtx = gen_rtx (SYMBOL_REF, VOIDmode, counts); \
SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \
\
if (BLOCKNO) \
cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \
\
if (flag_pic) \
cnt_rtx = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, cnt_rtx); \
\
xops[0] = gen_rtx (MEM, SImode, cnt_rtx); \
output_asm_insn (AS1(inc%L0,%0), xops); \
} \
while (0)
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in the stack pointer does not matter. The value is tested only in
functions that have frame pointers. functions that have frame pointers.
@ -925,36 +1148,35 @@ do { \
After reload, it makes no difference, since pseudo regs have After reload, it makes no difference, since pseudo regs have
been eliminated by then. */ been eliminated by then. */
#ifndef REG_OK_STRICT
/* Nonzero if X is a hard reg that can be used as an index or if /* Non strict versions, pseudos are ok */
it is a pseudo reg. */ #define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
(REGNO (X) < STACK_POINTER_REGNUM \
#define REG_OK_FOR_INDEX_P(X) \
(REGNO (X) < STACK_POINTER_REGNUM \
|| REGNO (X) >= FIRST_PSEUDO_REGISTER) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
/* Nonzero if X is a hard reg that can be used as a base reg #define REG_OK_FOR_BASE_NONSTRICT_P(X) \
of if it is a pseudo reg. */ (REGNO (X) <= STACK_POINTER_REGNUM \
/* ?wfs */ || REGNO (X) == ARG_POINTER_REGNUM \
|| REGNO (X) >= FIRST_PSEUDO_REGISTER)
#define REG_OK_FOR_BASE_P(X) \ #define REG_OK_FOR_STRREG_NONSTRICT_P(X) \
(REGNO (X) <= STACK_POINTER_REGNUM \
|| REGNO (X) == ARG_POINTER_REGNUM \
|| REGNO(X) >= FIRST_PSEUDO_REGISTER)
#define REG_OK_FOR_STRREG_P(X) \
(REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER) (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
#else /* Strict versions, hard registers only */
#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
/* Nonzero if X is a hard reg that can be used as an index. */ #define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) #define REG_OK_FOR_STRREG_STRICT_P(X) \
/* Nonzero if X is a hard reg that can be used as a base reg. */
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define REG_OK_FOR_STRREG_P(X) \
(REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X))) (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X)))
#ifndef REG_OK_STRICT
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_NONSTRICT_P(X)
#else
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_STRICT_P(X)
#endif #endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@ -980,62 +1202,22 @@ do { \
#define LEGITIMATE_CONSTANT_P(X) 1 #define LEGITIMATE_CONSTANT_P(X) 1
#define GO_IF_INDEXABLE_BASE(X, ADDR) \ #ifdef REG_OK_STRICT
if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
#define LEGITIMATE_INDEX_REG_P(X) \
(GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
/* Return 1 if X is an index or an index times a scale. */
#define LEGITIMATE_INDEX_P(X) \
(LEGITIMATE_INDEX_REG_P (X) \
|| (GET_CODE (X) == MULT \
&& LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
&& (INTVAL (XEXP (X, 1)) == 2 \
|| INTVAL (XEXP (X, 1)) == 4 \
|| INTVAL (XEXP (X, 1)) == 8)))
/* Go to ADDR if X is an index term, a base reg, or a sum of those. */
#define GO_IF_INDEXING(X, ADDR) \
{ if (LEGITIMATE_INDEX_P (X)) goto ADDR; \
GO_IF_INDEXABLE_BASE (X, ADDR); \
if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \
{ GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
{ GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
/* We used to allow this, but it isn't ever used.
|| ((GET_CODE (X) == POST_DEC || GET_CODE (X) == POST_INC) \
&& REG_P (XEXP (X, 0)) \
&& REG_OK_FOR_STRREG_P (XEXP (X, 0))) \
*/
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ \ { \
if (CONSTANT_ADDRESS_P (X) \ if (legitimate_address_p (MODE, X, 1)) \
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \
goto ADDR; \ goto ADDR; \
GO_IF_INDEXING (X, ADDR); \
if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
{ \
rtx x0 = XEXP (X, 0); \
if (! flag_pic || ! SYMBOLIC_CONST (XEXP (X, 1))) \
{ GO_IF_INDEXING (x0, ADDR); } \
else if (x0 == pic_offset_table_rtx) \
goto ADDR; \
else if (GET_CODE (x0) == PLUS) \
{ \
if (XEXP (x0, 0) == pic_offset_table_rtx) \
{ GO_IF_INDEXABLE_BASE (XEXP (x0, 1), ADDR); } \
if (XEXP (x0, 1) == pic_offset_table_rtx) \
{ GO_IF_INDEXABLE_BASE (XEXP (x0, 0), ADDR); } \
} \
} \
} }
#else
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ \
if (legitimate_address_p (MODE, X, 0)) \
goto ADDR; \
}
#endif
/* Try machine-dependent ways of modifying an illegitimate address /* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address. to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c. This macro is used in only one place: `memory_address' in explow.c.
@ -1057,38 +1239,13 @@ do { \
When -fpic is used, special handling is needed for symbolic references. When -fpic is used, special handling is needed for symbolic references.
See comments by legitimize_pic_address in i386.c for details. */ See comments by legitimize_pic_address in i386.c for details. */
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
{ extern rtx legitimize_pic_address (); \ { \
int ch = (X) != (OLDX); \ rtx orig_x = (X); \
if (flag_pic && SYMBOLIC_CONST (X)) \ (X) = legitimize_address (X, OLDX, MODE); \
{ \ if (memory_address_p (MODE, X)) \
(X) = legitimize_pic_address (X, 0); \ goto WIN; \
if (memory_address_p (MODE, X)) \ }
goto WIN; \
} \
if (GET_CODE (X) == PLUS) \
{ if (GET_CODE (XEXP (X, 0)) == MULT) \
ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \
if (GET_CODE (XEXP (X, 1)) == MULT) \
ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \
if (ch && GET_CODE (XEXP (X, 1)) == REG \
&& GET_CODE (XEXP (X, 0)) == REG) \
goto WIN; \
if (flag_pic && SYMBOLIC_CONST (XEXP (X, 1))) \
ch = 1, (X) = legitimize_pic_address (X, 0); \
if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
if (GET_CODE (XEXP (X, 0)) == REG) \
{ register rtx temp = gen_reg_rtx (Pmode); \
register rtx val = force_operand (XEXP (X, 1), temp); \
if (val != temp) emit_move_insn (temp, val); \
XEXP (X, 1) = temp; \
goto WIN; } \
else if (GET_CODE (XEXP (X, 1)) == REG) \
{ register rtx temp = gen_reg_rtx (Pmode); \
register rtx val = force_operand (XEXP (X, 0), temp); \
if (val != temp) emit_move_insn (temp, val); \
XEXP (X, 0) = temp; \
goto WIN; }}}
/* Nonzero if the constant value X is a legitimate general operand /* Nonzero if the constant value X is a legitimate general operand
when generating PIC code. It is given that flag_pic is on and when generating PIC code. It is given that flag_pic is on and
@ -1312,7 +1469,6 @@ while (0)
stored from the compare operation. Note that we can't use "rtx" here stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */ since it hasn't been defined! */
extern struct rtx_def *i386_compare_op0, *i386_compare_op1;
extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
/* Tell final.c how to eliminate redundant test instructions. */ /* Tell final.c how to eliminate redundant test instructions. */
@ -1658,6 +1814,60 @@ extern char *qi_high_reg_name[];
#define RET return "" #define RET return ""
#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx)) #define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
/* Functions in i386.c */
extern void override_options ();
extern void order_regs_for_local_alloc ();
extern void output_op_from_reg ();
extern void output_to_reg ();
extern char *singlemove_string ();
extern char *output_move_double ();
extern char *output_move_memory ();
extern char *output_move_pushmem ();
extern int standard_80387_constant_p ();
extern char *output_move_const_single ();
extern int symbolic_operand ();
extern int call_insn_operand ();
extern int expander_call_insn_operand ();
extern int symbolic_reference_mentioned_p ();
extern void emit_pic_move ();
extern void function_prologue ();
extern int simple_386_epilogue ();
extern void function_epilogue ();
extern int legitimate_address_p ();
extern struct rtx_def *legitimize_pic_address ();
extern struct rtx_def *legitimize_address ();
extern void print_operand ();
extern void print_operand_address ();
extern void notice_update_cc ();
extern void split_di ();
extern int binary_387_op ();
extern int shift_op ();
extern int VOIDmode_compare_op ();
extern char *output_387_binary_op ();
extern char *output_fix_trunc ();
extern char *output_float_compare ();
extern char *output_fp_cc0_set ();
extern void save_386_machine_status ();
extern void restore_386_machine_status ();
extern void clear_386_stack_locals ();
extern struct rtx_def *assign_386_stack_local ();
/* Variables in i386.c */
extern char *i386_reg_alloc_order; /* register allocation order */
extern char *hi_reg_name[]; /* names for 16 bit regs */
extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */
extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */
extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */
/* External variables used */
extern int optimize; /* optimization level */
extern int obey_regdecls; /* TRUE if stupid register allocation */
/* External functions used */
extern struct rtx_def *force_operand ();
/* /*
Local variables: Local variables:
version-control: t version-control: t

View file

@ -1,5 +1,5 @@
/* Definitions for Unix assembler syntax for the Intel 80386. /* Definitions for Unix assembler syntax for the Intel 80386.
Copyright (C) 1988 Free Software Foundation, Inc. Copyright (C) 1988, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
@ -28,13 +28,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Note that the other files fail to use these /* Note that the other files fail to use these
in some of the places where they should. */ in some of the places where they should. */
#ifdef __STDC__ #if defined(__STDC__) || defined(ALMOST_STDC)
#define AS2(a,b,c) #a " " #b "," #c #define AS2(a,b,c) #a " " #b "," #c
#define AS2C(b,c) " " #b "," #c
#define AS3(a,b,c,d) #a " " #b "," #c "," #d #define AS3(a,b,c,d) #a " " #b "," #c "," #d
#define AS1(a,b) #a " " #b #define AS1(a,b) #a " " #b
#else #else
#define AS1(a,b) "a b" #define AS1(a,b) "a b"
#define AS2(a,b,c) "a b,c" #define AS2(a,b,c) "a b,c"
#define AS2C(b,c) " b,c"
#define AS3(a,b,c,d) "a b,c,d" #define AS3(a,b,c,d) "a b,c,d"
#endif #endif

View file

@ -32,169 +32,184 @@ enum insn_code {
CODE_FOR_cmpdf_ccfpeq = 40, CODE_FOR_cmpdf_ccfpeq = 40,
CODE_FOR_cmpsf_cc = 41, CODE_FOR_cmpsf_cc = 41,
CODE_FOR_cmpsf_ccfpeq = 42, CODE_FOR_cmpsf_ccfpeq = 42,
CODE_FOR_movsi = 48, CODE_FOR_movsi = 49,
CODE_FOR_movhi = 51, CODE_FOR_movhi = 54,
CODE_FOR_movstricthi = 52, CODE_FOR_movstricthi = 56,
CODE_FOR_movqi = 54, CODE_FOR_movqi = 61,
CODE_FOR_movstrictqi = 55, CODE_FOR_movstrictqi = 63,
CODE_FOR_movsf = 57, CODE_FOR_movsf = 65,
CODE_FOR_swapdf = 59, CODE_FOR_movsf_push_nomove = 66,
CODE_FOR_movdf = 60, CODE_FOR_movsf_push = 67,
CODE_FOR_swapxf = 62, CODE_FOR_movsf_mem = 68,
CODE_FOR_movxf = 63, CODE_FOR_movsf_normal = 69,
CODE_FOR_movdi = 65, CODE_FOR_swapsf = 70,
CODE_FOR_zero_extendhisi2 = 66, CODE_FOR_movdf = 71,
CODE_FOR_zero_extendqihi2 = 67, CODE_FOR_movdf_push_nomove = 72,
CODE_FOR_zero_extendqisi2 = 68, CODE_FOR_movdf_push = 73,
CODE_FOR_zero_extendsidi2 = 69, CODE_FOR_movdf_mem = 74,
CODE_FOR_extendsidi2 = 70, CODE_FOR_movdf_normal = 75,
CODE_FOR_extendhisi2 = 71, CODE_FOR_swapdf = 76,
CODE_FOR_extendqihi2 = 72, CODE_FOR_movxf = 77,
CODE_FOR_extendqisi2 = 73, CODE_FOR_movxf_push_nomove = 78,
CODE_FOR_extendsfdf2 = 74, CODE_FOR_movxf_push = 79,
CODE_FOR_extenddfxf2 = 75, CODE_FOR_movxf_mem = 80,
CODE_FOR_extendsfxf2 = 76, CODE_FOR_movxf_normal = 81,
CODE_FOR_truncdfsf2 = 77, CODE_FOR_swapxf = 82,
CODE_FOR_truncxfsf2 = 79, CODE_FOR_movdi = 84,
CODE_FOR_truncxfdf2 = 80, CODE_FOR_zero_extendhisi2 = 85,
CODE_FOR_fixuns_truncxfsi2 = 81, CODE_FOR_zero_extendqihi2 = 86,
CODE_FOR_fixuns_truncdfsi2 = 82, CODE_FOR_zero_extendqisi2 = 87,
CODE_FOR_fixuns_truncsfsi2 = 83, CODE_FOR_zero_extendsidi2 = 88,
CODE_FOR_fix_truncxfdi2 = 84, CODE_FOR_extendsidi2 = 89,
CODE_FOR_fix_truncdfdi2 = 85, CODE_FOR_extendhisi2 = 90,
CODE_FOR_fix_truncsfdi2 = 86, CODE_FOR_extendqihi2 = 91,
CODE_FOR_fix_truncxfsi2 = 90, CODE_FOR_extendqisi2 = 92,
CODE_FOR_fix_truncdfsi2 = 91, CODE_FOR_extendsfdf2 = 93,
CODE_FOR_fix_truncsfsi2 = 92, CODE_FOR_extenddfxf2 = 94,
CODE_FOR_floatsisf2 = 96, CODE_FOR_extendsfxf2 = 95,
CODE_FOR_floatdisf2 = 97, CODE_FOR_truncdfsf2 = 96,
CODE_FOR_floatsidf2 = 98, CODE_FOR_truncxfsf2 = 98,
CODE_FOR_floatdidf2 = 99, CODE_FOR_truncxfdf2 = 99,
CODE_FOR_floatsixf2 = 100, CODE_FOR_fixuns_truncxfsi2 = 100,
CODE_FOR_floatdixf2 = 101, CODE_FOR_fixuns_truncdfsi2 = 101,
CODE_FOR_adddi3 = 108, CODE_FOR_fixuns_truncsfsi2 = 102,
CODE_FOR_addsi3 = 109, CODE_FOR_fix_truncxfdi2 = 103,
CODE_FOR_addhi3 = 110, CODE_FOR_fix_truncdfdi2 = 104,
CODE_FOR_addqi3 = 111, CODE_FOR_fix_truncsfdi2 = 105,
CODE_FOR_addxf3 = 113, CODE_FOR_fix_truncxfsi2 = 109,
CODE_FOR_adddf3 = 114, CODE_FOR_fix_truncdfsi2 = 110,
CODE_FOR_addsf3 = 115, CODE_FOR_fix_truncsfsi2 = 111,
CODE_FOR_subdi3 = 116, CODE_FOR_floatsisf2 = 115,
CODE_FOR_subsi3 = 117, CODE_FOR_floatdisf2 = 116,
CODE_FOR_subhi3 = 118, CODE_FOR_floatsidf2 = 117,
CODE_FOR_subqi3 = 119, CODE_FOR_floatdidf2 = 118,
CODE_FOR_subxf3 = 120, CODE_FOR_floatsixf2 = 119,
CODE_FOR_subdf3 = 121, CODE_FOR_floatdixf2 = 120,
CODE_FOR_subsf3 = 122, CODE_FOR_adddi3 = 127,
CODE_FOR_mulhi3 = 124, CODE_FOR_addsi3 = 128,
CODE_FOR_mulsi3 = 126, CODE_FOR_addhi3 = 129,
CODE_FOR_umulqihi3 = 127, CODE_FOR_addqi3 = 130,
CODE_FOR_mulqihi3 = 128, CODE_FOR_movsi_lea = 131,
CODE_FOR_umulsidi3 = 129, CODE_FOR_addxf3 = 132,
CODE_FOR_mulsidi3 = 130, CODE_FOR_adddf3 = 133,
CODE_FOR_mulxf3 = 131, CODE_FOR_addsf3 = 134,
CODE_FOR_muldf3 = 132, CODE_FOR_subdi3 = 135,
CODE_FOR_mulsf3 = 133, CODE_FOR_subsi3 = 136,
CODE_FOR_divqi3 = 134, CODE_FOR_subhi3 = 137,
CODE_FOR_udivqi3 = 135, CODE_FOR_subqi3 = 138,
CODE_FOR_divxf3 = 136, CODE_FOR_subxf3 = 139,
CODE_FOR_divdf3 = 137, CODE_FOR_subdf3 = 140,
CODE_FOR_divsf3 = 138, CODE_FOR_subsf3 = 141,
CODE_FOR_divmodsi4 = 139, CODE_FOR_mulhi3 = 143,
CODE_FOR_divmodhi4 = 140, CODE_FOR_mulsi3 = 145,
CODE_FOR_udivmodsi4 = 141, CODE_FOR_umulqihi3 = 146,
CODE_FOR_udivmodhi4 = 142, CODE_FOR_mulqihi3 = 147,
CODE_FOR_andsi3 = 143, CODE_FOR_umulsidi3 = 148,
CODE_FOR_andhi3 = 144, CODE_FOR_mulsidi3 = 149,
CODE_FOR_andqi3 = 145, CODE_FOR_umulsi3_highpart = 150,
CODE_FOR_iorsi3 = 146, CODE_FOR_smulsi3_highpart = 151,
CODE_FOR_iorhi3 = 147, CODE_FOR_mulxf3 = 152,
CODE_FOR_iorqi3 = 148, CODE_FOR_muldf3 = 153,
CODE_FOR_xorsi3 = 149, CODE_FOR_mulsf3 = 154,
CODE_FOR_xorhi3 = 150, CODE_FOR_divqi3 = 155,
CODE_FOR_xorqi3 = 151, CODE_FOR_udivqi3 = 156,
CODE_FOR_negdi2 = 152, CODE_FOR_divxf3 = 157,
CODE_FOR_negsi2 = 153, CODE_FOR_divdf3 = 158,
CODE_FOR_neghi2 = 154, CODE_FOR_divsf3 = 159,
CODE_FOR_negqi2 = 155, CODE_FOR_divmodsi4 = 160,
CODE_FOR_negsf2 = 156, CODE_FOR_divmodhi4 = 161,
CODE_FOR_negdf2 = 157, CODE_FOR_udivmodsi4 = 162,
CODE_FOR_negxf2 = 159, CODE_FOR_udivmodhi4 = 163,
CODE_FOR_abssf2 = 161, CODE_FOR_andsi3 = 164,
CODE_FOR_absdf2 = 162, CODE_FOR_andhi3 = 165,
CODE_FOR_absxf2 = 164, CODE_FOR_andqi3 = 166,
CODE_FOR_sqrtsf2 = 166, CODE_FOR_iorsi3 = 167,
CODE_FOR_sqrtdf2 = 167, CODE_FOR_iorhi3 = 168,
CODE_FOR_sqrtxf2 = 169, CODE_FOR_iorqi3 = 169,
CODE_FOR_sindf2 = 172, CODE_FOR_xorsi3 = 170,
CODE_FOR_sinsf2 = 173, CODE_FOR_xorhi3 = 171,
CODE_FOR_cosdf2 = 175, CODE_FOR_xorqi3 = 172,
CODE_FOR_cossf2 = 176, CODE_FOR_negdi2 = 173,
CODE_FOR_one_cmplsi2 = 178, CODE_FOR_negsi2 = 174,
CODE_FOR_one_cmplhi2 = 179, CODE_FOR_neghi2 = 175,
CODE_FOR_one_cmplqi2 = 180, CODE_FOR_negqi2 = 176,
CODE_FOR_ashldi3 = 181, CODE_FOR_negsf2 = 177,
CODE_FOR_ashldi3_const_int = 182, CODE_FOR_negdf2 = 178,
CODE_FOR_ashldi3_non_const_int = 183, CODE_FOR_negxf2 = 180,
CODE_FOR_ashlsi3 = 184, CODE_FOR_abssf2 = 182,
CODE_FOR_ashlhi3 = 185, CODE_FOR_absdf2 = 183,
CODE_FOR_ashlqi3 = 186, CODE_FOR_absxf2 = 185,
CODE_FOR_ashrdi3 = 187, CODE_FOR_sqrtsf2 = 187,
CODE_FOR_ashrdi3_const_int = 188, CODE_FOR_sqrtdf2 = 188,
CODE_FOR_ashrdi3_non_const_int = 189, CODE_FOR_sqrtxf2 = 190,
CODE_FOR_ashrsi3 = 190, CODE_FOR_sindf2 = 193,
CODE_FOR_ashrhi3 = 191, CODE_FOR_sinsf2 = 194,
CODE_FOR_ashrqi3 = 192, CODE_FOR_cosdf2 = 196,
CODE_FOR_lshrdi3 = 193, CODE_FOR_cossf2 = 197,
CODE_FOR_lshrdi3_const_int = 194, CODE_FOR_one_cmplsi2 = 199,
CODE_FOR_lshrdi3_non_const_int = 195, CODE_FOR_one_cmplhi2 = 200,
CODE_FOR_lshrsi3 = 196, CODE_FOR_one_cmplqi2 = 201,
CODE_FOR_lshrhi3 = 197, CODE_FOR_ashldi3 = 202,
CODE_FOR_lshrqi3 = 198, CODE_FOR_ashldi3_const_int = 203,
CODE_FOR_rotlsi3 = 199, CODE_FOR_ashldi3_non_const_int = 204,
CODE_FOR_rotlhi3 = 200, CODE_FOR_ashlsi3 = 205,
CODE_FOR_rotlqi3 = 201, CODE_FOR_ashlhi3 = 206,
CODE_FOR_rotrsi3 = 202, CODE_FOR_ashlqi3 = 207,
CODE_FOR_rotrhi3 = 203, CODE_FOR_ashrdi3 = 208,
CODE_FOR_rotrqi3 = 204, CODE_FOR_ashrdi3_const_int = 209,
CODE_FOR_seq = 211, CODE_FOR_ashrdi3_non_const_int = 210,
CODE_FOR_sne = 213, CODE_FOR_ashrsi3 = 211,
CODE_FOR_sgt = 215, CODE_FOR_ashrhi3 = 212,
CODE_FOR_sgtu = 217, CODE_FOR_ashrqi3 = 213,
CODE_FOR_slt = 219, CODE_FOR_lshrdi3 = 214,
CODE_FOR_sltu = 221, CODE_FOR_lshrdi3_const_int = 215,
CODE_FOR_sge = 223, CODE_FOR_lshrdi3_non_const_int = 216,
CODE_FOR_sgeu = 225, CODE_FOR_lshrsi3 = 217,
CODE_FOR_sle = 227, CODE_FOR_lshrhi3 = 218,
CODE_FOR_sleu = 229, CODE_FOR_lshrqi3 = 219,
CODE_FOR_beq = 231, CODE_FOR_rotlsi3 = 220,
CODE_FOR_bne = 233, CODE_FOR_rotlhi3 = 221,
CODE_FOR_bgt = 235, CODE_FOR_rotlqi3 = 222,
CODE_FOR_bgtu = 237, CODE_FOR_rotrsi3 = 223,
CODE_FOR_blt = 239, CODE_FOR_rotrhi3 = 224,
CODE_FOR_bltu = 241, CODE_FOR_rotrqi3 = 225,
CODE_FOR_bge = 243, CODE_FOR_seq = 232,
CODE_FOR_bgeu = 245, CODE_FOR_sne = 234,
CODE_FOR_ble = 247, CODE_FOR_sgt = 236,
CODE_FOR_bleu = 249, CODE_FOR_sgtu = 238,
CODE_FOR_jump = 261, CODE_FOR_slt = 240,
CODE_FOR_indirect_jump = 262, CODE_FOR_sltu = 242,
CODE_FOR_casesi = 263, CODE_FOR_sge = 244,
CODE_FOR_tablejump = 265, CODE_FOR_sgeu = 246,
CODE_FOR_call_pop = 266, CODE_FOR_sle = 248,
CODE_FOR_call = 269, CODE_FOR_sleu = 250,
CODE_FOR_call_value_pop = 272, CODE_FOR_beq = 252,
CODE_FOR_call_value = 275, CODE_FOR_bne = 254,
CODE_FOR_untyped_call = 278, CODE_FOR_bgt = 256,
CODE_FOR_untyped_return = 281, CODE_FOR_bgtu = 258,
CODE_FOR_update_return = 282, CODE_FOR_blt = 260,
CODE_FOR_return = 283, CODE_FOR_bltu = 262,
CODE_FOR_nop = 284, CODE_FOR_bge = 264,
CODE_FOR_movstrsi = 285, CODE_FOR_bgeu = 266,
CODE_FOR_cmpstrsi = 287, CODE_FOR_ble = 268,
CODE_FOR_ffssi2 = 290, CODE_FOR_bleu = 270,
CODE_FOR_ffshi2 = 292, CODE_FOR_jump = 282,
CODE_FOR_strlensi = 307, CODE_FOR_indirect_jump = 283,
CODE_FOR_casesi = 284,
CODE_FOR_tablejump = 286,
CODE_FOR_call_pop = 287,
CODE_FOR_call = 290,
CODE_FOR_call_value_pop = 293,
CODE_FOR_call_value = 296,
CODE_FOR_untyped_call = 299,
CODE_FOR_blockage = 300,
CODE_FOR_return = 301,
CODE_FOR_nop = 302,
CODE_FOR_movstrsi = 303,
CODE_FOR_cmpstrsi = 305,
CODE_FOR_ffssi2 = 308,
CODE_FOR_ffshi2 = 310,
CODE_FOR_strlensi = 325,
CODE_FOR_nothing }; CODE_FOR_nothing };
#define MAX_INSN_CODE ((int) CODE_FOR_nothing) #define MAX_INSN_CODE ((int) CODE_FOR_nothing)

View file

@ -36,10 +36,23 @@ from the machine description file `md'. */
#define HAVE_movqi 1 #define HAVE_movqi 1
#define HAVE_movstrictqi 1 #define HAVE_movstrictqi 1
#define HAVE_movsf 1 #define HAVE_movsf 1
#define HAVE_swapdf 1 #define HAVE_movsf_push_nomove (!TARGET_MOVE)
#define HAVE_movsf_push 1
#define HAVE_movsf_mem 1
#define HAVE_movsf_normal ((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM))
#define HAVE_swapsf 1
#define HAVE_movdf 1 #define HAVE_movdf 1
#define HAVE_swapxf 1 #define HAVE_movdf_push_nomove (!TARGET_MOVE)
#define HAVE_movdf_push 1
#define HAVE_movdf_mem 1
#define HAVE_movdf_normal ((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM))
#define HAVE_swapdf 1
#define HAVE_movxf 1 #define HAVE_movxf 1
#define HAVE_movxf_push_nomove (!TARGET_MOVE)
#define HAVE_movxf_push 1
#define HAVE_movxf_mem 1
#define HAVE_movxf_normal ((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM))
#define HAVE_swapxf 1
#define HAVE_movdi 1 #define HAVE_movdi 1
#define HAVE_zero_extendhisi2 1 #define HAVE_zero_extendhisi2 1
#define HAVE_zero_extendqihi2 1 #define HAVE_zero_extendqihi2 1
@ -74,6 +87,7 @@ from the machine description file `md'. */
#define HAVE_addsi3 1 #define HAVE_addsi3 1
#define HAVE_addhi3 1 #define HAVE_addhi3 1
#define HAVE_addqi3 1 #define HAVE_addqi3 1
#define HAVE_movsi_lea 1
#define HAVE_addxf3 (TARGET_80387) #define HAVE_addxf3 (TARGET_80387)
#define HAVE_adddf3 (TARGET_80387) #define HAVE_adddf3 (TARGET_80387)
#define HAVE_addsf3 (TARGET_80387) #define HAVE_addsf3 (TARGET_80387)
@ -88,8 +102,10 @@ from the machine description file `md'. */
#define HAVE_mulsi3 1 #define HAVE_mulsi3 1
#define HAVE_umulqihi3 1 #define HAVE_umulqihi3 1
#define HAVE_mulqihi3 1 #define HAVE_mulqihi3 1
#define HAVE_umulsidi3 1 #define HAVE_umulsidi3 (TARGET_WIDE_MULTIPLY)
#define HAVE_mulsidi3 1 #define HAVE_mulsidi3 (TARGET_WIDE_MULTIPLY)
#define HAVE_umulsi3_highpart (TARGET_WIDE_MULTIPLY)
#define HAVE_smulsi3_highpart (TARGET_WIDE_MULTIPLY)
#define HAVE_mulxf3 (TARGET_80387) #define HAVE_mulxf3 (TARGET_80387)
#define HAVE_muldf3 (TARGET_80387) #define HAVE_muldf3 (TARGET_80387)
#define HAVE_mulsf3 (TARGET_80387) #define HAVE_mulsf3 (TARGET_80387)
@ -191,8 +207,7 @@ from the machine description file `md'. */
#define HAVE_call_value_pop 1 #define HAVE_call_value_pop 1
#define HAVE_call_value 1 #define HAVE_call_value 1
#define HAVE_untyped_call 1 #define HAVE_untyped_call 1
#define HAVE_untyped_return 1 #define HAVE_blockage 1
#define HAVE_update_return 1
#define HAVE_return (simple_386_epilogue ()) #define HAVE_return (simple_386_epilogue ())
#define HAVE_nop 1 #define HAVE_nop 1
#define HAVE_movstrsi 1 #define HAVE_movstrsi 1
@ -236,10 +251,23 @@ extern rtx gen_movstricthi PROTO((rtx, rtx));
extern rtx gen_movqi PROTO((rtx, rtx)); extern rtx gen_movqi PROTO((rtx, rtx));
extern rtx gen_movstrictqi PROTO((rtx, rtx)); extern rtx gen_movstrictqi PROTO((rtx, rtx));
extern rtx gen_movsf PROTO((rtx, rtx)); extern rtx gen_movsf PROTO((rtx, rtx));
extern rtx gen_swapdf PROTO((rtx, rtx)); extern rtx gen_movsf_push_nomove PROTO((rtx, rtx));
extern rtx gen_movsf_push PROTO((rtx, rtx));
extern rtx gen_movsf_mem PROTO((rtx, rtx));
extern rtx gen_movsf_normal PROTO((rtx, rtx));
extern rtx gen_swapsf PROTO((rtx, rtx));
extern rtx gen_movdf PROTO((rtx, rtx)); extern rtx gen_movdf PROTO((rtx, rtx));
extern rtx gen_swapxf PROTO((rtx, rtx)); extern rtx gen_movdf_push_nomove PROTO((rtx, rtx));
extern rtx gen_movdf_push PROTO((rtx, rtx));
extern rtx gen_movdf_mem PROTO((rtx, rtx));
extern rtx gen_movdf_normal PROTO((rtx, rtx));
extern rtx gen_swapdf PROTO((rtx, rtx));
extern rtx gen_movxf PROTO((rtx, rtx)); extern rtx gen_movxf PROTO((rtx, rtx));
extern rtx gen_movxf_push_nomove PROTO((rtx, rtx));
extern rtx gen_movxf_push PROTO((rtx, rtx));
extern rtx gen_movxf_mem PROTO((rtx, rtx));
extern rtx gen_movxf_normal PROTO((rtx, rtx));
extern rtx gen_swapxf PROTO((rtx, rtx));
extern rtx gen_movdi PROTO((rtx, rtx)); extern rtx gen_movdi PROTO((rtx, rtx));
extern rtx gen_zero_extendhisi2 PROTO((rtx, rtx)); extern rtx gen_zero_extendhisi2 PROTO((rtx, rtx));
extern rtx gen_zero_extendqihi2 PROTO((rtx, rtx)); extern rtx gen_zero_extendqihi2 PROTO((rtx, rtx));
@ -274,6 +302,7 @@ extern rtx gen_adddi3 PROTO((rtx, rtx, rtx));
extern rtx gen_addsi3 PROTO((rtx, rtx, rtx)); extern rtx gen_addsi3 PROTO((rtx, rtx, rtx));
extern rtx gen_addhi3 PROTO((rtx, rtx, rtx)); extern rtx gen_addhi3 PROTO((rtx, rtx, rtx));
extern rtx gen_addqi3 PROTO((rtx, rtx, rtx)); extern rtx gen_addqi3 PROTO((rtx, rtx, rtx));
extern rtx gen_movsi_lea PROTO((rtx, rtx));
extern rtx gen_addxf3 PROTO((rtx, rtx, rtx)); extern rtx gen_addxf3 PROTO((rtx, rtx, rtx));
extern rtx gen_adddf3 PROTO((rtx, rtx, rtx)); extern rtx gen_adddf3 PROTO((rtx, rtx, rtx));
extern rtx gen_addsf3 PROTO((rtx, rtx, rtx)); extern rtx gen_addsf3 PROTO((rtx, rtx, rtx));
@ -290,6 +319,8 @@ extern rtx gen_umulqihi3 PROTO((rtx, rtx, rtx));
extern rtx gen_mulqihi3 PROTO((rtx, rtx, rtx)); extern rtx gen_mulqihi3 PROTO((rtx, rtx, rtx));
extern rtx gen_umulsidi3 PROTO((rtx, rtx, rtx)); extern rtx gen_umulsidi3 PROTO((rtx, rtx, rtx));
extern rtx gen_mulsidi3 PROTO((rtx, rtx, rtx)); extern rtx gen_mulsidi3 PROTO((rtx, rtx, rtx));
extern rtx gen_umulsi3_highpart PROTO((rtx, rtx, rtx));
extern rtx gen_smulsi3_highpart PROTO((rtx, rtx, rtx));
extern rtx gen_mulxf3 PROTO((rtx, rtx, rtx)); extern rtx gen_mulxf3 PROTO((rtx, rtx, rtx));
extern rtx gen_muldf3 PROTO((rtx, rtx, rtx)); extern rtx gen_muldf3 PROTO((rtx, rtx, rtx));
extern rtx gen_mulsf3 PROTO((rtx, rtx, rtx)); extern rtx gen_mulsf3 PROTO((rtx, rtx, rtx));
@ -380,8 +411,7 @@ extern rtx gen_indirect_jump PROTO((rtx));
extern rtx gen_casesi PROTO((rtx, rtx, rtx, rtx, rtx)); extern rtx gen_casesi PROTO((rtx, rtx, rtx, rtx, rtx));
extern rtx gen_tablejump PROTO((rtx, rtx)); extern rtx gen_tablejump PROTO((rtx, rtx));
extern rtx gen_untyped_call PROTO((rtx, rtx, rtx)); extern rtx gen_untyped_call PROTO((rtx, rtx, rtx));
extern rtx gen_untyped_return PROTO((rtx, rtx)); extern rtx gen_blockage PROTO((void));
extern rtx gen_update_return PROTO((rtx));
extern rtx gen_return PROTO((void)); extern rtx gen_return PROTO((void));
extern rtx gen_nop PROTO((void)); extern rtx gen_nop PROTO((void));
extern rtx gen_movstrsi PROTO((rtx, rtx, rtx, rtx)); extern rtx gen_movstrsi PROTO((rtx, rtx, rtx, rtx));
@ -438,10 +468,23 @@ extern rtx gen_movstricthi ();
extern rtx gen_movqi (); extern rtx gen_movqi ();
extern rtx gen_movstrictqi (); extern rtx gen_movstrictqi ();
extern rtx gen_movsf (); extern rtx gen_movsf ();
extern rtx gen_swapdf (); extern rtx gen_movsf_push_nomove ();
extern rtx gen_movsf_push ();
extern rtx gen_movsf_mem ();
extern rtx gen_movsf_normal ();
extern rtx gen_swapsf ();
extern rtx gen_movdf (); extern rtx gen_movdf ();
extern rtx gen_swapxf (); extern rtx gen_movdf_push_nomove ();
extern rtx gen_movdf_push ();
extern rtx gen_movdf_mem ();
extern rtx gen_movdf_normal ();
extern rtx gen_swapdf ();
extern rtx gen_movxf (); extern rtx gen_movxf ();
extern rtx gen_movxf_push_nomove ();
extern rtx gen_movxf_push ();
extern rtx gen_movxf_mem ();
extern rtx gen_movxf_normal ();
extern rtx gen_swapxf ();
extern rtx gen_movdi (); extern rtx gen_movdi ();
extern rtx gen_zero_extendhisi2 (); extern rtx gen_zero_extendhisi2 ();
extern rtx gen_zero_extendqihi2 (); extern rtx gen_zero_extendqihi2 ();
@ -476,6 +519,7 @@ extern rtx gen_adddi3 ();
extern rtx gen_addsi3 (); extern rtx gen_addsi3 ();
extern rtx gen_addhi3 (); extern rtx gen_addhi3 ();
extern rtx gen_addqi3 (); extern rtx gen_addqi3 ();
extern rtx gen_movsi_lea ();
extern rtx gen_addxf3 (); extern rtx gen_addxf3 ();
extern rtx gen_adddf3 (); extern rtx gen_adddf3 ();
extern rtx gen_addsf3 (); extern rtx gen_addsf3 ();
@ -492,6 +536,8 @@ extern rtx gen_umulqihi3 ();
extern rtx gen_mulqihi3 (); extern rtx gen_mulqihi3 ();
extern rtx gen_umulsidi3 (); extern rtx gen_umulsidi3 ();
extern rtx gen_mulsidi3 (); extern rtx gen_mulsidi3 ();
extern rtx gen_umulsi3_highpart ();
extern rtx gen_smulsi3_highpart ();
extern rtx gen_mulxf3 (); extern rtx gen_mulxf3 ();
extern rtx gen_muldf3 (); extern rtx gen_muldf3 ();
extern rtx gen_mulsf3 (); extern rtx gen_mulsf3 ();
@ -582,8 +628,7 @@ extern rtx gen_indirect_jump ();
extern rtx gen_casesi (); extern rtx gen_casesi ();
extern rtx gen_tablejump (); extern rtx gen_tablejump ();
extern rtx gen_untyped_call (); extern rtx gen_untyped_call ();
extern rtx gen_untyped_return (); extern rtx gen_blockage ();
extern rtx gen_update_return ();
extern rtx gen_return (); extern rtx gen_return ();
extern rtx gen_nop (); extern rtx gen_nop ();
extern rtx gen_movstrsi (); extern rtx gen_movstrsi ();

View file

@ -67,7 +67,7 @@ DEF_MACHMODE (HImode, "HI", MODE_INT, 2, 2, SImode)
/* Pointers on some machines use this type to distinguish them from ints. /* Pointers on some machines use this type to distinguish them from ints.
Useful if a pointer is 4 bytes but has some bits that are not significant, Useful if a pointer is 4 bytes but has some bits that are not significant,
so it is really not quite as wide as an integer. */ so it is really not quite as wide as an integer. */
DEF_MACHMODE (PSImode, "PSI", MODE_PARTIAL_INT, 4, 4, VOIDmode) DEF_MACHMODE (PSImode, "PSI", MODE_PARTIAL_INT, 4, 4, PDImode)
DEF_MACHMODE (SImode, "SI", MODE_INT, 4, 4, DImode) DEF_MACHMODE (SImode, "SI", MODE_INT, 4, 4, DImode)
DEF_MACHMODE (PDImode, "PDI", MODE_PARTIAL_INT, 8, 8, VOIDmode) DEF_MACHMODE (PDImode, "PDI", MODE_PARTIAL_INT, 8, 8, VOIDmode)
DEF_MACHMODE (DImode, "DI", MODE_INT, 8, 8, TImode) DEF_MACHMODE (DImode, "DI", MODE_INT, 8, 8, TImode)

View file

@ -119,7 +119,7 @@ break the ordinary 'growth' macro.
but in traditional C it is usually long. If we are in ANSI C and but in traditional C it is usually long. If we are in ANSI C and
don't already have ptrdiff_t get it. */ don't already have ptrdiff_t get it. */
#if defined (__STDC__) && ! defined (offsetof) #if defined (__STDC__) && __STDC__ && ! defined (offsetof)
#if defined (__GNUC__) && defined (IN_GCC) #if defined (__GNUC__) && defined (IN_GCC)
/* On Next machine, the system's stddef.h screws up if included /* On Next machine, the system's stddef.h screws up if included
after we have defined just ptrdiff_t, so include all of stddef.h. after we have defined just ptrdiff_t, so include all of stddef.h.
@ -132,7 +132,7 @@ break the ordinary 'growth' macro.
#include <stddef.h> #include <stddef.h>
#endif #endif
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
#define PTR_INT_TYPE ptrdiff_t #define PTR_INT_TYPE ptrdiff_t
#else #else
#define PTR_INT_TYPE long #define PTR_INT_TYPE long
@ -167,7 +167,7 @@ struct obstack /* control current object in current chunk */
/* Declare the external functions we use; they are in obstack.c. */ /* Declare the external functions we use; they are in obstack.c. */
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *); extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *, int, int, extern int _obstack_begin (struct obstack *, int, int,
@ -181,7 +181,7 @@ extern int _obstack_begin ();
extern int _obstack_begin_1 (); extern int _obstack_begin_1 ();
#endif #endif
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
/* Do the function-declarations after the structs /* Do the function-declarations after the structs
but before defining the macros. */ but before defining the macros. */
@ -492,7 +492,7 @@ __extension__ \
(h)->object_base = (h)->next_free, \ (h)->object_base = (h)->next_free, \
__INT_TO_PTR ((h)->temp))) __INT_TO_PTR ((h)->temp)))
#ifdef __STDC__ #if defined (__STDC__) && __STDC__
#define obstack_free(h,obj) \ #define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\

View file

@ -1,5 +1,5 @@
/* Define per-register tables for data flow info and register allocation. /* Define per-register tables for data flow info and register allocation.
Copyright (C) 1987, 1993 Free Software Foundation, Inc. Copyright (C) 1987, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
@ -53,6 +53,12 @@ extern short *reg_n_sets;
extern short *reg_n_deaths; extern short *reg_n_deaths;
/* Indexed by N; says whether a psuedo register N was ever used
within a SUBREG that changes the size of the reg. Some machines prohibit
such objects to be in certain (usually floating-point) registers. */
extern char *reg_changes_size;
/* Get the number of consecutive words required to hold pseudo-reg N. */ /* Get the number of consecutive words required to hold pseudo-reg N. */
#define PSEUDO_REGNO_SIZE(N) \ #define PSEUDO_REGNO_SIZE(N) \

View file

@ -216,9 +216,10 @@ extern void mark_home_live PROTO((int));
replacement (such as sp), plus an offset. */ replacement (such as sp), plus an offset. */
extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx)); extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx));
/* Emit code to perform an input reload of IN to RELOADREG. IN is from /* Emit code to perform a reload from IN (which may be a reload register) to
operand OPNUM with reload type TYPE. */ OUT (which may also be a reload register). IN or OUT is from operand
extern rtx gen_input_reload PROTO((rtx, rtx, int, enum reload_type)); OPNUM with reload type TYPE. */
extern rtx gen_reload PROTO((rtx, rtx, int, enum reload_type));
/* Functions in caller-save.c: */ /* Functions in caller-save.c: */

View file

@ -922,6 +922,10 @@ extern rtx output_constant_def PROTO((union tree_node *));
extern rtx immed_real_const PROTO((union tree_node *)); extern rtx immed_real_const PROTO((union tree_node *));
extern union tree_node *make_tree PROTO((union tree_node *, rtx)); extern union tree_node *make_tree PROTO((union tree_node *, rtx));
/* Abort routines */
extern void fatal_insn_not_found PROTO((rtx));
extern void fatal_insn PROTO((char *, rtx));
/* Define a default value for STORE_FLAG_VALUE. */ /* Define a default value for STORE_FLAG_VALUE. */
#ifndef STORE_FLAG_VALUE #ifndef STORE_FLAG_VALUE

View file

@ -33,21 +33,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef CPP_PREDEFINES #undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__=2 -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" #define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__=2 -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)"
#if 0
#define INCLUDE_DEFAULTS { \ #define INCLUDE_DEFAULTS { \
{ "/usr/include", 0 }, \ { "/usr/include", 0 }, \
{ "/usr/include/g++", 1 }, \ { "/usr/include/g++", 1 }, \
{ 0, 0} \ { 0, 0} \
} }
#endif
#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}"
/* Like the default, except no -lg. */ /* Like the default, except no -lg. */
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" #define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
#define LINK_SPEC \
"%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*} \
%{p:-Bstatic} %{pg:-Bstatic} %{Z}"
#undef SIZE_TYPE #undef SIZE_TYPE
#define SIZE_TYPE "unsigned int" #define SIZE_TYPE "unsigned int"
@ -55,12 +51,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PTRDIFF_TYPE "int" #define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE #undef WCHAR_TYPE
#define WCHAR_TYPE "int" #define WCHAR_TYPE "short unsigned int"
#define WCHAR_UNSIGNED 0 #define WCHAR_UNSIGNED 1
#undef WCHAR_TYPE_SIZE #undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD #define WCHAR_TYPE_SIZE 16
#define HAVE_ATEXIT #define HAVE_ATEXIT
@ -74,9 +70,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define FUNCTION_PROFILER(FILE, LABELNO) \ #define FUNCTION_PROFILER(FILE, LABELNO) \
{ \ { \
if (flag_pic) \ if (flag_pic) \
fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ { \
fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \
LPREFIX, (LABELNO)); \
fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
} \
else \ else \
fprintf (FILE, "\tcall mcount\n"); \ { \
fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \
fprintf (FILE, "\tcall mcount\n"); \
} \
} }
#if 0 /* not ready for this; it should be decided at compile time */ #if 0 /* not ready for this; it should be decided at compile time */
@ -183,7 +186,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
size_directive_output = 0; \ size_directive_output = 0; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
{ \ { \
size_directive_output = 1; \ size_directive_output = 1; \
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
assemble_name (FILE, NAME); \ assemble_name (FILE, NAME); \
fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
@ -197,20 +200,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
size_directive_output was set size_directive_output was set
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ #define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \ do { \
char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \ && ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \ && DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \ && !size_directive_output) \
{ \ { \
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
assemble_name (FILE, name); \ assemble_name (FILE, name); \
fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL)));\
} \ } \
} while (0) } while (0)
/* This is how to declare the size of a function. */ /* This is how to declare the size of a function. */
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ #define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
@ -232,82 +236,9 @@ do { \
} \ } \
} while (0) } while (0)
/* This section copied from i386/osfrose.h */ #define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}"
#define LINK_SPEC \
/* A C statement or compound statement to output to FILE some "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}"
assembler code to initialize basic-block profiling for the current
object module. This code should call the subroutine
`__bb_init_func' once per object module, passing it as its sole
argument the address of a block allocated in the object module.
The name of the block is a local symbol made with this statement:
ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
Of course, since you are writing the definition of
`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
can take a short cut in the definition of this macro and use the
name that you know will result.
The first word of this block is a flag which will be nonzero if the
object module has already been initialized. So test this word
first, and do not call `__bb_init_func' if the flag is nonzero. */
#undef FUNCTION_BLOCK_PROFILER
#define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \
do \
{ \
if (!flag_pic) \
{ \
fprintf (STREAM, "\tcmpl $0,%sPBX0\n", LPREFIX); \
fprintf (STREAM, "\tjne 0f\n"); \
fprintf (STREAM, "\tpushl $%sPBX0\n", LPREFIX); \
fprintf (STREAM, "\tcall ___bb_init_func\n"); \
fprintf (STREAM, "0:\n"); \
} \
else \
{ \
fprintf (STREAM, "\tpushl %eax\n"); \
fprintf (STREAM, "\tmovl %sPBX0@GOT(%ebx),%eax\n"); \
fprintf (STREAM, "\tcmpl $0,(%eax)\n"); \
fprintf (STREAM, "\tjne 0f\n"); \
fprintf (STREAM, "\tpushl %eax\n"); \
fprintf (STREAM, "\tcall ___bb_init_func@PLT\n"); \
fprintf (STREAM, "0:\n"); \
fprintf (STREAM, "\tpopl %eax\n"); \
} \
} \
while (0)
/* A C statement or compound statement to increment the count
associated with the basic block number BLOCKNO. Basic blocks are
numbered separately from zero within each compilation. The count
associated with block number BLOCKNO is at index BLOCKNO in a
vector of words; the name of this array is a local symbol made
with this statement:
ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
Of course, since you are writing the definition of
`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
can take a short cut in the definition of this macro and use the
name that you know will result. */
#undef BLOCK_PROFILER
#define BLOCK_PROFILER(STREAM, BLOCKNO) \
do \
{ \
if (!flag_pic) \
fprintf (STREAM, "\tincl %sPBX2+%d\n", LPREFIX, (BLOCKNO)*4); \
else \
{ \
fprintf (STREAM, "\tpushl %eax\n"); \
fprintf (STREAM, "\tmovl %sPBX2@GOT(%ebx),%eax\n", LPREFIX); \
fprintf (STREAM, "\tincl %d(%eax)\n", (BLOCKNO)*4); \
fprintf (STREAM, "\tpopl %eax\n"); \
} \
} \
while (0)
/* This is defined when gcc is compiled in the BSD-directory-tree, and must /* This is defined when gcc is compiled in the BSD-directory-tree, and must
* make up for the gap to all the stuff done in the GNU-makefiles. * make up for the gap to all the stuff done in the GNU-makefiles.

View file

@ -619,6 +619,10 @@ struct tree_block
function when they are created. */ function when they are created. */
#define TYPE_NEEDS_CONSTRUCTING(NODE) ((NODE)->type.needs_constructing_flag) #define TYPE_NEEDS_CONSTRUCTING(NODE) ((NODE)->type.needs_constructing_flag)
/* Indicates that objects of this type (a UNION_TYPE), should be passed
the same way that the first union alternative would be passed. */
#define TYPE_TRANSPARENT_UNION(NODE) ((NODE)->type.transparent_union_flag)
struct tree_type struct tree_type
{ {
char common[sizeof (struct tree_common)]; char common[sizeof (struct tree_common)];
@ -637,6 +641,7 @@ struct tree_type
unsigned string_flag : 1; unsigned string_flag : 1;
unsigned no_force_blk_flag : 1; unsigned no_force_blk_flag : 1;
unsigned needs_constructing_flag : 1; unsigned needs_constructing_flag : 1;
unsigned transparent_union_flag : 1;
unsigned lang_flag_0 : 1; unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1; unsigned lang_flag_1 : 1;
unsigned lang_flag_2 : 1; unsigned lang_flag_2 : 1;
@ -644,7 +649,7 @@ struct tree_type
unsigned lang_flag_4 : 1; unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1; unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1; unsigned lang_flag_6 : 1;
/* room for 6 more bits */ /* room for 5 more bits */
unsigned int align; unsigned int align;
union tree_node *pointer_to; union tree_node *pointer_to;
@ -928,6 +933,11 @@ struct tree_type
so it should not be output now. */ so it should not be output now. */
#define DECL_DEFER_OUTPUT(NODE) ((NODE)->decl.defer_output) #define DECL_DEFER_OUTPUT(NODE) ((NODE)->decl.defer_output)
/* Used in PARM_DECLs whose type are unions to indicate that the
argument should be passed in the same way that the first union
alternative would be passed. */
#define DECL_TRANSPARENT_UNION(NODE) ((NODE)->decl.transparent_union)
/* Additional flags for language-specific uses. */ /* Additional flags for language-specific uses. */
#define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0) #define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1) #define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1)
@ -963,7 +973,8 @@ struct tree_decl
unsigned in_system_header_flag : 1; unsigned in_system_header_flag : 1;
unsigned common_flag : 1; unsigned common_flag : 1;
unsigned defer_output : 1; unsigned defer_output : 1;
/* room for five more */ unsigned transparent_union : 1;
/* room for four more */
unsigned lang_flag_0 : 1; unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1; unsigned lang_flag_1 : 1;
@ -1238,6 +1249,12 @@ extern tree get_pending_sizes PROTO((void));
extern tree sizetype; extern tree sizetype;
/* If nonzero, an upper limit on alignment of structure fields, in bits. */
extern int maximum_field_alignment;
/* If non-zero, the alignment of a bitsting or (power-)set value, in bits. */
extern int set_alignment;
/* Concatenate two lists (chains of TREE_LIST nodes) X and Y /* Concatenate two lists (chains of TREE_LIST nodes) X and Y
by making the last node in X point to Y. by making the last node in X point to Y.
Returns X, except if X is 0 returns Y. */ Returns X, except if X is 0 returns Y. */
@ -1481,6 +1498,9 @@ extern void (*incomplete_decl_finalize_hook) ();
/* In tree.c */ /* In tree.c */
extern char *perm_calloc PROTO((int, long)); extern char *perm_calloc PROTO((int, long));
extern tree get_set_constructor_bits PROTO((tree, char*, int));
extern tree get_set_constructor_words PROTO((tree,
HOST_WIDE_INT*, int));
/* In stmt.c */ /* In stmt.c */

File diff suppressed because it is too large Load diff

View file

@ -5,10 +5,10 @@
LIB= gcc LIB= gcc
INSTALL_PIC_ARCHIVE= yes INSTALL_PIC_ARCHIVE= yes
SHLIB_MAJOR= 26 SHLIB_MAJOR= 26
SHLIB_MINOR= 0 SHLIB_MINOR= 1
LIB1OBJS= _mulsi3.o _udivsi3.o _divsi3.o _umodsi3.o _modsi3.o _lshrsi3.o _lshlsi3.o _ashrsi3.o _ashlsi3.o _divdf3.o _muldf3.o _negdf2.o _adddf3.o _subdf3.o _fixdfsi.o _fixsfsi.o _floatsidf.o _floatsisf.o _truncdfsf2.o _extendsfdf2.o _addsf3.o _negsf2.o _subsf3.o _mulsf3.o _divsf3.o _eqdf2.o _nedf2.o _gtdf2.o _gedf2.o _ltdf2.o _ledf2.o _eqsf2.o _nesf2.o _gtsf2.o _gesf2.o _ltsf2.o _lesf2.o LIB1OBJS= _mulsi3.o _udivsi3.o _divsi3.o _umodsi3.o _modsi3.o _lshrsi3.o _lshlsi3.o _ashrsi3.o _ashlsi3.o _divdf3.o _muldf3.o _negdf2.o _adddf3.o _subdf3.o _fixdfsi.o _fixsfsi.o _floatsidf.o _floatsisf.o _truncdfsf2.o _extendsfdf2.o _addsf3.o _negsf2.o _subsf3.o _mulsf3.o _divsf3.o _eqdf2.o _nedf2.o _gtdf2.o _gedf2.o _ltdf2.o _ledf2.o _eqsf2.o _nesf2.o _gtsf2.o _gesf2.o _ltsf2.o _lesf2.o
LIB2OBJS= _muldi3.o _divdi3.o _moddi3.o _udivdi3.o _umoddi3.o _negdi2.o _lshrdi3.o _lshldi3.o _ashldi3.o _ashrdi3.o _ffsdi2.o _udiv_w_sdiv.o _udivmoddi4.o _cmpdi2.o _ucmpdi2.o _floatdidf.o _floatdisf.o _fixunsdfsi.o _fixunssfsi.o _fixunsdfdi.o _fixdfdi.o _fixunssfdi.o _fixsfdi.o _fixxfdi.o _fixunsxfdi.o _floatdixf.o _fixunsxfsi.o _fixtfdi.o _fixunstfdi.o _floatditf.o __gcc_bcmp.o _varargs.o _eprintf.o _op_new.o _op_vnew.o _new_handler.o _op_delete.o _op_vdel.o _bb.o _shtab.o _clear_cache.o _trampoline.o __main.o _exit.o _ctors.o LIB2OBJS= _muldi3.o _divdi3.o _moddi3.o _udivdi3.o _umoddi3.o _negdi2.o _lshrdi3.o _lshldi3.o _ashldi3.o _ashrdi3.o _ffsdi2.o _udiv_w_sdiv.o _udivmoddi4.o _cmpdi2.o _ucmpdi2.o _floatdidf.o _floatdisf.o _fixunsdfsi.o _fixunssfsi.o _fixunsdfdi.o _fixdfdi.o _fixunssfdi.o _fixsfdi.o _fixxfdi.o _fixunsxfdi.o _floatdixf.o _fixunsxfsi.o _fixtfdi.o _fixunstfdi.o _floatditf.o __gcc_bcmp.o _varargs.o _eprintf.o _op_new.o _op_vnew.o _new_handler.o _op_delete.o _op_vdel.o _bb.o _shtab.o _clear_cache.o _trampoline.o __main.o _exit.o _ctors.o _eh.o _pure.o
OBJS= ${LIB1OBJS} ${LIB2OBJS} OBJS= ${LIB1OBJS} ${LIB2OBJS}
LIB1SOBJS=${LIB1OBJS:.o=.so} LIB1SOBJS=${LIB1OBJS:.o=.so}

View file

@ -1428,6 +1428,7 @@ BLOCK_PROFILER_CODE
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h> #include <stdio.h>
char *ctime ();
#ifdef HAVE_ATEXIT #ifdef HAVE_ATEXIT
extern void atexit (void (*) (void)); extern void atexit (void (*) (void));
@ -1995,21 +1996,9 @@ __do_global_dtors ()
#ifdef DO_GLOBAL_DTORS_BODY #ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY; DO_GLOBAL_DTORS_BODY;
#else #else
unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0]; func_ptr *p;
unsigned i; for (p = __DTOR_LIST__ + 1; *p; )
(*p++) ();
/* Some systems place the number of pointers
in the first word of the table.
On other systems, that word is -1.
In all cases, the table is null-terminated. */
/* If the length is not recorded, count up to the null. */
if (nptrs == -1)
for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
/* GNU LD format. */
for (i = nptrs; i >= 1; i--)
__DTOR_LIST__[i] ();
#endif #endif
} }
@ -2149,3 +2138,162 @@ func_ptr __CTOR_LIST__[2];
#include "gbl-ctors.h" #include "gbl-ctors.h"
func_ptr __DTOR_LIST__[2]; func_ptr __DTOR_LIST__[2];
#endif #endif
#ifdef L_eh
typedef struct {
void *start;
void *end;
void *exception_handler;
} exception_table;
struct exception_table_node {
exception_table *table;
void *start;
void *end;
struct exception_table_node *next;
};
static int except_table_pos = 0;
static void *except_pc = (void *)0;
static struct exception_table_node *exception_table_list = 0;
static exception_table *
find_exception_table (pc)
void* pc;
{
register struct exception_table_node *table = exception_table_list;
for ( ; table != 0; table = table->next)
{
if (table->start <= pc && table->end > pc)
return table->table;
}
return 0;
}
/* this routine takes a pc, and the address of the exception handler associated
with the closest exception table handler entry associated with that PC,
or 0 if there are no table entries the PC fits in. The algorithm works
something like this:
while(current_entry exists) {
if(current_entry.start < pc )
current_entry = next_entry;
else {
if(prev_entry.start <= pc && prev_entry.end > pc) {
save pointer to prev_entry;
return prev_entry.exception_handler;
}
else return 0;
}
}
return 0;
Assuming a correctly sorted table (ascending order) this routine should
return the tighest match...
In the advent of a tie, we have to give the last entry, as it represents
an inner block.
*/
void *
__find_first_exception_table_match(pc)
void *pc;
{
exception_table *table = find_exception_table (pc);
int pos = 0;
int best = 0;
if (table == 0)
return (void*)0;
#if 0
printf("find_first_exception_table_match(): pc = %x!\n",pc);
#endif
except_pc = pc;
#if 0
/* We can't do this yet, as we don't know that the table is sorted. */
do {
++pos;
if (table[pos].start > except_pc)
/* found the first table[pos].start > except_pc, so the previous
entry better be the one we want! */
break;
} while(table[pos].exception_handler != (void*)-1);
--pos;
if (table[pos].start <= except_pc && table[pos].end > except_pc)
{
except_table_pos = pos;
#if 0
printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
#endif
return table[pos].exception_handler;
}
#else
while (table[++pos].exception_handler != (void*)-1) {
if (table[pos].start <= except_pc && table[pos].end > except_pc)
{
/* This can apply. Make sure it is better or as good as the previous
best. */
/* The best one ends first. */
if (best == 0 || (table[pos].end <= table[best].end
/* The best one starts last. */
&& table[pos].start >= table[best].start))
best = pos;
}
}
if (best != 0)
return table[best].exception_handler;
#endif
#if 0
printf("find_first_eh_table_match(): else: returning NULL!\n");
#endif
return (void*)0;
}
int
__throw_type_match (const char *catch_type, const char *throw_type)
{
#if 0
printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
catch_type, throw_type);
#endif
return strcmp (catch_type, throw_type);
}
void
__register_exceptions (exception_table *table)
{
struct exception_table_node *node = (struct exception_table_node*)
malloc (sizeof (struct exception_table_node));
exception_table *range = table + 1;
node->table = table;
/* This look can be optimized away either if the table
is sorted, or if we pass in extra parameters. */
node->start = range->start;
node->end = range->end;
for (range++ ; range->start != (void*)(-1); range++)
{
if (range->start < node->start)
node->start = range->start;
if (range->end < node->end)
node->end = range->end;
}
node->next = exception_table_list;
exception_table_list = node;
}
#endif /* L_eh */
#ifdef L_pure
#define MESSAGE "pure virtual method called\n"
void
__pure_virtual ()
{
write (2, MESSAGE, sizeof (MESSAGE) - 1);
_exit (-1);
}
#endif